@valbuild/server 0.60.11 → 0.60.12

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.
@@ -82,7 +82,7 @@ type ValServerOverrides = Partial<{
82
82
  *
83
83
  * @example "myorg/my-project"
84
84
  */
85
- valCloud: string;
85
+ remote: string;
86
86
  /**
87
87
  * After Val is enabled, redirect to this url.
88
88
  *
@@ -2560,7 +2560,7 @@ class ProxyValServer extends ValServer {
2560
2560
  };
2561
2561
  }
2562
2562
  const params = `commit=${encodeURIComponent(commit)}&root=${encodeURIComponent(this.apiOptions.root || "/")}&cwd=${encodeURIComponent(this.cwd)}`;
2563
- const url = new URL(`/v1/commit/${this.options.valName}/heads/${this.options.git.branch}/~?${params}`, this.options.valContentUrl);
2563
+ const url = new URL(`/v1/commit/${this.options.remote}/heads/${this.options.git.branch}/~?${params}`, this.options.valContentUrl);
2564
2564
 
2565
2565
  // Creates a fresh copy of the fs. We cannot touch the existing fs, since there might be parallel operations?
2566
2566
  // We could perhaps free up the other fs while doing this operation, but uncertain if we can actually do that and if that would actually help on memory.
@@ -2621,7 +2621,7 @@ class ProxyValServer extends ValServer {
2621
2621
  commit,
2622
2622
  cwd: this.cwd
2623
2623
  });
2624
- const url = new URL(`/v1/fs/${this.options.valName}/heads/${this.options.git.branch}/~?${params}`, this.options.valContentUrl);
2624
+ const url = new URL(`/v1/fs/${this.options.remote}/heads/${this.options.git.branch}/~?${params}`, this.options.valContentUrl);
2625
2625
  try {
2626
2626
  const fetchRes = await fetch(url, {
2627
2627
  headers: getAuthHeaders(token, "application/json")
@@ -2800,7 +2800,7 @@ class ProxyValServer extends ValServer {
2800
2800
  }
2801
2801
  async session(cookies) {
2802
2802
  return withAuth(this.options.valSecret, cookies, "session", async data => {
2803
- const url = new URL(`/api/val/${this.options.valName}/auth/session`, this.options.valBuildUrl);
2803
+ const url = new URL(`/api/val/${this.options.remote}/auth/session`, this.options.valBuildUrl);
2804
2804
  const fetchRes = await fetch(url, {
2805
2805
  headers: getAuthHeaders(data.token, "application/json")
2806
2806
  });
@@ -2825,7 +2825,7 @@ class ProxyValServer extends ValServer {
2825
2825
  });
2826
2826
  }
2827
2827
  async consumeCode(code) {
2828
- const url = new URL(`/api/val/${this.options.valName}/auth/token`, this.options.valBuildUrl);
2828
+ const url = new URL(`/api/val/${this.options.remote}/auth/token`, this.options.valBuildUrl);
2829
2829
  url.searchParams.set("code", encodeURIComponent(code));
2830
2830
  return fetch(url, {
2831
2831
  method: "POST",
@@ -2851,13 +2851,13 @@ class ProxyValServer extends ValServer {
2851
2851
  });
2852
2852
  }
2853
2853
  getAuthorizeUrl(publicValApiRoute, token) {
2854
- const url = new URL(`/auth/${this.options.valName}/authorize`, this.options.valBuildUrl);
2854
+ const url = new URL(`/auth/${this.options.remote}/authorize`, this.options.valBuildUrl);
2855
2855
  url.searchParams.set("redirect_uri", encodeURIComponent(`${publicValApiRoute}/callback`));
2856
2856
  url.searchParams.set("state", token);
2857
2857
  return url.toString();
2858
2858
  }
2859
2859
  getAppErrorUrl(error) {
2860
- const url = new URL(`/auth/${this.options.valName}/authorize`, this.options.valBuildUrl);
2860
+ const url = new URL(`/auth/${this.options.remote}/authorize`, this.options.valBuildUrl);
2861
2861
  url.searchParams.set("error", encodeURIComponent(error));
2862
2862
  return url.toString();
2863
2863
  }
@@ -2872,7 +2872,7 @@ class ProxyValServer extends ValServer {
2872
2872
  token
2873
2873
  }) => {
2874
2874
  const patchIds = query.id || [];
2875
- const url = new URL(`/v1/patches/${this.options.valName}/heads/${this.options.git.branch}/~`, this.options.valContentUrl);
2875
+ const url = new URL(`/v1/patches/${this.options.remote}/heads/${this.options.git.branch}/~`, this.options.valContentUrl);
2876
2876
  const fetchRes = await fetch(url, {
2877
2877
  method: "DELETE",
2878
2878
  headers: getAuthHeaders(token, "application/json"),
@@ -2905,7 +2905,7 @@ class ProxyValServer extends ValServer {
2905
2905
  }
2906
2906
  const patchIds = query.id || [];
2907
2907
  const params = patchIds.length > 0 ? `commit=${encodeURIComponent(commit)}&${patchIds.map(id => `id=${encodeURIComponent(id)}`).join("&")}` : `commit=${encodeURIComponent(commit)}`;
2908
- const url = new URL(`/v1/patches/${this.options.valName}/heads/${this.options.git.branch}/~?${params}`, this.options.valContentUrl);
2908
+ const url = new URL(`/v1/patches/${this.options.remote}/heads/${this.options.git.branch}/~?${params}`, this.options.valContentUrl);
2909
2909
  // Proxy patch to val.build
2910
2910
  const fetchRes = await fetch(url, {
2911
2911
  method: "GET",
@@ -2949,7 +2949,7 @@ class ProxyValServer extends ValServer {
2949
2949
  };
2950
2950
  }
2951
2951
  const patches = parsedPatches.data;
2952
- const url = new URL(`/v1/patches/${this.options.valName}/heads/${this.options.git.branch}/~?${params}`, this.options.valContentUrl);
2952
+ const url = new URL(`/v1/patches/${this.options.remote}/heads/${this.options.git.branch}/~?${params}`, this.options.valContentUrl);
2953
2953
  // Proxy patch to val.build
2954
2954
  const fetchRes = await fetch(url, {
2955
2955
  method: "POST",
@@ -2968,7 +2968,7 @@ class ProxyValServer extends ValServer {
2968
2968
  }
2969
2969
  async getFiles(filePath, query, cookies) {
2970
2970
  return withAuth(this.options.valSecret, cookies, "getFiles", async data => {
2971
- const url = new URL(`/v1/files/${this.options.valName}${filePath}`, this.options.valContentUrl);
2971
+ const url = new URL(`/v1/files/${this.options.remote}${filePath}`, this.options.valContentUrl);
2972
2972
  if (typeof query.sha256 === "string") {
2973
2973
  url.searchParams.append("sha256", query.sha256);
2974
2974
  } else {
@@ -3253,9 +3253,9 @@ async function initHandlerOptions(route, opts) {
3253
3253
  if (!maybeGitBranch) {
3254
3254
  throw new Error("VAL_GIT_BRANCH env var must be set in proxy mode");
3255
3255
  }
3256
- const maybeValName = opts.valCloud || process.env.VAL_CLOUD_NAME || process.env.VAL_NAME; // VAL_NAME is deprecated
3257
- if (!maybeValName) {
3258
- throw new Error("VAL_CLOUD_NAME env var must be set in proxy mode");
3256
+ const maybeValRemote = opts.remote || process.env.VAL_REMOTE;
3257
+ if (!maybeValRemote) {
3258
+ throw new Error("Proxy mode does not work unless the 'remote' option in val.config is defined or the VAL_REMOTE env var is set.");
3259
3259
  }
3260
3260
  return {
3261
3261
  mode: "proxy",
@@ -3268,7 +3268,7 @@ async function initHandlerOptions(route, opts) {
3268
3268
  commit: maybeGitCommit,
3269
3269
  branch: maybeGitBranch
3270
3270
  },
3271
- valName: maybeValName,
3271
+ remote: maybeValRemote,
3272
3272
  valEnableRedirectUrl: opts.valEnableRedirectUrl || process.env.VAL_ENABLE_REDIRECT_URL,
3273
3273
  valDisableRedirectUrl: opts.valDisableRedirectUrl || process.env.VAL_DISABLE_REDIRECT_URL
3274
3274
  };
@@ -2560,7 +2560,7 @@ class ProxyValServer extends ValServer {
2560
2560
  };
2561
2561
  }
2562
2562
  const params = `commit=${encodeURIComponent(commit)}&root=${encodeURIComponent(this.apiOptions.root || "/")}&cwd=${encodeURIComponent(this.cwd)}`;
2563
- const url = new URL(`/v1/commit/${this.options.valName}/heads/${this.options.git.branch}/~?${params}`, this.options.valContentUrl);
2563
+ const url = new URL(`/v1/commit/${this.options.remote}/heads/${this.options.git.branch}/~?${params}`, this.options.valContentUrl);
2564
2564
 
2565
2565
  // Creates a fresh copy of the fs. We cannot touch the existing fs, since there might be parallel operations?
2566
2566
  // We could perhaps free up the other fs while doing this operation, but uncertain if we can actually do that and if that would actually help on memory.
@@ -2621,7 +2621,7 @@ class ProxyValServer extends ValServer {
2621
2621
  commit,
2622
2622
  cwd: this.cwd
2623
2623
  });
2624
- const url = new URL(`/v1/fs/${this.options.valName}/heads/${this.options.git.branch}/~?${params}`, this.options.valContentUrl);
2624
+ const url = new URL(`/v1/fs/${this.options.remote}/heads/${this.options.git.branch}/~?${params}`, this.options.valContentUrl);
2625
2625
  try {
2626
2626
  const fetchRes = await fetch(url, {
2627
2627
  headers: getAuthHeaders(token, "application/json")
@@ -2800,7 +2800,7 @@ class ProxyValServer extends ValServer {
2800
2800
  }
2801
2801
  async session(cookies) {
2802
2802
  return withAuth(this.options.valSecret, cookies, "session", async data => {
2803
- const url = new URL(`/api/val/${this.options.valName}/auth/session`, this.options.valBuildUrl);
2803
+ const url = new URL(`/api/val/${this.options.remote}/auth/session`, this.options.valBuildUrl);
2804
2804
  const fetchRes = await fetch(url, {
2805
2805
  headers: getAuthHeaders(data.token, "application/json")
2806
2806
  });
@@ -2825,7 +2825,7 @@ class ProxyValServer extends ValServer {
2825
2825
  });
2826
2826
  }
2827
2827
  async consumeCode(code) {
2828
- const url = new URL(`/api/val/${this.options.valName}/auth/token`, this.options.valBuildUrl);
2828
+ const url = new URL(`/api/val/${this.options.remote}/auth/token`, this.options.valBuildUrl);
2829
2829
  url.searchParams.set("code", encodeURIComponent(code));
2830
2830
  return fetch(url, {
2831
2831
  method: "POST",
@@ -2851,13 +2851,13 @@ class ProxyValServer extends ValServer {
2851
2851
  });
2852
2852
  }
2853
2853
  getAuthorizeUrl(publicValApiRoute, token) {
2854
- const url = new URL(`/auth/${this.options.valName}/authorize`, this.options.valBuildUrl);
2854
+ const url = new URL(`/auth/${this.options.remote}/authorize`, this.options.valBuildUrl);
2855
2855
  url.searchParams.set("redirect_uri", encodeURIComponent(`${publicValApiRoute}/callback`));
2856
2856
  url.searchParams.set("state", token);
2857
2857
  return url.toString();
2858
2858
  }
2859
2859
  getAppErrorUrl(error) {
2860
- const url = new URL(`/auth/${this.options.valName}/authorize`, this.options.valBuildUrl);
2860
+ const url = new URL(`/auth/${this.options.remote}/authorize`, this.options.valBuildUrl);
2861
2861
  url.searchParams.set("error", encodeURIComponent(error));
2862
2862
  return url.toString();
2863
2863
  }
@@ -2872,7 +2872,7 @@ class ProxyValServer extends ValServer {
2872
2872
  token
2873
2873
  }) => {
2874
2874
  const patchIds = query.id || [];
2875
- const url = new URL(`/v1/patches/${this.options.valName}/heads/${this.options.git.branch}/~`, this.options.valContentUrl);
2875
+ const url = new URL(`/v1/patches/${this.options.remote}/heads/${this.options.git.branch}/~`, this.options.valContentUrl);
2876
2876
  const fetchRes = await fetch(url, {
2877
2877
  method: "DELETE",
2878
2878
  headers: getAuthHeaders(token, "application/json"),
@@ -2905,7 +2905,7 @@ class ProxyValServer extends ValServer {
2905
2905
  }
2906
2906
  const patchIds = query.id || [];
2907
2907
  const params = patchIds.length > 0 ? `commit=${encodeURIComponent(commit)}&${patchIds.map(id => `id=${encodeURIComponent(id)}`).join("&")}` : `commit=${encodeURIComponent(commit)}`;
2908
- const url = new URL(`/v1/patches/${this.options.valName}/heads/${this.options.git.branch}/~?${params}`, this.options.valContentUrl);
2908
+ const url = new URL(`/v1/patches/${this.options.remote}/heads/${this.options.git.branch}/~?${params}`, this.options.valContentUrl);
2909
2909
  // Proxy patch to val.build
2910
2910
  const fetchRes = await fetch(url, {
2911
2911
  method: "GET",
@@ -2949,7 +2949,7 @@ class ProxyValServer extends ValServer {
2949
2949
  };
2950
2950
  }
2951
2951
  const patches = parsedPatches.data;
2952
- const url = new URL(`/v1/patches/${this.options.valName}/heads/${this.options.git.branch}/~?${params}`, this.options.valContentUrl);
2952
+ const url = new URL(`/v1/patches/${this.options.remote}/heads/${this.options.git.branch}/~?${params}`, this.options.valContentUrl);
2953
2953
  // Proxy patch to val.build
2954
2954
  const fetchRes = await fetch(url, {
2955
2955
  method: "POST",
@@ -2968,7 +2968,7 @@ class ProxyValServer extends ValServer {
2968
2968
  }
2969
2969
  async getFiles(filePath, query, cookies) {
2970
2970
  return withAuth(this.options.valSecret, cookies, "getFiles", async data => {
2971
- const url = new URL(`/v1/files/${this.options.valName}${filePath}`, this.options.valContentUrl);
2971
+ const url = new URL(`/v1/files/${this.options.remote}${filePath}`, this.options.valContentUrl);
2972
2972
  if (typeof query.sha256 === "string") {
2973
2973
  url.searchParams.append("sha256", query.sha256);
2974
2974
  } else {
@@ -3253,9 +3253,9 @@ async function initHandlerOptions(route, opts) {
3253
3253
  if (!maybeGitBranch) {
3254
3254
  throw new Error("VAL_GIT_BRANCH env var must be set in proxy mode");
3255
3255
  }
3256
- const maybeValName = opts.valCloud || process.env.VAL_CLOUD_NAME || process.env.VAL_NAME; // VAL_NAME is deprecated
3257
- if (!maybeValName) {
3258
- throw new Error("VAL_CLOUD_NAME env var must be set in proxy mode");
3256
+ const maybeValRemote = opts.remote || process.env.VAL_REMOTE;
3257
+ if (!maybeValRemote) {
3258
+ throw new Error("Proxy mode does not work unless the 'remote' option in val.config is defined or the VAL_REMOTE env var is set.");
3259
3259
  }
3260
3260
  return {
3261
3261
  mode: "proxy",
@@ -3268,7 +3268,7 @@ async function initHandlerOptions(route, opts) {
3268
3268
  commit: maybeGitCommit,
3269
3269
  branch: maybeGitBranch
3270
3270
  },
3271
- valName: maybeValName,
3271
+ remote: maybeValRemote,
3272
3272
  valEnableRedirectUrl: opts.valEnableRedirectUrl || process.env.VAL_ENABLE_REDIRECT_URL,
3273
3273
  valDisableRedirectUrl: opts.valDisableRedirectUrl || process.env.VAL_DISABLE_REDIRECT_URL
3274
3274
  };
@@ -2529,7 +2529,7 @@ class ProxyValServer extends ValServer {
2529
2529
  };
2530
2530
  }
2531
2531
  const params = `commit=${encodeURIComponent(commit)}&root=${encodeURIComponent(this.apiOptions.root || "/")}&cwd=${encodeURIComponent(this.cwd)}`;
2532
- const url = new URL(`/v1/commit/${this.options.valName}/heads/${this.options.git.branch}/~?${params}`, this.options.valContentUrl);
2532
+ const url = new URL(`/v1/commit/${this.options.remote}/heads/${this.options.git.branch}/~?${params}`, this.options.valContentUrl);
2533
2533
 
2534
2534
  // Creates a fresh copy of the fs. We cannot touch the existing fs, since there might be parallel operations?
2535
2535
  // We could perhaps free up the other fs while doing this operation, but uncertain if we can actually do that and if that would actually help on memory.
@@ -2590,7 +2590,7 @@ class ProxyValServer extends ValServer {
2590
2590
  commit,
2591
2591
  cwd: this.cwd
2592
2592
  });
2593
- const url = new URL(`/v1/fs/${this.options.valName}/heads/${this.options.git.branch}/~?${params}`, this.options.valContentUrl);
2593
+ const url = new URL(`/v1/fs/${this.options.remote}/heads/${this.options.git.branch}/~?${params}`, this.options.valContentUrl);
2594
2594
  try {
2595
2595
  const fetchRes = await fetch(url, {
2596
2596
  headers: getAuthHeaders(token, "application/json")
@@ -2769,7 +2769,7 @@ class ProxyValServer extends ValServer {
2769
2769
  }
2770
2770
  async session(cookies) {
2771
2771
  return withAuth(this.options.valSecret, cookies, "session", async data => {
2772
- const url = new URL(`/api/val/${this.options.valName}/auth/session`, this.options.valBuildUrl);
2772
+ const url = new URL(`/api/val/${this.options.remote}/auth/session`, this.options.valBuildUrl);
2773
2773
  const fetchRes = await fetch(url, {
2774
2774
  headers: getAuthHeaders(data.token, "application/json")
2775
2775
  });
@@ -2794,7 +2794,7 @@ class ProxyValServer extends ValServer {
2794
2794
  });
2795
2795
  }
2796
2796
  async consumeCode(code) {
2797
- const url = new URL(`/api/val/${this.options.valName}/auth/token`, this.options.valBuildUrl);
2797
+ const url = new URL(`/api/val/${this.options.remote}/auth/token`, this.options.valBuildUrl);
2798
2798
  url.searchParams.set("code", encodeURIComponent(code));
2799
2799
  return fetch(url, {
2800
2800
  method: "POST",
@@ -2820,13 +2820,13 @@ class ProxyValServer extends ValServer {
2820
2820
  });
2821
2821
  }
2822
2822
  getAuthorizeUrl(publicValApiRoute, token) {
2823
- const url = new URL(`/auth/${this.options.valName}/authorize`, this.options.valBuildUrl);
2823
+ const url = new URL(`/auth/${this.options.remote}/authorize`, this.options.valBuildUrl);
2824
2824
  url.searchParams.set("redirect_uri", encodeURIComponent(`${publicValApiRoute}/callback`));
2825
2825
  url.searchParams.set("state", token);
2826
2826
  return url.toString();
2827
2827
  }
2828
2828
  getAppErrorUrl(error) {
2829
- const url = new URL(`/auth/${this.options.valName}/authorize`, this.options.valBuildUrl);
2829
+ const url = new URL(`/auth/${this.options.remote}/authorize`, this.options.valBuildUrl);
2830
2830
  url.searchParams.set("error", encodeURIComponent(error));
2831
2831
  return url.toString();
2832
2832
  }
@@ -2841,7 +2841,7 @@ class ProxyValServer extends ValServer {
2841
2841
  token
2842
2842
  }) => {
2843
2843
  const patchIds = query.id || [];
2844
- const url = new URL(`/v1/patches/${this.options.valName}/heads/${this.options.git.branch}/~`, this.options.valContentUrl);
2844
+ const url = new URL(`/v1/patches/${this.options.remote}/heads/${this.options.git.branch}/~`, this.options.valContentUrl);
2845
2845
  const fetchRes = await fetch(url, {
2846
2846
  method: "DELETE",
2847
2847
  headers: getAuthHeaders(token, "application/json"),
@@ -2874,7 +2874,7 @@ class ProxyValServer extends ValServer {
2874
2874
  }
2875
2875
  const patchIds = query.id || [];
2876
2876
  const params = patchIds.length > 0 ? `commit=${encodeURIComponent(commit)}&${patchIds.map(id => `id=${encodeURIComponent(id)}`).join("&")}` : `commit=${encodeURIComponent(commit)}`;
2877
- const url = new URL(`/v1/patches/${this.options.valName}/heads/${this.options.git.branch}/~?${params}`, this.options.valContentUrl);
2877
+ const url = new URL(`/v1/patches/${this.options.remote}/heads/${this.options.git.branch}/~?${params}`, this.options.valContentUrl);
2878
2878
  // Proxy patch to val.build
2879
2879
  const fetchRes = await fetch(url, {
2880
2880
  method: "GET",
@@ -2918,7 +2918,7 @@ class ProxyValServer extends ValServer {
2918
2918
  };
2919
2919
  }
2920
2920
  const patches = parsedPatches.data;
2921
- const url = new URL(`/v1/patches/${this.options.valName}/heads/${this.options.git.branch}/~?${params}`, this.options.valContentUrl);
2921
+ const url = new URL(`/v1/patches/${this.options.remote}/heads/${this.options.git.branch}/~?${params}`, this.options.valContentUrl);
2922
2922
  // Proxy patch to val.build
2923
2923
  const fetchRes = await fetch(url, {
2924
2924
  method: "POST",
@@ -2937,7 +2937,7 @@ class ProxyValServer extends ValServer {
2937
2937
  }
2938
2938
  async getFiles(filePath, query, cookies) {
2939
2939
  return withAuth(this.options.valSecret, cookies, "getFiles", async data => {
2940
- const url = new URL(`/v1/files/${this.options.valName}${filePath}`, this.options.valContentUrl);
2940
+ const url = new URL(`/v1/files/${this.options.remote}${filePath}`, this.options.valContentUrl);
2941
2941
  if (typeof query.sha256 === "string") {
2942
2942
  url.searchParams.append("sha256", query.sha256);
2943
2943
  } else {
@@ -3222,9 +3222,9 @@ async function initHandlerOptions(route, opts) {
3222
3222
  if (!maybeGitBranch) {
3223
3223
  throw new Error("VAL_GIT_BRANCH env var must be set in proxy mode");
3224
3224
  }
3225
- const maybeValName = opts.valCloud || process.env.VAL_CLOUD_NAME || process.env.VAL_NAME; // VAL_NAME is deprecated
3226
- if (!maybeValName) {
3227
- throw new Error("VAL_CLOUD_NAME env var must be set in proxy mode");
3225
+ const maybeValRemote = opts.remote || process.env.VAL_REMOTE;
3226
+ if (!maybeValRemote) {
3227
+ throw new Error("Proxy mode does not work unless the 'remote' option in val.config is defined or the VAL_REMOTE env var is set.");
3228
3228
  }
3229
3229
  return {
3230
3230
  mode: "proxy",
@@ -3237,7 +3237,7 @@ async function initHandlerOptions(route, opts) {
3237
3237
  commit: maybeGitCommit,
3238
3238
  branch: maybeGitBranch
3239
3239
  },
3240
- valName: maybeValName,
3240
+ remote: maybeValRemote,
3241
3241
  valEnableRedirectUrl: opts.valEnableRedirectUrl || process.env.VAL_ENABLE_REDIRECT_URL,
3242
3242
  valDisableRedirectUrl: opts.valDisableRedirectUrl || process.env.VAL_DISABLE_REDIRECT_URL
3243
3243
  };
package/package.json CHANGED
@@ -12,7 +12,7 @@
12
12
  "./package.json": "./package.json"
13
13
  },
14
14
  "types": "dist/valbuild-server.cjs.d.ts",
15
- "version": "0.60.11",
15
+ "version": "0.60.12",
16
16
  "scripts": {
17
17
  "typecheck": "tsc --noEmit",
18
18
  "test": "jest",
@@ -24,9 +24,9 @@
24
24
  "concurrently": "^7.6.0"
25
25
  },
26
26
  "dependencies": {
27
- "@valbuild/core": "~0.60.11",
28
- "@valbuild/shared": "~0.60.11",
29
- "@valbuild/ui": "~0.60.11",
27
+ "@valbuild/core": "~0.60.12",
28
+ "@valbuild/shared": "~0.60.12",
29
+ "@valbuild/ui": "~0.60.12",
30
30
  "express": "^4.18.2",
31
31
  "image-size": "^1.0.2",
32
32
  "minimatch": "^3.0.4",