which-url 0.0.6 → 0.0.8
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.
- package/README.md +64 -11
- package/dist/env-var.d.ts +1 -1
- package/dist/env-var.d.ts.map +1 -1
- package/dist/env.d.ts +1 -1
- package/dist/env.d.ts.map +1 -1
- package/dist/index.d.ts +30 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +79 -39
- package/dist/resolve.d.ts +2 -2
- package/dist/resolve.d.ts.map +1 -1
- package/dist/types.d.ts +41 -14
- package/dist/types.d.ts.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -20,7 +20,7 @@ Preview https://myapp-git-feat.vercel.app "preview"
|
|
|
20
20
|
Production https://myapp.com "production"
|
|
21
21
|
```
|
|
22
22
|
|
|
23
|
-
Works across environments (local, preview, production),
|
|
23
|
+
Works across environments (local, preview, production), browser bundles, Node/Bun servers, and edge runtimes that expose compatible env vars through `process.env` or build-time public env replacement.
|
|
24
24
|
|
|
25
25
|
The default export gives you everything as an object:
|
|
26
26
|
|
|
@@ -85,7 +85,31 @@ Reads environment variables that hosting providers set automatically:
|
|
|
85
85
|
3. `window.location.origin` (browser fallback)
|
|
86
86
|
4. `http://localhost:${PORT || 3000}` (development fallback)
|
|
87
87
|
|
|
88
|
-
|
|
88
|
+
When you call `createUrl({ env })`, the passed object replaces `process.env` as the source for steps 1–2.
|
|
89
|
+
|
|
90
|
+
If nothing is detected in production, the default singleton returns empty URL strings so imports stay safe in tests, client bundles, and build tools. Call `createUrl()` directly when a missing URL should throw.
|
|
91
|
+
|
|
92
|
+
## Strict mode with `createUrl()`
|
|
93
|
+
|
|
94
|
+
Use the default export or named constants for convenience:
|
|
95
|
+
|
|
96
|
+
```typescript
|
|
97
|
+
import { origin } from 'which-url'
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
Use `createUrl()` for production-critical configuration like auth, CORS, emails, and webhooks:
|
|
101
|
+
|
|
102
|
+
```typescript
|
|
103
|
+
import { createUrl } from 'which-url'
|
|
104
|
+
|
|
105
|
+
const appUrl = createUrl()
|
|
106
|
+
|
|
107
|
+
auth({ baseURL: appUrl.origin })
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
`createUrl()` resolves fresh environment values when called. If no URL can be detected in production, it throws with instructions to set `APP_URL`.
|
|
111
|
+
|
|
112
|
+
For runtimes that pass env as an argument (e.g. Cloudflare Workers), call `createUrl({ env })` and the passed object replaces `process.env` for that resolution. See [Cloudflare Workers](#cloudflare-workers) below.
|
|
89
113
|
|
|
90
114
|
## Override with `APP_URL`
|
|
91
115
|
|
|
@@ -160,6 +184,8 @@ Zero config — [portless](https://portless.sh) sets `PORTLESS_URL` and `which-u
|
|
|
160
184
|
origin → https://myapp.localhost
|
|
161
185
|
```
|
|
162
186
|
|
|
187
|
+
When sharing via Tailscale (`portless run --tailscale`), `PORTLESS_TAILSCALE_URL` takes priority so `origin` returns the publicly-reachable URL.
|
|
188
|
+
|
|
163
189
|
### Tunnels (ngrok, Cloudflare Tunnel)
|
|
164
190
|
|
|
165
191
|
Tunnel URLs can't be auto-detected — they're external to the app process. Set `APP_URL`:
|
|
@@ -170,29 +196,54 @@ APP_URL=https://abc123.ngrok-free.app npm run dev
|
|
|
170
196
|
|
|
171
197
|
### Cloudflare Workers
|
|
172
198
|
|
|
173
|
-
Cloudflare Workers
|
|
199
|
+
Cloudflare Workers pass config through the `env` argument to `fetch`, not `process.env`. Pass it to `createUrl({ env })`:
|
|
200
|
+
|
|
201
|
+
```typescript
|
|
202
|
+
import { createUrl } from "which-url"
|
|
203
|
+
|
|
204
|
+
export default {
|
|
205
|
+
async fetch(request: Request, env: Env) {
|
|
206
|
+
const appUrl = createUrl({ env })
|
|
207
|
+
|
|
208
|
+
return Response.json({ origin: appUrl.origin, env: appUrl.env })
|
|
209
|
+
},
|
|
210
|
+
}
|
|
211
|
+
```
|
|
174
212
|
|
|
175
213
|
```toml
|
|
214
|
+
# wrangler.toml
|
|
176
215
|
[vars]
|
|
177
|
-
APP_URL = "https://
|
|
216
|
+
APP_URL = "https://api.example.com"
|
|
217
|
+
APP_ENV = "production"
|
|
178
218
|
```
|
|
179
219
|
|
|
180
|
-
|
|
220
|
+
Non-string bindings (KV, Durable Objects, R2, service bindings) are ignored automatically — only string `[vars]` participate in URL detection.
|
|
221
|
+
|
|
222
|
+
> ⚠️ The default singleton (`import appUrl from "which-url"`) and named exports (`origin`, `env`, etc.) resolve at **module load**, before your `fetch` handler runs. On Workers they will not see your `[vars]`. Use `createUrl({ env })` from inside your handler.
|
|
223
|
+
|
|
224
|
+
If you're on `nodejs_compat` and prefer `process.env`, the default singleton works too — but `createUrl({ env })` is the runtime-native path and doesn't require the compat flag.
|
|
181
225
|
|
|
182
226
|
### Debugging
|
|
183
227
|
|
|
184
228
|
```typescript
|
|
185
|
-
import
|
|
229
|
+
import appUrl from 'which-url'
|
|
186
230
|
|
|
187
|
-
console.log(debug)
|
|
188
|
-
// "
|
|
231
|
+
console.log(appUrl.debug)
|
|
232
|
+
// "[provider:vercel] url=myapp.com | env=production (vercel:production)"
|
|
233
|
+
// "[override] APP_URL=https://custom.com | env=production (NODE_ENV=production)"
|
|
234
|
+
// "[portless] PORTLESS_URL=https://myapp.localhost | env=local (NODE_ENV=development)"
|
|
235
|
+
// "[fallback] PORT=3004 | env=local (NODE_ENV=development)"
|
|
189
236
|
```
|
|
190
237
|
|
|
191
238
|
## API
|
|
192
239
|
|
|
193
240
|
### Default export
|
|
194
241
|
|
|
195
|
-
An object with URL properties and environment helpers.
|
|
242
|
+
An import-safe singleton object with URL properties and environment helpers. It resolves once when the package is imported.
|
|
243
|
+
|
|
244
|
+
### `createUrl()`
|
|
245
|
+
|
|
246
|
+
Strict resolver function. It resolves when called and throws if no URL can be detected.
|
|
196
247
|
|
|
197
248
|
### Named exports
|
|
198
249
|
|
|
@@ -206,11 +257,13 @@ An object with URL properties and environment helpers.
|
|
|
206
257
|
| `port` | `string` | `""` or `"3000"` |
|
|
207
258
|
| `env` | `AppEnv` | `"production"` \| `"preview"` \| `"local"` |
|
|
208
259
|
| `platform` | `Platform` | `"vercel"` \| `"netlify"` \| ... \| `null` |
|
|
209
|
-
| `
|
|
210
|
-
| `debug` | `string` | `"platform=vercel \| source=provider \| url=https://myapp.com \| env=production"` |
|
|
260
|
+
| `debug`* | `string` | `"[provider:vercel] url=myapp.com \| env=production (vercel:production)"` |
|
|
211
261
|
| `isProduction` | `boolean` | |
|
|
212
262
|
| `isPreview` | `boolean` | |
|
|
213
263
|
| `isLocal` | `boolean` | |
|
|
264
|
+
| `createUrl` | `(options?: { env?: Record<string, unknown> }) => WhichUrlWithDebug` | strict resolver |
|
|
265
|
+
|
|
266
|
+
\* `debug` is non-enumerable on the default export and objects returned by `createUrl()` — excluded from `JSON.stringify` to avoid React hydration mismatches. It is also available as a named export.
|
|
214
267
|
|
|
215
268
|
## License
|
|
216
269
|
|
package/dist/env-var.d.ts
CHANGED
|
@@ -7,5 +7,5 @@
|
|
|
7
7
|
* falls back to dynamic lookup for test/server compatibility.
|
|
8
8
|
*/
|
|
9
9
|
export declare function getVar(env: Record<string, string | undefined>, name: string): string | undefined;
|
|
10
|
-
export declare function getEnv(): Record<string, string | undefined>;
|
|
10
|
+
export declare function getEnv(override?: Record<string, unknown>): Record<string, string | undefined>;
|
|
11
11
|
//# sourceMappingURL=env-var.d.ts.map
|
package/dist/env-var.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"env-var.d.ts","sourceRoot":"","sources":["../src/env-var.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"env-var.d.ts","sourceRoot":"","sources":["../src/env-var.ts"],"names":[],"mappings":"AAkGA;;;;;;;GAOG;AACH,wBAAgB,MAAM,CACpB,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,EACvC,IAAI,EAAE,MAAM,GACX,MAAM,GAAG,SAAS,CA4BpB;AAED,wBAAgB,MAAM,CACpB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GACjC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAQpC"}
|
package/dist/env.d.ts
CHANGED
package/dist/env.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"env.d.ts","sourceRoot":"","sources":["../src/env.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,SAAS,CAAA;AAIrC,MAAM,WAAW,SAAS;IACxB,GAAG,EAAE,MAAM,CAAA;IACX,UAAU,EAAE,MAAM,CAAA;CACnB;AAED,wBAAgB,UAAU,
|
|
1
|
+
{"version":3,"file":"env.d.ts","sourceRoot":"","sources":["../src/env.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,SAAS,CAAA;AAIrC,MAAM,WAAW,SAAS;IACxB,GAAG,EAAE,MAAM,CAAA;IACX,UAAU,EAAE,MAAM,CAAA;CACnB;AAED,wBAAgB,UAAU,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAyB3E"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,16 +1,43 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
declare
|
|
1
|
+
import type { WhichUrlWithDebug, AppEnv, Platform, CreateUrlOptions } from "./types";
|
|
2
|
+
export declare function createUrl(options?: CreateUrlOptions): WhichUrlWithDebug;
|
|
3
|
+
declare let _resolved: WhichUrlWithDebug;
|
|
4
|
+
/** Full URL including protocol — `"https://myapp.com"` */
|
|
3
5
|
export declare const href: string;
|
|
6
|
+
/** Full origin — `"https://myapp.com"` (same as href) */
|
|
4
7
|
export declare const origin: string;
|
|
8
|
+
/** Hostname without port — `"myapp.com"` */
|
|
5
9
|
export declare const hostname: string;
|
|
10
|
+
/** Hostname with port — `"myapp.com"` or `"localhost:3000"` */
|
|
6
11
|
export declare const host: string;
|
|
12
|
+
/** Protocol with colon — `"https:"` or `"http:"` */
|
|
7
13
|
export declare const protocol: string;
|
|
14
|
+
/** Port string — `""` for default ports, `"3000"` for custom */
|
|
8
15
|
export declare const port: string;
|
|
16
|
+
/** Current environment — `"production"`, `"preview"`, or `"local"` */
|
|
9
17
|
export declare const env: AppEnv;
|
|
18
|
+
/** Detected hosting platform — `"vercel"`, `"netlify"`, etc. or `null` */
|
|
10
19
|
export declare const platform: Platform;
|
|
20
|
+
/** Resolution debug string. */
|
|
21
|
+
export declare const debug: string;
|
|
22
|
+
/** `true` when running in production */
|
|
11
23
|
export declare const isProduction: boolean;
|
|
24
|
+
/** `true` when running in a preview/staging deployment */
|
|
12
25
|
export declare const isPreview: boolean;
|
|
26
|
+
/** `true` when running locally (development) */
|
|
13
27
|
export declare const isLocal: boolean;
|
|
28
|
+
/**
|
|
29
|
+
* Auto-detected app URL with environment metadata.
|
|
30
|
+
*
|
|
31
|
+
* @example
|
|
32
|
+
* ```ts
|
|
33
|
+
* import appUrl from 'which-url'
|
|
34
|
+
*
|
|
35
|
+
* appUrl.origin // "https://myapp.com"
|
|
36
|
+
* appUrl.env // "production"
|
|
37
|
+
* appUrl.platform // "vercel"
|
|
38
|
+
* appUrl.debug // "[provider:vercel] url=myapp.com | env=production (vercel:production)"
|
|
39
|
+
* ```
|
|
40
|
+
*/
|
|
14
41
|
export default _resolved;
|
|
15
|
-
export type { WhichUrl, AppEnv, Platform };
|
|
42
|
+
export type { WhichUrl, WhichUrlWithDebug, AppEnv, Platform, PlatformName, CreateUrlOptions } from "./types";
|
|
16
43
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,EAAE,QAAQ,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAA;AAYpF,wBAAgB,SAAS,CAAC,OAAO,CAAC,EAAE,gBAAgB,GAAG,iBAAiB,CAwBvE;AAkCD,QAAA,IAAI,SAAS,EAAE,iBAAiB,CAAA;AAOhC,0DAA0D;AAC1D,eAAO,MAAM,IAAI,EAAE,MAAuB,CAAA;AAC1C,yDAAyD;AACzD,eAAO,MAAM,MAAM,EAAE,MAAyB,CAAA;AAC9C,4CAA4C;AAC5C,eAAO,MAAM,QAAQ,EAAE,MAA2B,CAAA;AAClD,+DAA+D;AAC/D,eAAO,MAAM,IAAI,EAAE,MAAuB,CAAA;AAC1C,oDAAoD;AACpD,eAAO,MAAM,QAAQ,EAAE,MAA2B,CAAA;AAClD,gEAAgE;AAChE,eAAO,MAAM,IAAI,EAAE,MAAuB,CAAA;AAC1C,sEAAsE;AACtE,eAAO,MAAM,GAAG,EAAE,MAAsB,CAAA;AACxC,0EAA0E;AAC1E,eAAO,MAAM,QAAQ,EAAE,QAA6B,CAAA;AACpD,+BAA+B;AAC/B,eAAO,MAAM,KAAK,EAAE,MAAwB,CAAA;AAC5C,wCAAwC;AACxC,eAAO,MAAM,YAAY,EAAE,OAAgC,CAAA;AAC3D,0DAA0D;AAC1D,eAAO,MAAM,SAAS,EAAE,OAA6B,CAAA;AACrD,gDAAgD;AAChD,eAAO,MAAM,OAAO,EAAE,OAA2B,CAAA;AAEjD;;;;;;;;;;;;GAYG;AACH,eAAe,SAAS,CAAA;AAExB,YAAY,EAAE,QAAQ,EAAE,iBAAiB,EAAE,MAAM,EAAE,QAAQ,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAA"}
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,12 @@
|
|
|
1
1
|
// src/env-var.ts
|
|
2
|
+
var ENV_VARS = [
|
|
3
|
+
"VERCEL_ENV",
|
|
4
|
+
"VERCEL_URL",
|
|
5
|
+
"VERCEL_BRANCH_URL",
|
|
6
|
+
"VERCEL_PROJECT_PRODUCTION_URL",
|
|
7
|
+
"APP_URL",
|
|
8
|
+
"APP_ENV"
|
|
9
|
+
];
|
|
2
10
|
function readStatic(name) {
|
|
3
11
|
switch (name) {
|
|
4
12
|
case "VERCEL_ENV":
|
|
@@ -13,13 +21,17 @@ function readStatic(name) {
|
|
|
13
21
|
return process.env.APP_URL || process.env.NEXT_PUBLIC_APP_URL || process.env.NUXT_ENV_APP_URL || process.env.VITE_APP_URL || process.env.PUBLIC_APP_URL || process.env.REACT_APP_APP_URL || process.env.GATSBY_APP_URL || process.env.VUE_APP_APP_URL || process.env.REDWOOD_ENV_APP_URL || process.env.SANITY_STUDIO_APP_URL || undefined;
|
|
14
22
|
case "APP_ENV":
|
|
15
23
|
return process.env.APP_ENV || process.env.NEXT_PUBLIC_APP_ENV || process.env.NUXT_ENV_APP_ENV || process.env.VITE_APP_ENV || process.env.PUBLIC_APP_ENV || process.env.REACT_APP_APP_ENV || process.env.GATSBY_APP_ENV || process.env.VUE_APP_APP_ENV || process.env.REDWOOD_ENV_APP_ENV || process.env.SANITY_STUDIO_APP_ENV || undefined;
|
|
24
|
+
default:
|
|
25
|
+
return;
|
|
16
26
|
}
|
|
17
27
|
}
|
|
18
28
|
function getVar(env, name) {
|
|
19
29
|
if (typeof process !== "undefined" && process?.env && env === process.env) {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
30
|
+
if (ENV_VARS.includes(name)) {
|
|
31
|
+
const val = readStatic(name);
|
|
32
|
+
if (val)
|
|
33
|
+
return val;
|
|
34
|
+
}
|
|
23
35
|
}
|
|
24
36
|
const PREFIXES = [
|
|
25
37
|
"",
|
|
@@ -40,12 +52,24 @@ function getVar(env, name) {
|
|
|
40
52
|
}
|
|
41
53
|
return;
|
|
42
54
|
}
|
|
43
|
-
function getEnv() {
|
|
55
|
+
function getEnv(override) {
|
|
56
|
+
if (override !== undefined) {
|
|
57
|
+
return filterStrings(override);
|
|
58
|
+
}
|
|
44
59
|
if (typeof process !== "undefined" && process?.env) {
|
|
45
60
|
return process.env;
|
|
46
61
|
}
|
|
47
62
|
return {};
|
|
48
63
|
}
|
|
64
|
+
function filterStrings(source) {
|
|
65
|
+
const out = {};
|
|
66
|
+
for (const key in source) {
|
|
67
|
+
const value = source[key];
|
|
68
|
+
if (typeof value === "string")
|
|
69
|
+
out[key] = value;
|
|
70
|
+
}
|
|
71
|
+
return out;
|
|
72
|
+
}
|
|
49
73
|
|
|
50
74
|
// src/providers.ts
|
|
51
75
|
var providers = [
|
|
@@ -144,13 +168,17 @@ function normalizeUrl(raw) {
|
|
|
144
168
|
}
|
|
145
169
|
|
|
146
170
|
// src/resolve.ts
|
|
147
|
-
function resolveUrl() {
|
|
148
|
-
const env = getEnv();
|
|
171
|
+
function resolveUrl(envOverride) {
|
|
172
|
+
const env = getEnv(envOverride);
|
|
149
173
|
const override = getVar(env, "APP_URL");
|
|
150
174
|
if (override)
|
|
151
175
|
return { url: normalizeUrl(override), debugLabel: `[override] APP_URL=${override}` };
|
|
152
|
-
if (env.
|
|
176
|
+
if (env.PORTLESS_TAILSCALE_URL) {
|
|
177
|
+
return { url: env.PORTLESS_TAILSCALE_URL, debugLabel: `[portless:tailscale] PORTLESS_TAILSCALE_URL=${env.PORTLESS_TAILSCALE_URL}` };
|
|
178
|
+
}
|
|
179
|
+
if (env.PORTLESS_URL) {
|
|
153
180
|
return { url: env.PORTLESS_URL, debugLabel: `[portless] PORTLESS_URL=${env.PORTLESS_URL}` };
|
|
181
|
+
}
|
|
154
182
|
for (const p of providers) {
|
|
155
183
|
if (p.detect(env)) {
|
|
156
184
|
const url = p.resolveUrl(env);
|
|
@@ -168,8 +196,8 @@ function resolveUrl() {
|
|
|
168
196
|
}
|
|
169
197
|
throw new Error("which-url: Cannot detect app URL. Set APP_URL environment variable.");
|
|
170
198
|
}
|
|
171
|
-
function resolvePlatform() {
|
|
172
|
-
const env = getEnv();
|
|
199
|
+
function resolvePlatform(envOverride) {
|
|
200
|
+
const env = getEnv(envOverride);
|
|
173
201
|
for (const p of providers) {
|
|
174
202
|
if (p.detect(env)) {
|
|
175
203
|
return p.name;
|
|
@@ -180,8 +208,8 @@ function resolvePlatform() {
|
|
|
180
208
|
|
|
181
209
|
// src/env.ts
|
|
182
210
|
var validEnvs = ["production", "preview", "local"];
|
|
183
|
-
function resolveEnv() {
|
|
184
|
-
const env = getEnv();
|
|
211
|
+
function resolveEnv(envOverride) {
|
|
212
|
+
const env = getEnv(envOverride);
|
|
185
213
|
const appEnv = getVar(env, "APP_ENV");
|
|
186
214
|
if (appEnv && validEnvs.includes(appEnv)) {
|
|
187
215
|
return { env: appEnv, debugLabel: `APP_ENV=${appEnv}` };
|
|
@@ -200,11 +228,20 @@ function resolveEnv() {
|
|
|
200
228
|
}
|
|
201
229
|
|
|
202
230
|
// src/index.ts
|
|
203
|
-
function
|
|
204
|
-
|
|
231
|
+
function makeDebugNonEnumerable(result) {
|
|
232
|
+
Object.defineProperty(result, "debug", {
|
|
233
|
+
value: result.debug,
|
|
234
|
+
enumerable: false,
|
|
235
|
+
configurable: false
|
|
236
|
+
});
|
|
237
|
+
return result;
|
|
238
|
+
}
|
|
239
|
+
function createUrl(options) {
|
|
240
|
+
const envOverride = options?.env;
|
|
241
|
+
const { url, debugLabel: urlDebug } = resolveUrl(envOverride);
|
|
205
242
|
const parsed = new URL(url);
|
|
206
|
-
const { env, debugLabel: envDebug } = resolveEnv();
|
|
207
|
-
const platform = resolvePlatform();
|
|
243
|
+
const { env, debugLabel: envDebug } = resolveEnv(envOverride);
|
|
244
|
+
const platform = resolvePlatform(envOverride);
|
|
208
245
|
const debug = `${urlDebug} | env=${env} (${envDebug})`;
|
|
209
246
|
const result = {
|
|
210
247
|
href: parsed.origin,
|
|
@@ -220,18 +257,17 @@ function resolve() {
|
|
|
220
257
|
isPreview: env === "preview",
|
|
221
258
|
isLocal: env === "local"
|
|
222
259
|
};
|
|
223
|
-
|
|
224
|
-
value: debug,
|
|
225
|
-
enumerable: false,
|
|
226
|
-
configurable: false
|
|
227
|
-
});
|
|
228
|
-
return result;
|
|
260
|
+
return makeDebugNonEnumerable(result);
|
|
229
261
|
}
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
262
|
+
function createFallback(error) {
|
|
263
|
+
const message = error instanceof Error ? error.message : "resolution failed";
|
|
264
|
+
let resolvedEnv = "local";
|
|
265
|
+
let envDebug = "default";
|
|
266
|
+
try {
|
|
267
|
+
const result = resolveEnv();
|
|
268
|
+
resolvedEnv = result.env;
|
|
269
|
+
envDebug = result.debugLabel;
|
|
270
|
+
} catch {}
|
|
235
271
|
const fallback = {
|
|
236
272
|
href: "",
|
|
237
273
|
origin: "",
|
|
@@ -239,19 +275,20 @@ try {
|
|
|
239
275
|
host: "",
|
|
240
276
|
protocol: "",
|
|
241
277
|
port: "",
|
|
242
|
-
env:
|
|
243
|
-
platform:
|
|
244
|
-
debug:
|
|
245
|
-
isProduction:
|
|
246
|
-
isPreview:
|
|
247
|
-
isLocal:
|
|
278
|
+
env: resolvedEnv,
|
|
279
|
+
platform: resolvePlatform(),
|
|
280
|
+
debug: `[error] ${message} | env=${resolvedEnv} (${envDebug})`,
|
|
281
|
+
isProduction: resolvedEnv === "production",
|
|
282
|
+
isPreview: resolvedEnv === "preview",
|
|
283
|
+
isLocal: resolvedEnv === "local"
|
|
248
284
|
};
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
285
|
+
return makeDebugNonEnumerable(fallback);
|
|
286
|
+
}
|
|
287
|
+
var _resolved;
|
|
288
|
+
try {
|
|
289
|
+
_resolved = createUrl();
|
|
290
|
+
} catch (e) {
|
|
291
|
+
_resolved = createFallback(e);
|
|
255
292
|
}
|
|
256
293
|
var href = _resolved.href;
|
|
257
294
|
var origin = _resolved.origin;
|
|
@@ -261,6 +298,7 @@ var protocol = _resolved.protocol;
|
|
|
261
298
|
var port = _resolved.port;
|
|
262
299
|
var env = _resolved.env;
|
|
263
300
|
var platform = _resolved.platform;
|
|
301
|
+
var debug = _resolved.debug;
|
|
264
302
|
var isProduction = _resolved.isProduction;
|
|
265
303
|
var isPreview = _resolved.isPreview;
|
|
266
304
|
var isLocal = _resolved.isLocal;
|
|
@@ -277,5 +315,7 @@ export {
|
|
|
277
315
|
hostname,
|
|
278
316
|
host,
|
|
279
317
|
env,
|
|
280
|
-
src_default as default
|
|
318
|
+
src_default as default,
|
|
319
|
+
debug,
|
|
320
|
+
createUrl
|
|
281
321
|
};
|
package/dist/resolve.d.ts
CHANGED
|
@@ -3,6 +3,6 @@ export interface ResolveResult {
|
|
|
3
3
|
url: string;
|
|
4
4
|
debugLabel: string;
|
|
5
5
|
}
|
|
6
|
-
export declare function resolveUrl(): ResolveResult;
|
|
7
|
-
export declare function resolvePlatform(): Platform;
|
|
6
|
+
export declare function resolveUrl(envOverride?: Record<string, unknown>): ResolveResult;
|
|
7
|
+
export declare function resolvePlatform(envOverride?: Record<string, unknown>): Platform;
|
|
8
8
|
//# sourceMappingURL=resolve.d.ts.map
|
package/dist/resolve.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resolve.d.ts","sourceRoot":"","sources":["../src/resolve.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAA;AAEvC,MAAM,WAAW,aAAa;IAC5B,GAAG,EAAE,MAAM,CAAA;IACX,UAAU,EAAE,MAAM,CAAA;CACnB;AAED,wBAAgB,UAAU,
|
|
1
|
+
{"version":3,"file":"resolve.d.ts","sourceRoot":"","sources":["../src/resolve.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAA;AAEvC,MAAM,WAAW,aAAa;IAC5B,GAAG,EAAE,MAAM,CAAA;IACX,UAAU,EAAE,MAAM,CAAA;CACnB;AAED,wBAAgB,UAAU,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,aAAa,CAuC/E;AAED,wBAAgB,eAAe,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,QAAQ,CAQ/E"}
|
package/dist/types.d.ts
CHANGED
|
@@ -1,21 +1,48 @@
|
|
|
1
1
|
export type AppEnv = "production" | "preview" | "local";
|
|
2
|
-
export type
|
|
2
|
+
export type PlatformName = "vercel" | "netlify" | "cloudflare" | "railway" | "fly" | "render" | "digitalocean" | "heroku";
|
|
3
|
+
export type Platform = PlatformName | null;
|
|
3
4
|
export interface WhichUrl {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
5
|
+
/** Full URL including protocol — `"https://myapp.com"` */
|
|
6
|
+
readonly href: string;
|
|
7
|
+
/** Full origin — `"https://myapp.com"` (same as href) */
|
|
8
|
+
readonly origin: string;
|
|
9
|
+
/** Hostname without port — `"myapp.com"` */
|
|
10
|
+
readonly hostname: string;
|
|
11
|
+
/** Hostname with port — `"myapp.com"` or `"localhost:3000"` */
|
|
12
|
+
readonly host: string;
|
|
13
|
+
/** Protocol with colon — `"https:"` or `"http:"` */
|
|
14
|
+
readonly protocol: string;
|
|
15
|
+
/** Port string — `""` for default ports, `"3000"` for custom */
|
|
16
|
+
readonly port: string;
|
|
17
|
+
/** Current environment — `"production"`, `"preview"`, or `"local"` */
|
|
18
|
+
readonly env: AppEnv;
|
|
19
|
+
/** Detected hosting platform — `"vercel"`, `"netlify"`, etc. or `null` */
|
|
20
|
+
readonly platform: Platform;
|
|
21
|
+
/** `true` when running in production */
|
|
22
|
+
readonly isProduction: boolean;
|
|
23
|
+
/** `true` when running in a preview/staging deployment */
|
|
24
|
+
readonly isPreview: boolean;
|
|
25
|
+
/** `true` when running locally (development) */
|
|
26
|
+
readonly isLocal: boolean;
|
|
27
|
+
}
|
|
28
|
+
export interface WhichUrlWithDebug extends WhichUrl {
|
|
29
|
+
/** Resolution debug string (non-enumerable — excluded from JSON.stringify and object spread). */
|
|
30
|
+
readonly debug: string;
|
|
31
|
+
}
|
|
32
|
+
export interface CreateUrlOptions {
|
|
33
|
+
/**
|
|
34
|
+
* Runtime environment source. Pass this when `process.env` isn't available
|
|
35
|
+
* or doesn't contain your config — e.g. on Cloudflare Workers, where the
|
|
36
|
+
* Worker `env` argument carries `[vars]` from `wrangler.toml`.
|
|
37
|
+
*
|
|
38
|
+
* When provided, `process.env` is ignored entirely. Only string-valued
|
|
39
|
+
* entries participate in URL detection — non-string Workers bindings
|
|
40
|
+
* (KV namespaces, Durable Objects, R2 buckets, service bindings) are dropped.
|
|
41
|
+
*/
|
|
42
|
+
env?: Record<string, unknown>;
|
|
16
43
|
}
|
|
17
44
|
export interface ProviderDetector {
|
|
18
|
-
name:
|
|
45
|
+
name: PlatformName;
|
|
19
46
|
detect: (env: Record<string, string | undefined>) => boolean;
|
|
20
47
|
resolveUrl: (env: Record<string, string | undefined>) => string | null;
|
|
21
48
|
resolveEnv: (env: Record<string, string | undefined>) => AppEnv;
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,MAAM,GAAG,YAAY,GAAG,SAAS,GAAG,OAAO,CAAA;AAEvD,MAAM,MAAM,
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,MAAM,GAAG,YAAY,GAAG,SAAS,GAAG,OAAO,CAAA;AAEvD,MAAM,MAAM,YAAY,GACpB,QAAQ,GACR,SAAS,GACT,YAAY,GACZ,SAAS,GACT,KAAK,GACL,QAAQ,GACR,cAAc,GACd,QAAQ,CAAA;AAEZ,MAAM,MAAM,QAAQ,GAAG,YAAY,GAAG,IAAI,CAAA;AAE1C,MAAM,WAAW,QAAQ;IACvB,0DAA0D;IAC1D,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,yDAAyD;IACzD,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,4CAA4C;IAC5C,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,+DAA+D;IAC/D,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,oDAAoD;IACpD,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,gEAAgE;IAChE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,sEAAsE;IACtE,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;IACpB,0EAA0E;IAC1E,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAA;IAC3B,wCAAwC;IACxC,QAAQ,CAAC,YAAY,EAAE,OAAO,CAAA;IAC9B,0DAA0D;IAC1D,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAA;IAC3B,gDAAgD;IAChD,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAA;CAC1B;AAED,MAAM,WAAW,iBAAkB,SAAQ,QAAQ;IACjD,iGAAiG;IACjG,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CACvB;AAED,MAAM,WAAW,gBAAgB;IAC/B;;;;;;;;OAQG;IACH,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAC9B;AAED,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,YAAY,CAAA;IAClB,MAAM,EAAE,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,KAAK,OAAO,CAAA;IAC5D,UAAU,EAAE,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,KAAK,MAAM,GAAG,IAAI,CAAA;IACtE,UAAU,EAAE,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,KAAK,MAAM,CAAA;CAChE"}
|