@uniformdev/redirect 19.62.0 → 19.62.1-alpha.127

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/dist/index.js CHANGED
@@ -5,9 +5,6 @@ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
5
  var __getOwnPropNames = Object.getOwnPropertyNames;
6
6
  var __getProtoOf = Object.getPrototypeOf;
7
7
  var __hasOwnProp = Object.prototype.hasOwnProperty;
8
- var __commonJS = (cb, mod) => function __require() {
9
- return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
10
- };
11
8
  var __export = (target, all) => {
12
9
  for (var name in all)
13
10
  __defProp(target, name, { get: all[name], enumerable: true });
@@ -30,300 +27,6 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
30
27
  ));
31
28
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
32
29
 
33
- // ../../node_modules/.pnpm/dotenv@16.3.1/node_modules/dotenv/package.json
34
- var require_package = __commonJS({
35
- "../../node_modules/.pnpm/dotenv@16.3.1/node_modules/dotenv/package.json"(exports, module2) {
36
- module2.exports = {
37
- name: "dotenv",
38
- version: "16.3.1",
39
- description: "Loads environment variables from .env file",
40
- main: "lib/main.js",
41
- types: "lib/main.d.ts",
42
- exports: {
43
- ".": {
44
- types: "./lib/main.d.ts",
45
- require: "./lib/main.js",
46
- default: "./lib/main.js"
47
- },
48
- "./config": "./config.js",
49
- "./config.js": "./config.js",
50
- "./lib/env-options": "./lib/env-options.js",
51
- "./lib/env-options.js": "./lib/env-options.js",
52
- "./lib/cli-options": "./lib/cli-options.js",
53
- "./lib/cli-options.js": "./lib/cli-options.js",
54
- "./package.json": "./package.json"
55
- },
56
- scripts: {
57
- "dts-check": "tsc --project tests/types/tsconfig.json",
58
- lint: "standard",
59
- "lint-readme": "standard-markdown",
60
- pretest: "npm run lint && npm run dts-check",
61
- test: "tap tests/*.js --100 -Rspec",
62
- prerelease: "npm test",
63
- release: "standard-version"
64
- },
65
- repository: {
66
- type: "git",
67
- url: "git://github.com/motdotla/dotenv.git"
68
- },
69
- funding: "https://github.com/motdotla/dotenv?sponsor=1",
70
- keywords: [
71
- "dotenv",
72
- "env",
73
- ".env",
74
- "environment",
75
- "variables",
76
- "config",
77
- "settings"
78
- ],
79
- readmeFilename: "README.md",
80
- license: "BSD-2-Clause",
81
- devDependencies: {
82
- "@definitelytyped/dtslint": "^0.0.133",
83
- "@types/node": "^18.11.3",
84
- decache: "^4.6.1",
85
- sinon: "^14.0.1",
86
- standard: "^17.0.0",
87
- "standard-markdown": "^7.1.0",
88
- "standard-version": "^9.5.0",
89
- tap: "^16.3.0",
90
- tar: "^6.1.11",
91
- typescript: "^4.8.4"
92
- },
93
- engines: {
94
- node: ">=12"
95
- },
96
- browser: {
97
- fs: false
98
- }
99
- };
100
- }
101
- });
102
-
103
- // ../../node_modules/.pnpm/dotenv@16.3.1/node_modules/dotenv/lib/main.js
104
- var require_main = __commonJS({
105
- "../../node_modules/.pnpm/dotenv@16.3.1/node_modules/dotenv/lib/main.js"(exports, module2) {
106
- "use strict";
107
- var fs = require("fs");
108
- var path = require("path");
109
- var os = require("os");
110
- var crypto = require("crypto");
111
- var packageJson = require_package();
112
- var version = packageJson.version;
113
- var LINE = /(?:^|^)\s*(?:export\s+)?([\w.-]+)(?:\s*=\s*?|:\s+?)(\s*'(?:\\'|[^'])*'|\s*"(?:\\"|[^"])*"|\s*`(?:\\`|[^`])*`|[^#\r\n]+)?\s*(?:#.*)?(?:$|$)/mg;
114
- function parse(src) {
115
- const obj = {};
116
- let lines = src.toString();
117
- lines = lines.replace(/\r\n?/mg, "\n");
118
- let match;
119
- while ((match = LINE.exec(lines)) != null) {
120
- const key = match[1];
121
- let value = match[2] || "";
122
- value = value.trim();
123
- const maybeQuote = value[0];
124
- value = value.replace(/^(['"`])([\s\S]*)\1$/mg, "$2");
125
- if (maybeQuote === '"') {
126
- value = value.replace(/\\n/g, "\n");
127
- value = value.replace(/\\r/g, "\r");
128
- }
129
- obj[key] = value;
130
- }
131
- return obj;
132
- }
133
- function _parseVault(options) {
134
- const vaultPath = _vaultPath(options);
135
- const result = DotenvModule.configDotenv({ path: vaultPath });
136
- if (!result.parsed) {
137
- throw new Error(`MISSING_DATA: Cannot parse ${vaultPath} for an unknown reason`);
138
- }
139
- const keys = _dotenvKey(options).split(",");
140
- const length = keys.length;
141
- let decrypted;
142
- for (let i = 0; i < length; i++) {
143
- try {
144
- const key = keys[i].trim();
145
- const attrs = _instructions(result, key);
146
- decrypted = DotenvModule.decrypt(attrs.ciphertext, attrs.key);
147
- break;
148
- } catch (error) {
149
- if (i + 1 >= length) {
150
- throw error;
151
- }
152
- }
153
- }
154
- return DotenvModule.parse(decrypted);
155
- }
156
- function _log(message) {
157
- console.log(`[dotenv@${version}][INFO] ${message}`);
158
- }
159
- function _warn(message) {
160
- console.log(`[dotenv@${version}][WARN] ${message}`);
161
- }
162
- function _debug(message) {
163
- console.log(`[dotenv@${version}][DEBUG] ${message}`);
164
- }
165
- function _dotenvKey(options) {
166
- if (options && options.DOTENV_KEY && options.DOTENV_KEY.length > 0) {
167
- return options.DOTENV_KEY;
168
- }
169
- if (process.env.DOTENV_KEY && process.env.DOTENV_KEY.length > 0) {
170
- return process.env.DOTENV_KEY;
171
- }
172
- return "";
173
- }
174
- function _instructions(result, dotenvKey) {
175
- let uri;
176
- try {
177
- uri = new URL(dotenvKey);
178
- } catch (error) {
179
- if (error.code === "ERR_INVALID_URL") {
180
- throw new Error("INVALID_DOTENV_KEY: Wrong format. Must be in valid uri format like dotenv://:key_1234@dotenv.org/vault/.env.vault?environment=development");
181
- }
182
- throw error;
183
- }
184
- const key = uri.password;
185
- if (!key) {
186
- throw new Error("INVALID_DOTENV_KEY: Missing key part");
187
- }
188
- const environment = uri.searchParams.get("environment");
189
- if (!environment) {
190
- throw new Error("INVALID_DOTENV_KEY: Missing environment part");
191
- }
192
- const environmentKey = `DOTENV_VAULT_${environment.toUpperCase()}`;
193
- const ciphertext = result.parsed[environmentKey];
194
- if (!ciphertext) {
195
- throw new Error(`NOT_FOUND_DOTENV_ENVIRONMENT: Cannot locate environment ${environmentKey} in your .env.vault file.`);
196
- }
197
- return { ciphertext, key };
198
- }
199
- function _vaultPath(options) {
200
- let dotenvPath = path.resolve(process.cwd(), ".env");
201
- if (options && options.path && options.path.length > 0) {
202
- dotenvPath = options.path;
203
- }
204
- return dotenvPath.endsWith(".vault") ? dotenvPath : `${dotenvPath}.vault`;
205
- }
206
- function _resolveHome(envPath) {
207
- return envPath[0] === "~" ? path.join(os.homedir(), envPath.slice(1)) : envPath;
208
- }
209
- function _configVault(options) {
210
- _log("Loading env from encrypted .env.vault");
211
- const parsed = DotenvModule._parseVault(options);
212
- let processEnv = process.env;
213
- if (options && options.processEnv != null) {
214
- processEnv = options.processEnv;
215
- }
216
- DotenvModule.populate(processEnv, parsed, options);
217
- return { parsed };
218
- }
219
- function configDotenv(options) {
220
- let dotenvPath = path.resolve(process.cwd(), ".env");
221
- let encoding = "utf8";
222
- const debug = Boolean(options && options.debug);
223
- if (options) {
224
- if (options.path != null) {
225
- dotenvPath = _resolveHome(options.path);
226
- }
227
- if (options.encoding != null) {
228
- encoding = options.encoding;
229
- }
230
- }
231
- try {
232
- const parsed = DotenvModule.parse(fs.readFileSync(dotenvPath, { encoding }));
233
- let processEnv = process.env;
234
- if (options && options.processEnv != null) {
235
- processEnv = options.processEnv;
236
- }
237
- DotenvModule.populate(processEnv, parsed, options);
238
- return { parsed };
239
- } catch (e) {
240
- if (debug) {
241
- _debug(`Failed to load ${dotenvPath} ${e.message}`);
242
- }
243
- return { error: e };
244
- }
245
- }
246
- function config(options) {
247
- const vaultPath = _vaultPath(options);
248
- if (_dotenvKey(options).length === 0) {
249
- return DotenvModule.configDotenv(options);
250
- }
251
- if (!fs.existsSync(vaultPath)) {
252
- _warn(`You set DOTENV_KEY but you are missing a .env.vault file at ${vaultPath}. Did you forget to build it?`);
253
- return DotenvModule.configDotenv(options);
254
- }
255
- return DotenvModule._configVault(options);
256
- }
257
- function decrypt(encrypted, keyStr) {
258
- const key = Buffer.from(keyStr.slice(-64), "hex");
259
- let ciphertext = Buffer.from(encrypted, "base64");
260
- const nonce = ciphertext.slice(0, 12);
261
- const authTag = ciphertext.slice(-16);
262
- ciphertext = ciphertext.slice(12, -16);
263
- try {
264
- const aesgcm = crypto.createDecipheriv("aes-256-gcm", key, nonce);
265
- aesgcm.setAuthTag(authTag);
266
- return `${aesgcm.update(ciphertext)}${aesgcm.final()}`;
267
- } catch (error) {
268
- const isRange = error instanceof RangeError;
269
- const invalidKeyLength = error.message === "Invalid key length";
270
- const decryptionFailed = error.message === "Unsupported state or unable to authenticate data";
271
- if (isRange || invalidKeyLength) {
272
- const msg = "INVALID_DOTENV_KEY: It must be 64 characters long (or more)";
273
- throw new Error(msg);
274
- } else if (decryptionFailed) {
275
- const msg = "DECRYPTION_FAILED: Please check your DOTENV_KEY";
276
- throw new Error(msg);
277
- } else {
278
- console.error("Error: ", error.code);
279
- console.error("Error: ", error.message);
280
- throw error;
281
- }
282
- }
283
- }
284
- function populate(processEnv, parsed, options = {}) {
285
- const debug = Boolean(options && options.debug);
286
- const override = Boolean(options && options.override);
287
- if (typeof parsed !== "object") {
288
- throw new Error("OBJECT_REQUIRED: Please check the processEnv argument being passed to populate");
289
- }
290
- for (const key of Object.keys(parsed)) {
291
- if (Object.prototype.hasOwnProperty.call(processEnv, key)) {
292
- if (override === true) {
293
- processEnv[key] = parsed[key];
294
- }
295
- if (debug) {
296
- if (override === true) {
297
- _debug(`"${key}" is already defined and WAS overwritten`);
298
- } else {
299
- _debug(`"${key}" is already defined and was NOT overwritten`);
300
- }
301
- }
302
- } else {
303
- processEnv[key] = parsed[key];
304
- }
305
- }
306
- }
307
- var DotenvModule = {
308
- configDotenv,
309
- _configVault,
310
- _parseVault,
311
- config,
312
- decrypt,
313
- parse,
314
- populate
315
- };
316
- module2.exports.configDotenv = DotenvModule.configDotenv;
317
- module2.exports._configVault = DotenvModule._configVault;
318
- module2.exports._parseVault = DotenvModule._parseVault;
319
- module2.exports.config = DotenvModule.config;
320
- module2.exports.decrypt = DotenvModule.decrypt;
321
- module2.exports.parse = DotenvModule.parse;
322
- module2.exports.populate = DotenvModule.populate;
323
- module2.exports = DotenvModule;
324
- }
325
- });
326
-
327
30
  // src/index.ts
328
31
  var src_exports = {};
329
32
  __export(src_exports, {
@@ -334,6 +37,9 @@ __export(src_exports, {
334
37
  RedirectFileConverter: () => RedirectFileConverter,
335
38
  UncachedRedirectClient: () => UncachedRedirectClient,
336
39
  WithMemoryCache: () => WithMemoryCache,
40
+ getSourceVariables: () => getSourceVariables,
41
+ getTargetVariableExpandedUrl: () => getTargetVariableExpandedUrl,
42
+ mergeQueryStrings: () => mergeQueryStrings,
337
43
  processUrl: () => processUrl
338
44
  });
339
45
  module.exports = __toCommonJS(src_exports);
@@ -600,22 +306,78 @@ var import_api = require("@uniformdev/context/api");
600
306
  // src/util/url.ts
601
307
  function processUrl(url) {
602
308
  var _a, _b, _c, _d, _e, _f;
603
- const matches = url.match(/^(https?:\/\/)?(([^:/?#]*)(?:(:[0-9]+))?)?([/]{0,1}[^?#]*)(\?[^#]*|)(#.*|)$/);
309
+ const matches = url.match(/^(https?:\/\/)?(([^:/?#]*)(?:(:[0-9]+))?)?([/]{0,1}[^?#]*)(\?[^#?]*|)(#.*|)$/);
310
+ const protocol = (_a = matches == null ? void 0 : matches[1]) != null ? _a : "";
311
+ const domain = (_b = matches == null ? void 0 : matches[3]) != null ? _b : "";
312
+ const port = (_c = matches == null ? void 0 : matches[4]) != null ? _c : "";
313
+ const path = (_d = matches == null ? void 0 : matches[5].replace(/\/+$/g, "")) != null ? _d : "";
314
+ const query = (_e = matches == null ? void 0 : matches[6]) != null ? _e : "";
315
+ const fragment = (_f = matches == null ? void 0 : matches[7]) != null ? _f : "";
604
316
  return {
605
- url,
606
- protocol: (_a = matches == null ? void 0 : matches[1]) != null ? _a : "",
607
- domain: (_b = matches == null ? void 0 : matches[3]) != null ? _b : "",
608
- port: (_c = matches == null ? void 0 : matches[4]) != null ? _c : "",
609
- path: (_d = matches == null ? void 0 : matches[5]) != null ? _d : "",
610
- query: (_e = matches == null ? void 0 : matches[6]) != null ? _e : "",
611
- fragment: (_f = matches == null ? void 0 : matches[7]) != null ? _f : ""
317
+ url: `${protocol}${domain}${port}${path}${query}${fragment}`,
318
+ protocol,
319
+ domain,
320
+ port,
321
+ path,
322
+ query,
323
+ fragment
612
324
  };
613
325
  }
614
326
 
327
+ // src/util/process.ts
328
+ function getTargetVariableExpandedUrl(url, redirectDefinition, isVariable) {
329
+ const processedTarget = processUrl(redirectDefinition.targetUrl);
330
+ const processedSource = processUrl(redirectDefinition.sourceUrl);
331
+ let finalUrlPath = processedTarget.path;
332
+ const processedUrl = processUrl(url);
333
+ const variables = getSourceVariables(processedUrl.path, processedSource.path, isVariable);
334
+ for (const variable in variables) {
335
+ finalUrlPath = finalUrlPath.replace(variable, variables[variable]);
336
+ }
337
+ let protocol = redirectDefinition.targetPreserveIncomingProtocol || processedTarget.protocol === "" ? processedUrl.protocol : processedTarget.protocol;
338
+ const domain = protocol !== "" ? redirectDefinition.targetPreserveIncomingDomain || processedTarget.domain === "" ? processedUrl.domain : processedTarget.domain : "";
339
+ if (domain === "" && protocol !== "") {
340
+ protocol = "";
341
+ }
342
+ const port = domain === "" ? "" : redirectDefinition.targetPreserveIncomingDomain || processedTarget.domain === "" ? processedUrl.port : processedTarget.port;
343
+ const query = redirectDefinition.sourceRetainQuerystring && redirectDefinition.targetMergeQuerystring ? mergeQueryStrings(processedUrl.query, processedTarget.query) : !redirectDefinition.targetMergeQuerystring && redirectDefinition.sourceRetainQuerystring ? processedUrl.query : processedTarget.query;
344
+ const fragment = redirectDefinition.sourceRetainQuerystring && redirectDefinition.targetMergeQuerystring ? mergeQueryStrings(processedUrl.fragment, processedTarget.fragment) : !redirectDefinition.targetMergeQuerystring && redirectDefinition.sourceRetainQuerystring ? processedUrl.fragment : processedTarget.fragment;
345
+ return `${protocol}${domain}${port}${finalUrlPath}${query}${fragment}`;
346
+ }
347
+ function getSourceVariables(path, source, isVariable = (pathSegment, isLast) => pathSegment.startsWith(":") || pathSegment === "*" && isLast) {
348
+ const variables = {};
349
+ const pathSegments = path.split("/");
350
+ const sourceSegments = source.split("/");
351
+ sourceSegments.forEach((sourceSegment, i) => {
352
+ if (pathSegments.length >= i && isVariable(sourceSegment, i === sourceSegments.length - 1)) {
353
+ variables[sourceSegment] = pathSegments[i];
354
+ }
355
+ });
356
+ return variables;
357
+ }
358
+ function mergeQueryStrings(qs1, qs2) {
359
+ let fragment = false;
360
+ if (qs1.startsWith("#")) {
361
+ fragment = true;
362
+ qs1 = qs1.substring(1);
363
+ }
364
+ if (qs2.startsWith("#")) {
365
+ fragment = true;
366
+ qs2 = qs2.substring(1);
367
+ }
368
+ const params1 = new URLSearchParams(qs1);
369
+ const params2 = new URLSearchParams(qs2);
370
+ const merged = new URLSearchParams([...params1, ...params2]).toString();
371
+ if (merged.length > 0)
372
+ return (fragment ? "#" : "?") + merged;
373
+ return "";
374
+ }
375
+
615
376
  // src/redirectClient.ts
616
377
  var _RedirectClient = class _RedirectClient extends import_api.ApiClient {
617
378
  constructor(options) {
618
379
  super(options);
380
+ // Get a single redirect by ID or project map id
619
381
  this.getRedirect = async (options) => {
620
382
  var _a;
621
383
  const { projectId } = this.options;
@@ -623,12 +385,14 @@ var _RedirectClient = class _RedirectClient extends import_api.ApiClient {
623
385
  const results = await this.apiClient(fetchUri);
624
386
  return (_a = results.redirects) == null ? void 0 : _a[0];
625
387
  };
388
+ // Get redirects by list of IDs, source URL, target URL, or search
626
389
  this.getRedirects = async (options) => {
627
390
  const { projectId } = this.options;
628
391
  const fetchUri = this.createUrl("/api/v1/redirect", { ...options, projectId });
629
392
  const results = await this.apiClient(fetchUri);
630
393
  return results;
631
394
  };
395
+ // Assemble a trie powered search structure, used to have instant resolution of redirects. Note, result set may be large.
632
396
  this.getRedirectTrie = async (options) => {
633
397
  var _a, _b;
634
398
  const { projectId } = this.options;
@@ -710,7 +474,7 @@ var _RedirectClient = class _RedirectClient extends import_api.ApiClient {
710
474
  return _RedirectClient.processDefinitionToResults(
711
475
  processedUrl,
712
476
  redirect,
713
- _RedirectClient.getSourceVariables(
477
+ getSourceVariables(
714
478
  processedUrl.path,
715
479
  processUrl((options == null ? void 0 : options.reverse) ? redirect.redirect.targetUrl : redirect.redirect.sourceUrl).path
716
480
  ),
@@ -720,6 +484,8 @@ var _RedirectClient = class _RedirectClient extends import_api.ApiClient {
720
484
  const trie = await this.getRedirectTrie();
721
485
  return (_b = _RedirectClient.processHops(sanitizedUrl, trie, true, options)) == null ? void 0 : _b[0];
722
486
  };
487
+ // Caculate redirect matches based on an incoming URL with an option to use a trie storage structure to streamline future
488
+ // redirect resolutions. Note this may cause a large in memory load for large collections of redirect, off by default.
723
489
  this.processUrlAllMatches = async (url, options, useTrie) => {
724
490
  const sanitizedUrl = url.endsWith("/") ? url.replace(/\/+$/, "") : url;
725
491
  if (!useTrie) {
@@ -731,7 +497,7 @@ var _RedirectClient = class _RedirectClient extends import_api.ApiClient {
731
497
  return _RedirectClient.processDefinitionToResults(
732
498
  processedUrl,
733
499
  redirect,
734
- _RedirectClient.getSourceVariables(
500
+ getSourceVariables(
735
501
  processedUrl.path,
736
502
  processUrl((options == null ? void 0 : options.reverse) ? redirect.redirect.targetUrl : redirect.redirect.sourceUrl).path
737
503
  ),
@@ -752,6 +518,7 @@ var _RedirectClient = class _RedirectClient extends import_api.ApiClient {
752
518
  }
753
519
  }
754
520
  }
521
+ // Get all redirects in Uniform 500 at a time.
755
522
  async *getAllRedirects(orderBy = "updated_at desc") {
756
523
  var _a, _b;
757
524
  const { projectId } = this.options;
@@ -800,6 +567,8 @@ var _RedirectClient = class _RedirectClient extends import_api.ApiClient {
800
567
  }
801
568
  return await _RedirectClient.assemblingPromise;
802
569
  }
570
+ // Find all redirects involved for the current URL, this is for the case where a redirect definition leads to
571
+ // another redirect. This also involves cycle busting error handling
803
572
  static processHops(initialUrl, trie, bestMatch, options) {
804
573
  const url = (options == null ? void 0 : options.reverse) ? initialUrl.replace(/\/:/, "/~~") : initialUrl;
805
574
  const isCycle = (id, result) => {
@@ -868,7 +637,7 @@ var _RedirectClient = class _RedirectClient extends import_api.ApiClient {
868
637
  const redirect = definition == null ? void 0 : definition.redirect;
869
638
  if (redirect.sourceMustMatchDomain && processedUrl.domain !== processedResult.domain)
870
639
  return void 0;
871
- const finalUrl = (options == null ? void 0 : options.reverse) ? "n/a" : _RedirectClient.getTargetVariableExpandedUrl(processedUrl.url, redirect);
640
+ const finalUrl = (options == null ? void 0 : options.reverse) ? "n/a" : getTargetVariableExpandedUrl(processedUrl.url, redirect);
872
641
  return {
873
642
  url: finalUrl,
874
643
  definition,
@@ -894,56 +663,6 @@ var _RedirectClient = class _RedirectClient extends import_api.ApiClient {
894
663
  }
895
664
  return true;
896
665
  }
897
- static getTargetVariableExpandedUrl(url, redirectDefinition, isVariable) {
898
- const processedTarget = processUrl(redirectDefinition.targetUrl);
899
- const processedSource = processUrl(redirectDefinition.sourceUrl);
900
- let finalUrlPath = processedTarget.path;
901
- const processedUrl = processUrl(url);
902
- const variables = this.getSourceVariables(processedUrl.path, processedSource.path, isVariable);
903
- for (const variable in variables) {
904
- finalUrlPath = finalUrlPath.replace(variable, variables[variable]);
905
- }
906
- let protocol = redirectDefinition.targetPreserveIncomingProtocol || processedTarget.protocol === "" ? processedUrl.protocol : processedTarget.protocol;
907
- const domain = protocol !== "" ? redirectDefinition.targetPreserveIncomingDomain || processedTarget.domain === "" ? processedUrl.domain : processedTarget.domain : "";
908
- if (domain === "" && protocol !== "") {
909
- protocol = "";
910
- }
911
- const port = domain === "" ? "" : redirectDefinition.targetPreserveIncomingDomain || processedTarget.domain === "" ? processedUrl.port : processedTarget.port;
912
- const query = redirectDefinition.sourceRetainQuerystring && redirectDefinition.targetMergeQuerystring ? this.mergeQueryStrings(processedUrl.query, processedTarget.query) : !redirectDefinition.targetMergeQuerystring && redirectDefinition.sourceRetainQuerystring ? processedUrl.query : processedTarget.query;
913
- const fragment = redirectDefinition.sourceRetainQuerystring && redirectDefinition.targetMergeQuerystring ? this.mergeQueryStrings(processedUrl.fragment, processedTarget.fragment) : !redirectDefinition.targetMergeQuerystring && redirectDefinition.sourceRetainQuerystring ? processedUrl.fragment : processedTarget.fragment;
914
- return `${protocol}${domain}${port}${finalUrlPath}${query}${fragment}`;
915
- }
916
- static mergeQueryStrings(qs1, qs2) {
917
- let fragment = false;
918
- if (qs1.startsWith("#")) {
919
- fragment = true;
920
- qs1 = qs1.substring(1);
921
- }
922
- if (qs2.startsWith("#")) {
923
- fragment = true;
924
- qs2 = qs2.substring(1);
925
- }
926
- const params1 = new URLSearchParams(qs1);
927
- const params2 = new URLSearchParams(qs2);
928
- const merged = new URLSearchParams([...params1, ...params2]).toString();
929
- if (merged.length > 0)
930
- return (fragment ? "#" : "?") + merged;
931
- return "";
932
- }
933
- static getSourceVariables(path, source, isVariable = (pathSegment, isLast) => pathSegment.startsWith(":") || pathSegment === "*" && isLast) {
934
- const variables = {};
935
- const pathSegments = path.split("/");
936
- const sourceSegments = source.split("/");
937
- if (pathSegments.length !== sourceSegments.length && !source.endsWith("/*")) {
938
- throw new Error("Path and source have different numbers of path segments, must be the same");
939
- }
940
- sourceSegments.forEach((sourceSegment, i) => {
941
- if (isVariable(sourceSegment, i === sourceSegments.length - 1)) {
942
- variables[sourceSegment] = pathSegments[i];
943
- }
944
- });
945
- return variables;
946
- }
947
666
  };
948
667
  _RedirectClient.processUrlBestMatch = async (url, trie, options) => {
949
668
  var _a;
@@ -962,8 +681,6 @@ var UncachedRedirectClient = class extends RedirectClient {
962
681
 
963
682
  // src/util/RedirectFileConverter.ts
964
683
  var getDefaultClient = async () => {
965
- const dotenv = await Promise.resolve().then(() => __toESM(require_main()));
966
- dotenv.config();
967
684
  return new RedirectClient({
968
685
  apiKey: process.env.UNIFORM_API_KEY,
969
686
  apiHost: process.env.UNIFORM_BASE_URL,
@@ -1041,5 +758,8 @@ async function RedirectFileConverter({
1041
758
  RedirectFileConverter,
1042
759
  UncachedRedirectClient,
1043
760
  WithMemoryCache,
761
+ getSourceVariables,
762
+ getTargetVariableExpandedUrl,
763
+ mergeQueryStrings,
1044
764
  processUrl
1045
765
  });