@dash0/sdk-web 0.20.0 → 0.22.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.
Files changed (38) hide show
  1. package/README.md +12 -0
  2. package/dist/dash0.iife.js +1 -1
  3. package/dist/dash0.iife.js.map +1 -1
  4. package/dist/dash0.js +1 -1
  5. package/dist/dash0.js.map +1 -1
  6. package/dist/dash0.umd.cjs +1 -1
  7. package/dist/dash0.umd.cjs.map +1 -1
  8. package/dist/modules/api/browser-env.js +33 -0
  9. package/dist/modules/api/init.js +23 -18
  10. package/dist/modules/api/init_test.js +272 -1
  11. package/dist/modules/api/vcs.js +190 -0
  12. package/dist/modules/semantic-conventions.js +8 -0
  13. package/dist/modules/transport/index.js +4 -0
  14. package/dist/modules/utils/index.js +1 -0
  15. package/dist/modules/utils/session-sampling.js +16 -0
  16. package/dist/modules/utils/session-sampling_test.js +72 -0
  17. package/dist/modules/vars.js +1 -0
  18. package/dist/tsconfig.tsbuildinfo +1 -1
  19. package/dist/types/api/browser-env.d.ts +54 -0
  20. package/dist/types/api/vcs.d.ts +10 -0
  21. package/dist/types/semantic-conventions.d.ts +7 -0
  22. package/dist/types/types/options.d.ts +62 -0
  23. package/dist/types/utils/index.d.ts +1 -0
  24. package/dist/types/utils/session-sampling.d.ts +9 -0
  25. package/dist/types/utils/session-sampling_test.d.ts +1 -0
  26. package/dist/types/vars.d.ts +5 -0
  27. package/package.json +1 -1
  28. package/src/api/browser-env.ts +94 -0
  29. package/src/api/init.ts +62 -20
  30. package/src/api/init_test.ts +357 -1
  31. package/src/api/vcs.ts +328 -0
  32. package/src/semantic-conventions.ts +9 -0
  33. package/src/transport/index.ts +3 -0
  34. package/src/types/options.ts +66 -0
  35. package/src/utils/index.ts +1 -0
  36. package/src/utils/session-sampling.ts +15 -0
  37. package/src/utils/session-sampling_test.ts +83 -0
  38. package/src/vars.ts +7 -0
