redfireforge-cli 0.8.10 → 0.8.11

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 (2) hide show
  1. package/dist/redfireforge.mjs +123 -38
  2. package/package.json +1 -1
@@ -30809,42 +30809,121 @@ async function httpFetch(url, method, headers, body, signal) {
30809
30809
  }
30810
30810
  return proxyFetch(url, method, headers, body, signal);
30811
30811
  }
30812
- async function tauriFetch(url, method, headers, body, signal) {
30812
+ var _studioInvoke;
30813
+ var _pluginHttpFetch = null;
30814
+ function isStudioHttpFetchResponse(value) {
30815
+ return typeof value === "object" && value !== null && typeof value.status === "number" && typeof value.body === "string";
30816
+ }
30817
+ async function getStudioInvoke() {
30818
+ if (_studioInvoke !== void 0) return _studioInvoke;
30813
30819
  try {
30814
- const { fetch: tFetch } = await Promise.resolve().then(() => (init_dist_js(), dist_js_exports));
30815
- const opts = {
30816
- method,
30817
- headers
30818
- };
30819
- if (body && method !== "GET") {
30820
- opts.body = body;
30820
+ const { invoke: invoke2 } = await Promise.resolve().then(() => (init_core(), core_exports));
30821
+ _studioInvoke = (cmd, args) => invoke2(cmd, args);
30822
+ } catch {
30823
+ _studioInvoke = null;
30824
+ }
30825
+ return _studioInvoke;
30826
+ }
30827
+ function studioResponseToHttp(native, t0, tDone) {
30828
+ return {
30829
+ status: native.status,
30830
+ statusText: native.statusText ?? "",
30831
+ headers: native.headers ?? {},
30832
+ body: native.body ?? "",
30833
+ error: native.error,
30834
+ timing: {
30835
+ dnsLookup: 0,
30836
+ tcpConnect: 0,
30837
+ tlsHandshake: 0,
30838
+ ttfb: round2(tDone - t0),
30839
+ download: 0,
30840
+ total: round2(tDone - t0)
30821
30841
  }
30822
- if (signal) {
30823
- opts.signal = signal;
30842
+ };
30843
+ }
30844
+ async function tauriFetchViaPooledCommand(url, method, headers, body, signal) {
30845
+ if (signal?.aborted) {
30846
+ return { status: 0, statusText: "", headers: {}, body: "", error: "Aborted" };
30847
+ }
30848
+ const invoke2 = await getStudioInvoke();
30849
+ if (!invoke2) return null;
30850
+ const request = {
30851
+ url,
30852
+ method,
30853
+ headers,
30854
+ body: body && method !== "GET" && method !== "HEAD" ? body : void 0
30855
+ };
30856
+ const t0 = performance.now();
30857
+ const invokePromise = invoke2("studio_http_fetch", { request });
30858
+ const run2 = async () => {
30859
+ try {
30860
+ const native = await invokePromise;
30861
+ if (!isStudioHttpFetchResponse(native)) return null;
30862
+ return studioResponseToHttp(native, t0, performance.now());
30863
+ } catch {
30864
+ return null;
30824
30865
  }
30825
- const t0 = performance.now();
30826
- const response = await tFetch(url, opts);
30827
- const tFirstByte = performance.now();
30828
- const responseBody = await response.text();
30829
- const tDone = performance.now();
30830
- const responseHeaders = {};
30831
- response.headers.forEach((v, k) => {
30832
- responseHeaders[k] = v;
30833
- });
30834
- return {
30835
- status: response.status,
30836
- statusText: response.statusText,
30837
- headers: responseHeaders,
30838
- body: responseBody,
30839
- timing: {
30840
- dnsLookup: 0,
30841
- tcpConnect: 0,
30842
- tlsHandshake: 0,
30843
- ttfb: round2(tFirstByte - t0),
30844
- download: round2(tDone - tFirstByte),
30845
- total: round2(tDone - t0)
30846
- }
30866
+ };
30867
+ if (!signal) return run2();
30868
+ return new Promise((resolve6) => {
30869
+ const onAbort = () => {
30870
+ resolve6({ status: 0, statusText: "", headers: {}, body: "", error: "Aborted" });
30847
30871
  };
30872
+ signal.addEventListener("abort", onAbort, { once: true });
30873
+ void run2().then((result) => {
30874
+ signal.removeEventListener("abort", onAbort);
30875
+ if (signal.aborted) {
30876
+ resolve6({ status: 0, statusText: "", headers: {}, body: "", error: "Aborted" });
30877
+ return;
30878
+ }
30879
+ resolve6(result);
30880
+ });
30881
+ });
30882
+ }
30883
+ async function tauriFetchViaPlugin(url, method, headers, body, signal) {
30884
+ if (!_pluginHttpFetch) {
30885
+ const { fetch: tFetch } = await Promise.resolve().then(() => (init_dist_js(), dist_js_exports));
30886
+ _pluginHttpFetch = tFetch;
30887
+ }
30888
+ const opts = {
30889
+ method,
30890
+ headers
30891
+ };
30892
+ if (body && method !== "GET") {
30893
+ opts.body = body;
30894
+ }
30895
+ if (signal) {
30896
+ opts.signal = signal;
30897
+ }
30898
+ const t0 = performance.now();
30899
+ const response = await _pluginHttpFetch(url, opts);
30900
+ const tFirstByte = performance.now();
30901
+ const responseBody = await response.text();
30902
+ const tDone = performance.now();
30903
+ const responseHeaders = {};
30904
+ response.headers.forEach((v, k) => {
30905
+ responseHeaders[k] = v;
30906
+ });
30907
+ return {
30908
+ status: response.status,
30909
+ statusText: response.statusText,
30910
+ headers: responseHeaders,
30911
+ body: responseBody,
30912
+ timing: {
30913
+ dnsLookup: 0,
30914
+ tcpConnect: 0,
30915
+ tlsHandshake: 0,
30916
+ ttfb: round2(tFirstByte - t0),
30917
+ download: round2(tDone - tFirstByte),
30918
+ total: round2(tDone - t0)
30919
+ }
30920
+ };
30921
+ }
30922
+ async function tauriFetch(url, method, headers, body, signal) {
30923
+ try {
30924
+ const pooled = await tauriFetchViaPooledCommand(url, method, headers, body, signal);
30925
+ if (pooled) return pooled;
30926
+ return await tauriFetchViaPlugin(url, method, headers, body, signal);
30848
30927
  } catch (err) {
30849
30928
  return {
30850
30929
  status: 0,
@@ -31079,7 +31158,7 @@ function parseJwtExpiry(token) {
31079
31158
  return null;
31080
31159
  }
31081
31160
  }
31082
- async function acquireOAuth2Token(auth) {
31161
+ async function fetchOAuth2Token(auth) {
31083
31162
  if (!auth.tokenUrl || !auth.clientId || !auth.clientSecret) {
31084
31163
  throw new Error("OAuth2 requires tokenUrl, clientId, and clientSecret");
31085
31164
  }
@@ -31113,14 +31192,16 @@ var TokenManager = class {
31113
31192
  const nowSec = Math.floor(Date.now() / 1e3);
31114
31193
  return nowSec >= entry.expiresSec - TOKEN_EXPIRY_BUFFER_SEC;
31115
31194
  }
31116
- async getToken(scenario) {
31117
- if (scenario.auth?.type !== "oauth2") return void 0;
31118
- const key = this.credKey(scenario.auth);
31195
+ async getTokenForAuth(auth) {
31196
+ if (auth.type !== "oauth2") {
31197
+ throw new Error("getTokenForAuth requires oauth2 auth");
31198
+ }
31199
+ const key = this.credKey(auth);
31119
31200
  const cached = this.cache.get(key);
31120
31201
  if (cached && !this.isExpired(cached)) return cached.token;
31121
31202
  const inflight = this.pending.get(key);
31122
31203
  if (inflight) return inflight;
31123
- const refreshPromise = this.refresh(key, scenario.auth);
31204
+ const refreshPromise = this.refresh(key, auth);
31124
31205
  this.pending.set(key, refreshPromise);
31125
31206
  try {
31126
31207
  return await refreshPromise;
@@ -31128,8 +31209,12 @@ var TokenManager = class {
31128
31209
  this.pending.delete(key);
31129
31210
  }
31130
31211
  }
31212
+ async getToken(scenario) {
31213
+ if (scenario.auth?.type !== "oauth2") return void 0;
31214
+ return this.getTokenForAuth(scenario.auth);
31215
+ }
31131
31216
  async refresh(key, auth) {
31132
- const token = await acquireOAuth2Token(auth);
31217
+ const token = await fetchOAuth2Token(auth);
31133
31218
  const exp = parseJwtExpiry(token);
31134
31219
  const expiresSec = exp ?? Math.floor(Date.now() / 1e3) + 1800;
31135
31220
  this.cache.set(key, { token, expiresSec });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "redfireforge-cli",
3
- "version": "0.8.10",
3
+ "version": "0.8.11",
4
4
  "description": "RedfireForge CLI — API Performance Testing from the Command Line",
5
5
  "keywords": [
6
6
  "api",