which-url 0.0.4 → 0.0.6

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 CHANGED
@@ -148,6 +148,18 @@ Framework-prefixed env vars like `NEXT_PUBLIC_VERCEL_PROJECT_PRODUCTION_URL` are
148
148
 
149
149
  ## Advanced
150
150
 
151
+ ### Portless
152
+
153
+ Zero config — [portless](https://portless.sh) sets `PORTLESS_URL` and `which-url` picks it up automatically.
154
+
155
+ ```json
156
+ "dev": "portless run next dev"
157
+ ```
158
+
159
+ ```
160
+ origin → https://myapp.localhost
161
+ ```
162
+
151
163
  ### Tunnels (ngrok, Cloudflare Tunnel)
152
164
 
153
165
  Tunnel URLs can't be auto-detected — they're external to the app process. Set `APP_URL`:
@@ -167,15 +179,13 @@ APP_URL = "https://myapp.workers.dev"
167
179
 
168
180
  Modern wrangler polyfills `process.env` from `[vars]`, so `which-url` picks it up automatically.
169
181
 
170
- ### `createUrl(options?)`
171
-
172
- Re-resolves the URL from the current environment. Unlike the singleton (which catches errors), `createUrl()` throws in production if no URL is detected.
182
+ ### Debugging
173
183
 
174
184
  ```typescript
175
- import { createUrl } from 'which-url'
185
+ import { debug } from 'which-url'
176
186
 
177
- const url = createUrl({ fallback: 'https://fallback.example.com' })
178
- url.origin // never throws
187
+ console.log(debug)
188
+ // "platform=vercel | source=provider | url=https://myapp.com | env=production"
179
189
  ```
180
190
 
181
191
  ## API
@@ -196,6 +206,8 @@ An object with URL properties and environment helpers.
196
206
  | `port` | `string` | `""` or `"3000"` |
197
207
  | `env` | `AppEnv` | `"production"` \| `"preview"` \| `"local"` |
198
208
  | `platform` | `Platform` | `"vercel"` \| `"netlify"` \| ... \| `null` |
209
+ | `source` | `Source` | `"override"` \| `"provider"` \| `"browser"` \| `"fallback"` \| `null` |
210
+ | `debug` | `string` | `"platform=vercel \| source=provider \| url=https://myapp.com \| env=production"` |
199
211
  | `isProduction` | `boolean` | |
200
212
  | `isPreview` | `boolean` | |
201
213
  | `isLocal` | `boolean` | |
package/dist/env.d.ts CHANGED
@@ -1,3 +1,7 @@
1
1
  import type { AppEnv } from "./types";
2
- export declare function resolveEnv(): AppEnv;
2
+ export interface EnvResult {
3
+ env: AppEnv;
4
+ debugLabel: string;
5
+ }
6
+ export declare function resolveEnv(): EnvResult;
3
7
  //# sourceMappingURL=env.d.ts.map
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,wBAAgB,UAAU,IAAI,MAAM,CAwBnC"}
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,IAAI,SAAS,CAyBtC"}
package/dist/index.d.ts CHANGED
@@ -1,5 +1,4 @@
1
- import type { WhichUrl, AppEnv, Platform, CreateUrlOptions } from "./types";
2
- export declare function createUrl(options?: CreateUrlOptions): WhichUrl;
1
+ import type { WhichUrl, AppEnv, Platform } from "./types";
3
2
  declare let _resolved: WhichUrl;
4
3
  export declare const href: string;
5
4
  export declare const origin: string;
@@ -13,5 +12,5 @@ export declare const isProduction: boolean;
13
12
  export declare const isPreview: boolean;
14
13
  export declare const isLocal: boolean;
15
14
  export default _resolved;
16
- export type { WhichUrl, AppEnv, Platform, CreateUrlOptions };
15
+ export type { WhichUrl, AppEnv, Platform };
17
16
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAA;AAE3E,wBAAgB,SAAS,CAAC,OAAO,CAAC,EAAE,gBAAgB,GAAG,QAAQ,CAkB9D;AAGD,QAAA,IAAI,SAAS,EAAE,QAAQ,CAAA;AAuBvB,eAAO,MAAM,IAAI,EAAE,MAAuB,CAAA;AAC1C,eAAO,MAAM,MAAM,EAAE,MAAyB,CAAA;AAC9C,eAAO,MAAM,QAAQ,EAAE,MAA2B,CAAA;AAClD,eAAO,MAAM,IAAI,EAAE,MAAuB,CAAA;AAC1C,eAAO,MAAM,QAAQ,EAAE,MAA2B,CAAA;AAClD,eAAO,MAAM,IAAI,EAAE,MAAuB,CAAA;AAC1C,eAAO,MAAM,GAAG,EAAE,MAAsB,CAAA;AACxC,eAAO,MAAM,QAAQ,EAAE,QAA6B,CAAA;AACpD,eAAO,MAAM,YAAY,EAAE,OAAgC,CAAA;AAC3D,eAAO,MAAM,SAAS,EAAE,OAA6B,CAAA;AACrD,eAAO,MAAM,OAAO,EAAE,OAA2B,CAAA;AAGjD,eAAe,SAAS,CAAA;AAExB,YAAY,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,gBAAgB,EAAE,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAA;AAqCzD,QAAA,IAAI,SAAS,EAAE,QAAQ,CAAA;AA8BvB,eAAO,MAAM,IAAI,EAAE,MAAuB,CAAA;AAC1C,eAAO,MAAM,MAAM,EAAE,MAAyB,CAAA;AAC9C,eAAO,MAAM,QAAQ,EAAE,MAA2B,CAAA;AAClD,eAAO,MAAM,IAAI,EAAE,MAAuB,CAAA;AAC1C,eAAO,MAAM,QAAQ,EAAE,MAA2B,CAAA;AAClD,eAAO,MAAM,IAAI,EAAE,MAAuB,CAAA;AAC1C,eAAO,MAAM,GAAG,EAAE,MAAsB,CAAA;AACxC,eAAO,MAAM,QAAQ,EAAE,QAA6B,CAAA;AACpD,eAAO,MAAM,YAAY,EAAE,OAAgC,CAAA;AAC3D,eAAO,MAAM,SAAS,EAAE,OAA6B,CAAA;AACrD,eAAO,MAAM,OAAO,EAAE,OAA2B,CAAA;AAGjD,eAAe,SAAS,CAAA;AAExB,YAAY,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAA"}
package/dist/index.js CHANGED
@@ -144,28 +144,27 @@ function normalizeUrl(raw) {
144
144
  }
145
145
 
146
146
  // src/resolve.ts
147
- function resolveUrl(options) {
147
+ function resolveUrl() {
148
148
  const env = getEnv();
149
149
  const override = getVar(env, "APP_URL");
150
150
  if (override)
151
- return normalizeUrl(override);
151
+ return { url: normalizeUrl(override), debugLabel: `[override] APP_URL=${override}` };
152
+ if (env.PORTLESS_URL)
153
+ return { url: env.PORTLESS_URL, debugLabel: `[portless] PORTLESS_URL=${env.PORTLESS_URL}` };
152
154
  for (const p of providers) {
153
155
  if (p.detect(env)) {
154
156
  const url = p.resolveUrl(env);
155
157
  if (url)
156
- return normalizeUrl(url);
158
+ return { url: normalizeUrl(url), debugLabel: `[provider:${p.name}] url=${url}` };
157
159
  }
158
160
  }
159
161
  if (typeof window !== "undefined" && window.location) {
160
- return window.location.origin;
162
+ return { url: window.location.origin, debugLabel: `[browser] window.location.origin` };
161
163
  }
162
164
  const isProduction = env.NODE_ENV === "production";
163
165
  if (!isProduction) {
164
166
  const port = env.PORT || "3000";
165
- return `http://localhost:${port}`;
166
- }
167
- if (options?.fallback) {
168
- return normalizeUrl(options.fallback);
167
+ return { url: `http://localhost:${port}`, debugLabel: `[fallback] PORT=${port}` };
169
168
  }
170
169
  throw new Error("which-url: Cannot detect app URL. Set APP_URL environment variable.");
171
170
  }
@@ -185,27 +184,29 @@ function resolveEnv() {
185
184
  const env = getEnv();
186
185
  const appEnv = getVar(env, "APP_ENV");
187
186
  if (appEnv && validEnvs.includes(appEnv)) {
188
- return appEnv;
187
+ return { env: appEnv, debugLabel: `APP_ENV=${appEnv}` };
189
188
  }
190
189
  if (env.NODE_ENV === "development")
191
- return "local";
190
+ return { env: "local", debugLabel: "NODE_ENV=development" };
192
191
  for (const p of providers) {
193
192
  if (p.detect(env)) {
194
- return p.resolveEnv(env);
193
+ const resolved = p.resolveEnv(env);
194
+ return { env: resolved, debugLabel: `${p.name}:${resolved}` };
195
195
  }
196
196
  }
197
197
  if (env.NODE_ENV === "production")
198
- return "production";
199
- return "local";
198
+ return { env: "production", debugLabel: "NODE_ENV=production" };
199
+ return { env: "local", debugLabel: "default" };
200
200
  }
201
201
 
202
202
  // src/index.ts
203
- function createUrl(options) {
204
- const resolved = resolveUrl(options);
205
- const parsed = new URL(resolved);
206
- const env = resolveEnv();
203
+ function resolve() {
204
+ const { url, debugLabel: urlDebug } = resolveUrl();
205
+ const parsed = new URL(url);
206
+ const { env, debugLabel: envDebug } = resolveEnv();
207
207
  const platform = resolvePlatform();
208
- return {
208
+ const debug = `${urlDebug} | env=${env} (${envDebug})`;
209
+ const result = {
209
210
  href: parsed.origin,
210
211
  origin: parsed.origin,
211
212
  hostname: parsed.hostname,
@@ -214,17 +215,24 @@ function createUrl(options) {
214
215
  port: parsed.port,
215
216
  env,
216
217
  platform,
218
+ debug,
217
219
  isProduction: env === "production",
218
220
  isPreview: env === "preview",
219
221
  isLocal: env === "local"
220
222
  };
223
+ Object.defineProperty(result, "debug", {
224
+ value: debug,
225
+ enumerable: false,
226
+ configurable: false
227
+ });
228
+ return result;
221
229
  }
222
230
  var _resolved;
223
231
  try {
224
- _resolved = createUrl();
232
+ _resolved = resolve();
225
233
  } catch (e) {
226
234
  console.warn(`[which-url] Could not detect app URL. Set APP_URL (e.g. APP_URL=https://myapp.com or APP_URL=myapp.com)`);
227
- _resolved = {
235
+ const fallback = {
228
236
  href: "",
229
237
  origin: "",
230
238
  hostname: "",
@@ -233,10 +241,17 @@ try {
233
241
  port: "",
234
242
  env: "local",
235
243
  platform: null,
244
+ debug: "[error] resolution failed",
236
245
  isProduction: false,
237
246
  isPreview: false,
238
247
  isLocal: true
239
248
  };
249
+ Object.defineProperty(fallback, "debug", {
250
+ value: "[error] resolution failed",
251
+ enumerable: false,
252
+ configurable: false
253
+ });
254
+ _resolved = fallback;
240
255
  }
241
256
  var href = _resolved.href;
242
257
  var origin = _resolved.origin;
@@ -262,6 +277,5 @@ export {
262
277
  hostname,
263
278
  host,
264
279
  env,
265
- src_default as default,
266
- createUrl
280
+ src_default as default
267
281
  };
package/dist/resolve.d.ts CHANGED
@@ -1,4 +1,8 @@
1
- import type { CreateUrlOptions, Platform } from "./types";
2
- export declare function resolveUrl(options?: CreateUrlOptions): string;
1
+ import type { Platform } from "./types";
2
+ export interface ResolveResult {
3
+ url: string;
4
+ debugLabel: string;
5
+ }
6
+ export declare function resolveUrl(): ResolveResult;
3
7
  export declare function resolvePlatform(): Platform;
4
8
  //# sourceMappingURL=resolve.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"resolve.d.ts","sourceRoot":"","sources":["../src/resolve.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,gBAAgB,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAA;AAEzD,wBAAgB,UAAU,CAAC,OAAO,CAAC,EAAE,gBAAgB,GAAG,MAAM,CAoC7D;AAED,wBAAgB,eAAe,IAAI,QAAQ,CAQ1C"}
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,IAAI,aAAa,CAkC1C;AAED,wBAAgB,eAAe,IAAI,QAAQ,CAQ1C"}
package/dist/types.d.ts CHANGED
@@ -9,13 +9,11 @@ export interface WhichUrl {
9
9
  port: string;
10
10
  env: AppEnv;
11
11
  platform: Platform;
12
+ debug: string;
12
13
  isProduction: boolean;
13
14
  isPreview: boolean;
14
15
  isLocal: boolean;
15
16
  }
16
- export interface CreateUrlOptions {
17
- fallback?: string;
18
- }
19
17
  export interface ProviderDetector {
20
18
  name: string;
21
19
  detect: (env: Record<string, string | undefined>) => boolean;
@@ -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,QAAQ,GAChB,QAAQ,GACR,SAAS,GACT,YAAY,GACZ,SAAS,GACT,KAAK,GACL,QAAQ,GACR,cAAc,GACd,QAAQ,GACR,IAAI,CAAA;AAER,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,EAAE,MAAM,CAAA;IACd,QAAQ,EAAE,MAAM,CAAA;IAChB,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,EAAE,MAAM,CAAA;IAChB,IAAI,EAAE,MAAM,CAAA;IACZ,GAAG,EAAE,MAAM,CAAA;IACX,QAAQ,EAAE,QAAQ,CAAA;IAClB,YAAY,EAAE,OAAO,CAAA;IACrB,SAAS,EAAE,OAAO,CAAA;IAClB,OAAO,EAAE,OAAO,CAAA;CACjB;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,EAAE,MAAM,CAAA;CAClB;AAED,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAA;IACZ,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"}
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,QAAQ,GAChB,QAAQ,GACR,SAAS,GACT,YAAY,GACZ,SAAS,GACT,KAAK,GACL,QAAQ,GACR,cAAc,GACd,QAAQ,GACR,IAAI,CAAA;AAER,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,EAAE,MAAM,CAAA;IACd,QAAQ,EAAE,MAAM,CAAA;IAChB,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,EAAE,MAAM,CAAA;IAChB,IAAI,EAAE,MAAM,CAAA;IACZ,GAAG,EAAE,MAAM,CAAA;IACX,QAAQ,EAAE,QAAQ,CAAA;IAClB,KAAK,EAAE,MAAM,CAAA;IACb,YAAY,EAAE,OAAO,CAAA;IACrB,SAAS,EAAE,OAAO,CAAA;IAClB,OAAO,EAAE,OAAO,CAAA;CACjB;AAED,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAA;IACZ,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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "which-url",
3
- "version": "0.0.4",
3
+ "version": "0.0.6",
4
4
  "description": "Auto-detect your app's URL across hosting providers. Zero config.",
5
5
  "type": "module",
6
6
  "exports": {