@@ -0,0 +1,54 @@
1
+ /**
2
+ * Framework prefixes the SDK reads as literal `process.env.{PREFIX}{SUFFIX}`
3
+ * accessors. Vercel auto-prefixes its `VERCEL_*` system vars under each
4
+ * (per https://vercel.com/docs/environment-variables/framework-environment-variables).
5
+ * Users on platforms without auto-prefixing (Netlify, Cloudflare Pages,
6
+ * custom CI) can expose env vars under any of these prefixes to get the
7
+ * same detection.
8
+ *
9
+ * Caveat: a prefix being listed here means the SDK *will read* a literal
10
+ * `process.env.{PREFIX}_X` accessor — it does not guarantee the consumer's
11
+ * bundler will substitute that accessor. Webpack-based bundlers (Next.js,
12
+ * Gatsby, CRA) substitute `process.env.X` literals by default. Vite reads
13
+ * env vars via `import.meta.env.VITE_*` by default; for `process.env.VITE_*`
14
+ * to be substituted in a Vite build the consumer must add
15
+ * `define: { 'process.env.VITE_X': JSON.stringify(...) }` to their Vite
16
+ * config, or use a `process.env` polyfill plugin. When deploying to Vercel
17
+ * the `VITE_VERCEL_*` substitution happens inside the build environment, so
18
+ * Vite + Vercel works out of the box; Vite users on other platforms need to
19
+ * surface env vars via their own bundler config.
20
+ *
21
+ * Keep `FRAMEWORK_PREFIX_SAMPLES` in `init_test.ts` in sync when adding a
22
+ * prefix here.
23
+ */
24
+ export type FrameworkPrefix = "NEXT_PUBLIC_" | "NUXT_PUBLIC_" | "NUXT_ENV_" | "REACT_APP_" | "GATSBY_" | "VITE_" | "PUBLIC_" | "VUE_APP_" | "REDWOOD_ENV_" | "SANITY_STUDIO_";
25
+ /** Vercel system env vars consumed by detectEnvironment / detectDeploymentName / detectDeploymentId. */
26
+ type VercelDeploymentSuffix = "VERCEL_ENV" | "VERCEL_TARGET_ENV" | "VERCEL_BRANCH_URL";
27
+ /** Vercel git env vars consumed by VCS detection. */
28
+ type VercelGitSuffix = "VERCEL_GIT_PROVIDER" | "VERCEL_GIT_REPO_OWNER" | "VERCEL_GIT_REPO_SLUG" | "VERCEL_GIT_COMMIT_REF" | "VERCEL_GIT_COMMIT_SHA" | "VERCEL_GIT_PULL_REQUEST_ID";
29
+ /** Netlify build env vars (Netlify does not auto-prefix; users surface these via their framework convention). */
30
+ type NetlifyGitSuffix = "REPOSITORY_URL" | "BRANCH" | "COMMIT_REF" | "REVIEW_ID";
31
+ /** Every env var name the SDK reads as a literal `process.env.X` accessor. */
32
+ type BrowserBuildEnvKey = `${FrameworkPrefix}${VercelDeploymentSuffix | VercelGitSuffix | NetlifyGitSuffix}`;
33
+ /**
34
+ * Module-locally typed shape of `process.env`. Consumers re-declare `process`
35
+ * with this type so dot-notation accessors are typed (no `@ts-expect-error`)
36
+ * and `noPropertyAccessFromIndexSignature` does not fire (each key is a
37
+ * known union member, not an index signature).
38
+ */
39
+ export type BrowserBuildEnv = {
40
+ readonly [K in BrowserBuildEnvKey]?: string;
41
+ };
42
+ /**
43
+ * Return the first truthy value, or undefined. Used to walk the list of
44
+ * framework-prefixed variants of an env var and pick whichever the user's
45
+ * bundler substituted at build time.
46
+ *
47
+ * The falsy check skips empty strings as well as undefined — bundlers that
48
+ * do not substitute a literal leave it as `undefined`, not `""`, so empty
49
+ * is treated as "not set". This is intentional and matches every known
50
+ * `VERCEL_GIT_*` / `REPOSITORY_URL` / etc. value shape (non-empty strings
51
+ * or absent; Vercel PR IDs are positive integer strings, never `"0"`).
52
+ */
53
+ export declare function pickFirstString(...values: (string | undefined)[]): string | undefined;
54
+ export {};
@@ -0,0 +1,10 @@
1
+ import { InitOptions } from "../types/options";
2
+ /**
3
+ * Derive VCS (version control) context from the build environment and apply
4
+ * the resulting `vcs.*` resource attributes to `vars.resource.attributes`.
5
+ *
6
+ * Detection precedence per attribute: `opts.vcs` → Vercel env vars → Netlify
7
+ * env vars. Manual overrides via `opts.vcs` always win, even when
8
+ * `opts.disableVcsDetection` is set.
9
+ */
10
+ export declare function applyVcsResourceAttributes(opts: InitOptions): void;
@@ -4,6 +4,13 @@ export declare const SERVICE_VERSION = "service.version";
4
4
  export declare const DEPLOYMENT_ENVIRONMENT_NAME = "deployment.environment.name";
5
5
  export declare const DEPLOYMENT_NAME = "deployment.name";
6
6
  export declare const DEPLOYMENT_ID = "deployment.id";
7
+ export declare const VCS_PROVIDER_NAME = "vcs.provider.name";
8
+ export declare const VCS_OWNER_NAME = "vcs.owner.name";
9
+ export declare const VCS_REPOSITORY_NAME = "vcs.repository.name";
10
+ export declare const VCS_REPOSITORY_URL_FULL = "vcs.repository.url.full";
11
+ export declare const VCS_REF_HEAD_NAME = "vcs.ref.head.name";
12
+ export declare const VCS_REF_HEAD_REVISION = "vcs.ref.head.revision";
13
+ export declare const VCS_CHANGE_ID = "vcs.change.id";
7
14
  export declare const EVENT_NAME = "event.name";
8
15
  export declare const WEB_EVENT_TITLE = "dash0.web.event.title";
9
16
  export declare const WEB_EVENT_ID = "dash0.web.event.id";
@@ -2,6 +2,28 @@ import { AttributeValueType } from "../utils/otel";
2
2
  import { AnyValue } from "./otlp";
3
3
  import { Endpoint, Vars, PropagatorConfig } from "../vars";
4
4
  export type InstrumentationName = "@dash0/navigation" | "@dash0/web-vitals" | "@dash0/error" | "@dash0/fetch";
5
+ /**
6
+ * VCS (version control) context describing the build the SDK is running
7
+ * inside. Used both as the public manual-override shape on `InitOptions.vcs`
8
+ * and internally as the merged result of auto-detection. Each field maps to
9
+ * a standard OpenTelemetry `vcs.*` resource attribute.
10
+ */
11
+ export type VcsAttributes = {
12
+ /** vcs.provider.name — e.g. "github", "gitlab", "bitbucket". */
13
+ providerName?: string;
14
+ /** vcs.owner.name — repository owner / organization. */
15
+ ownerName?: string;
16
+ /** vcs.repository.name — short repository name (no owner prefix). */
17
+ repositoryName?: string;
18
+ /** vcs.repository.url.full — canonical repository URL. */
19
+ repositoryUrlFull?: string;
20
+ /** vcs.ref.head.name — branch or tag name the build was made from. */
21
+ refHeadName?: string;
22
+ /** vcs.ref.head.revision — commit SHA the build was made from. */
23
+ refHeadRevision?: string;
24
+ /** vcs.change.id — pull/merge request identifier (preview deploys). */
25
+ changeId?: string;
26
+ };
5
27
  export type InitOptions = {
6
28
  serviceName: string;
7
29
  serviceNamespace?: string;
@@ -23,6 +45,37 @@ export type InitOptions = {
23
45
  * Set to `false` to opt out and pass the `serviceName` through unchanged.
24
46
  */
25
47
  rejectSuspiciousServiceName?: boolean;
48
+ /**
49
+ * When `true`, disable auto-detection of VCS (version control) context
50
+ * from the build environment. By default the SDK reads VCS context from
51
+ * Vercel (`<FRAMEWORK_PREFIX>VERCEL_GIT_*`) and Netlify
52
+ * (`<FRAMEWORK_PREFIX>REPOSITORY_URL`, `<FRAMEWORK_PREFIX>BRANCH`,
53
+ * `<FRAMEWORK_PREFIX>COMMIT_REF`, `<FRAMEWORK_PREFIX>REVIEW_ID`) and applies the values
54
+ * as resource attributes following the OTel `vcs.*` semantic conventions:
55
+ *
56
+ * - vcs.provider.name
57
+ * - vcs.owner.name
58
+ * - vcs.repository.name
59
+ * - vcs.repository.url.full
60
+ * - vcs.ref.head.name
61
+ * - vcs.ref.head.revision
62
+ * - vcs.change.id
63
+ *
64
+ * Pairing telemetry with the git commit + branch the build came from lets
65
+ * Dash0 Agent answer questions like "which PR introduced this error?".
66
+ *
67
+ * Note: any fields supplied via `vcs` are still applied even when this flag
68
+ * is `true` — manual overrides always win. Set this flag when you want to
69
+ * prevent env-var reads entirely but still supply context explicitly.
70
+ */
71
+ disableVcsDetection?: boolean;
72
+ /**
73
+ * Manually specify VCS (version control) context. Each provided field
74
+ * overrides the value the SDK would otherwise auto-detect from the build
75
+ * environment for that attribute. Use this for non-Vercel/Netlify
76
+ * deployments, or when the auto-detected values are wrong.
77
+ */
78
+ vcs?: VcsAttributes;
26
79
  /**
27
80
  * OTLP endpoints to which the generated telemetry should be sent to.
28
81
  */
@@ -31,6 +84,15 @@ export type InitOptions = {
31
84
  * Which instrumentations to enable. Defaults to undefined, which means all instrumentations.
32
85
  */
33
86
  enabledInstrumentations?: InstrumentationName[];
87
+ /**
88
+ * The percentage of sessions for which telemetry data is recorded and transmitted.
89
+ * Must be a number between 0 and 100.
90
+ * - 0: No sessions are recorded/transferred.
91
+ * - 100: All sessions are recorded/transferred (default).
92
+ * - Any other value: That percentage of sessions are recorded/transferred.
93
+ * The sampling decision is deterministic per session ID.
94
+ */
95
+ sessionSamplingRate?: number;
34
96
  /**
35
97
  * The session inactivity timeout. Session inactivity is the maximum
36
98
  * allowed time to pass between two page loads before the session is considered
@@ -16,3 +16,4 @@ export * from "./url";
16
16
  export * from "./pick";
17
17
  export * from "./sanitize";
18
18
  export * from "./wrap";
19
+ export * from "./session-sampling";
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Determines whether a session should be sampled based on the session ID
3
+ * and a configured sampling rate.
4
+ *
5
+ * @param sessionId The hex session ID string
6
+ * @param samplingRate A number between 0 and 100 (inclusive)
7
+ * @returns true if the session should be sampled (data collected), false otherwise
8
+ */
9
+ export declare function isSessionSampledIn(sessionId: string, samplingRate: number): boolean;
@@ -0,0 +1 @@
1
+ export {};
@@ -145,5 +145,10 @@ export type Vars = {
145
145
  * experimental - in rare cases causes Chrome to crash to use at your own risk.
146
146
  */
147
147
  enableTransportCompression: boolean;
148
+ /**
149
+ * Whether the current session is sampled in (true) or out (false).
150
+ * Determined at init time based on sessionSamplingRate and the session ID.
151
+ */
152
+ isSessionSampled: boolean;
148
153
  };
149
154
  export declare const vars: Vars;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dash0/sdk-web",
3
- "version": "0.20.0",
3
+ "version": "0.22.0",
4
4
  "description": "Dash0's Web SDK to collect telemetry from end-users' web browsers",
5
5
  "type": "module",
6
6
  "main": "dist/dash0.umd.cjs",
@@ -0,0 +1,94 @@
1
+ // Shared types and helpers for reading build-environment variables exposed
2
+ // to the browser bundle. Owned by this module because it is used from both
3
+ // init.ts (environment / deployment detection) and vcs.ts (VCS detection).
4
+ //
5
+ // IMPORTANT: each `process.env.NAME` MUST be a LITERAL accessor in the
6
+ // caller's source. Webpack DefinePlugin, Next.js, Gatsby, and equivalents
7
+ // substitute env vars at build time only when they see the literal form.
8
+ // Dynamic lookups (`process.env[name]`, iterating a string array) are NOT
9
+ // substituted — they resolve to `undefined` in the browser bundle.
10
+ //
11
+ // The type unions below are the single source of truth for which env var
12
+ // names the SDK reads. They are composed via template-literal types so
13
+ // every (prefix × suffix) combination is enumerated at the type level.
14
+ // Adding a framework prefix is a one-line edit to `FrameworkPrefix`; adding
15
+ // a suffix is a one-line edit to the appropriate suffix union.
16
+
17
+ /**
18
+ * Framework prefixes the SDK reads as literal `process.env.{PREFIX}{SUFFIX}`
19
+ * accessors. Vercel auto-prefixes its `VERCEL_*` system vars under each
20
+ * (per https://vercel.com/docs/environment-variables/framework-environment-variables).
21
+ * Users on platforms without auto-prefixing (Netlify, Cloudflare Pages,
22
+ * custom CI) can expose env vars under any of these prefixes to get the
23
+ * same detection.
24
+ *
25
+ * Caveat: a prefix being listed here means the SDK *will read* a literal
26
+ * `process.env.{PREFIX}_X` accessor — it does not guarantee the consumer's
27
+ * bundler will substitute that accessor. Webpack-based bundlers (Next.js,
28
+ * Gatsby, CRA) substitute `process.env.X` literals by default. Vite reads
29
+ * env vars via `import.meta.env.VITE_*` by default; for `process.env.VITE_*`
30
+ * to be substituted in a Vite build the consumer must add
31
+ * `define: { 'process.env.VITE_X': JSON.stringify(...) }` to their Vite
32
+ * config, or use a `process.env` polyfill plugin. When deploying to Vercel
33
+ * the `VITE_VERCEL_*` substitution happens inside the build environment, so
34
+ * Vite + Vercel works out of the box; Vite users on other platforms need to
35
+ * surface env vars via their own bundler config.
36
+ *
37
+ * Keep `FRAMEWORK_PREFIX_SAMPLES` in `init_test.ts` in sync when adding a
38
+ * prefix here.
39
+ */
40
+ export type FrameworkPrefix =
41
+ | "NEXT_PUBLIC_"
42
+ | "NUXT_PUBLIC_"
43
+ | "NUXT_ENV_"
44
+ | "REACT_APP_"
45
+ | "GATSBY_"
46
+ | "VITE_"
47
+ | "PUBLIC_"
48
+ | "VUE_APP_"
49
+ | "REDWOOD_ENV_"
50
+ | "SANITY_STUDIO_";
51
+
52
+ /** Vercel system env vars consumed by detectEnvironment / detectDeploymentName / detectDeploymentId. */
53
+ type VercelDeploymentSuffix = "VERCEL_ENV" | "VERCEL_TARGET_ENV" | "VERCEL_BRANCH_URL";
54
+
55
+ /** Vercel git env vars consumed by VCS detection. */
56
+ type VercelGitSuffix =
57
+ | "VERCEL_GIT_PROVIDER"
58
+ | "VERCEL_GIT_REPO_OWNER"
59
+ | "VERCEL_GIT_REPO_SLUG"
60
+ | "VERCEL_GIT_COMMIT_REF"
61
+ | "VERCEL_GIT_COMMIT_SHA"
62
+ | "VERCEL_GIT_PULL_REQUEST_ID";
63
+
64
+ /** Netlify build env vars (Netlify does not auto-prefix; users surface these via their framework convention). */
65
+ type NetlifyGitSuffix = "REPOSITORY_URL" | "BRANCH" | "COMMIT_REF" | "REVIEW_ID";
66
+
67
+ /** Every env var name the SDK reads as a literal `process.env.X` accessor. */
68
+ type BrowserBuildEnvKey = `${FrameworkPrefix}${VercelDeploymentSuffix | VercelGitSuffix | NetlifyGitSuffix}`;
69
+
70
+ /**
71
+ * Module-locally typed shape of `process.env`. Consumers re-declare `process`
72
+ * with this type so dot-notation accessors are typed (no `@ts-expect-error`)
73
+ * and `noPropertyAccessFromIndexSignature` does not fire (each key is a
74
+ * known union member, not an index signature).
75
+ */
76
+ export type BrowserBuildEnv = { readonly [K in BrowserBuildEnvKey]?: string };
77
+
78
+ /**
79
+ * Return the first truthy value, or undefined. Used to walk the list of
80
+ * framework-prefixed variants of an env var and pick whichever the user's
81
+ * bundler substituted at build time.
82
+ *
83
+ * The falsy check skips empty strings as well as undefined — bundlers that
84
+ * do not substitute a literal leave it as `undefined`, not `""`, so empty
85
+ * is treated as "not set". This is intentional and matches every known
86
+ * `VERCEL_GIT_*` / `REPOSITORY_URL` / etc. value shape (non-empty strings
87
+ * or absent; Vercel PR IDs are positive integer strings, never `"0"`).
88
+ */
89
+ export function pickFirstString(...values: (string | undefined)[]): string | undefined {
90
+ for (const value of values) {
91
+ if (value) return value;
92
+ }
93
+ return undefined;
94
+ }
package/src/api/init.ts CHANGED
@@ -12,6 +12,7 @@ import {
12
12
  import {
13
13
  fetch,
14
14
  generateUniqueId,
15
+ isSessionSampledIn,
15
16
  isSafeServiceName,
16
17
  PAGE_LOAD_ID_BYTES,
17
18
  warn,
@@ -23,7 +24,7 @@ import {
23
24
  pick,
24
25
  loc,
25
26
  } from "../utils";
26
- import { trackSessions } from "./session";
27
+ import { sessionId, trackSessions } from "./session";
27
28
  import { startWebVitalsInstrumentation } from "../instrumentations/web-vitals";
28
29
  import { startErrorInstrumentation } from "../instrumentations/errors";
29
30
  import { addAttribute } from "../utils/otel";
@@ -32,6 +33,10 @@ import { startNavigationInstrumentation } from "../instrumentations/navigation";
32
33
  import { merge } from "ts-deepmerge";
33
34
  import { initializeTabId } from "../utils/tab-id";
34
35
  import { InitOptions, InstrumentationName } from "../types/options";
36
+ import { BrowserBuildEnv, pickFirstString } from "./browser-env";
37
+ import { applyVcsResourceAttributes } from "./vcs";
38
+
39
+ declare const process: { env?: BrowserBuildEnv } | undefined;
35
40
 
36
41
  let hasBeenInitialised: boolean = false;
37
42
 
@@ -93,6 +98,17 @@ export function init(opts: InitOptions) {
93
98
  initializeTabId();
94
99
  trackSessions(opts.sessionInactivityTimeoutMillis, opts.sessionTerminationTimeoutMillis);
95
100
 
101
+ if (opts.sessionSamplingRate != null) {
102
+ const rate = Math.max(0, Math.min(100, opts.sessionSamplingRate));
103
+ vars.isSessionSampled = sessionId != null ? isSessionSampledIn(sessionId, rate) : rate > 0;
104
+ }
105
+
106
+ if (!vars.isSessionSampled) {
107
+ debug("Session is not sampled. No telemetry will be transmitted for this session.");
108
+ hasBeenInitialised = true;
109
+ return;
110
+ }
111
+
96
112
  if (isInstrumentationEnabled("@dash0/navigation", opts)) {
97
113
  startNavigationInstrumentation();
98
114
  }
@@ -134,6 +150,8 @@ function initializeResourceAttributes(opts: InitOptions) {
134
150
  if (deploymentId) {
135
151
  addAttribute(vars.resource.attributes, DEPLOYMENT_ID, deploymentId);
136
152
  }
153
+
154
+ applyVcsResourceAttributes(opts);
137
155
  }
138
156
 
139
157
  function initializeSignalAttributes(opts: InitOptions) {
@@ -155,18 +173,30 @@ function isClient() {
155
173
  return win != null;
156
174
  }
157
175
 
176
+ // Vercel auto-prefixes its system env vars under every framework preset
177
+ // (see https://vercel.com/docs/environment-variables/framework-environment-variables).
178
+ // The shared `FrameworkPrefix` union in `./browser-env` is the single source
179
+ // of truth for which prefixes the SDK recognises. To add a new prefix, edit
180
+ // it there; the literal accessors below pick it up automatically via the
181
+ // typed `process.env` declaration.
182
+
158
183
  function detectEnvironment(opts: InitOptions): string | undefined {
159
- // if there is a manually specified value we use that
160
184
  if (opts.environment) {
161
185
  return opts.environment;
162
186
  }
163
-
164
- // if process isn't defined access to it causes an exception, but we can't check for its present due to how
165
- // plugins like webpack define work.
166
187
  try {
167
- // vercel
168
- // @ts-expect-error -- we need to access like this to allow webpack in the nextjs build to replace this
169
- return process?.env?.NEXT_PUBLIC_VERCEL_ENV;
188
+ return pickFirstString(
189
+ process?.env?.NEXT_PUBLIC_VERCEL_ENV,
190
+ process?.env?.NUXT_PUBLIC_VERCEL_ENV,
191
+ process?.env?.NUXT_ENV_VERCEL_ENV,
192
+ process?.env?.REACT_APP_VERCEL_ENV,
193
+ process?.env?.GATSBY_VERCEL_ENV,
194
+ process?.env?.VITE_VERCEL_ENV,
195
+ process?.env?.PUBLIC_VERCEL_ENV,
196
+ process?.env?.VUE_APP_VERCEL_ENV,
197
+ process?.env?.REDWOOD_ENV_VERCEL_ENV,
198
+ process?.env?.SANITY_STUDIO_VERCEL_ENV
199
+ );
170
200
  } catch (_ignored) {
171
201
  return undefined;
172
202
  }
@@ -176,13 +206,19 @@ function detectDeploymentName(opts: InitOptions): string | undefined {
176
206
  if (opts.deploymentName) {
177
207
  return opts.deploymentName;
178
208
  }
179
-
180
- // if process isn't defined access to it causes an exception, but we can't check for its present due to how
181
- // plugins like webpack define work.
182
209
  try {
183
- // vercel
184
- // @ts-expect-error -- we need to access like this to allow webpack in the nextjs build to replace this
185
- return process?.env?.NEXT_PUBLIC_VERCEL_TARGET_ENV;
210
+ return pickFirstString(
211
+ process?.env?.NEXT_PUBLIC_VERCEL_TARGET_ENV,
212
+ process?.env?.NUXT_PUBLIC_VERCEL_TARGET_ENV,
213
+ process?.env?.NUXT_ENV_VERCEL_TARGET_ENV,
214
+ process?.env?.REACT_APP_VERCEL_TARGET_ENV,
215
+ process?.env?.GATSBY_VERCEL_TARGET_ENV,
216
+ process?.env?.VITE_VERCEL_TARGET_ENV,
217
+ process?.env?.PUBLIC_VERCEL_TARGET_ENV,
218
+ process?.env?.VUE_APP_VERCEL_TARGET_ENV,
219
+ process?.env?.REDWOOD_ENV_VERCEL_TARGET_ENV,
220
+ process?.env?.SANITY_STUDIO_VERCEL_TARGET_ENV
221
+ );
186
222
  } catch (_ignored) {
187
223
  return undefined;
188
224
  }
@@ -192,13 +228,19 @@ function detectDeploymentId(opts: InitOptions): string | undefined {
192
228
  if (opts.deploymentId) {
193
229
  return opts.deploymentId;
194
230
  }
195
-
196
- // if process isn't defined access to it causes an exception, but we can't check for its present due to how
197
- // plugins like webpack define work.
198
231
  try {
199
- // vercel
200
- // @ts-expect-error -- we need to access like this to allow webpack in the nextjs build to replace this
201
- return process?.env?.NEXT_PUBLIC_VERCEL_BRANCH_URL;
232
+ return pickFirstString(
233
+ process?.env?.NEXT_PUBLIC_VERCEL_BRANCH_URL,
234
+ process?.env?.NUXT_PUBLIC_VERCEL_BRANCH_URL,
235
+ process?.env?.NUXT_ENV_VERCEL_BRANCH_URL,
236
+ process?.env?.REACT_APP_VERCEL_BRANCH_URL,
237
+ process?.env?.GATSBY_VERCEL_BRANCH_URL,
238
+ process?.env?.VITE_VERCEL_BRANCH_URL,
239
+ process?.env?.PUBLIC_VERCEL_BRANCH_URL,
240
+ process?.env?.VUE_APP_VERCEL_BRANCH_URL,
241
+ process?.env?.REDWOOD_ENV_VERCEL_BRANCH_URL,
242
+ process?.env?.SANITY_STUDIO_VERCEL_BRANCH_URL
243
+ );
202
244
  } catch (_ignored) {
203
245
  return undefined;
204
246
  }