@viasoftbr/shared-ui 0.0.7-2 → 0.0.7-4

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/services.cjs CHANGED
@@ -44,7 +44,8 @@ __export(services_exports, {
44
44
  setAccessToken: () => setAccessToken,
45
45
  setRefreshToken: () => setRefreshToken,
46
46
  subscribeToWebsocket: () => subscribeToWebsocket,
47
- userService: () => userService
47
+ userService: () => userService,
48
+ withAccessTokenQuery: () => withAccessTokenQuery
48
49
  });
49
50
  module.exports = __toCommonJS(services_exports);
50
51
 
@@ -2806,19 +2807,24 @@ function formatAxiosError(err) {
2806
2807
  return err instanceof Error ? err : new Error(String(err));
2807
2808
  }
2808
2809
  var fetchApi = {
2809
- getJson: async (path, params, headers) => {
2810
+ getJson: async (path, params, headersOrOptions) => {
2810
2811
  try {
2811
- const response = await (path.includes("/auth") ? authApi : api).get(path.replace("/auth", ""), { params, headers });
2812
+ const requestOptions = normalizeRequestOptions(params, headersOrOptions);
2813
+ const response = await (path.includes("/auth") ? authApi : api).get(path.replace("/auth", ""), {
2814
+ params: withTokenQueryParams(requestOptions),
2815
+ headers: requestOptions.headers
2816
+ });
2812
2817
  return response.data;
2813
2818
  } catch (e) {
2814
2819
  throw formatAxiosError(e);
2815
2820
  }
2816
2821
  },
2817
- getText: async (path, params, headers) => {
2822
+ getText: async (path, params, headersOrOptions) => {
2818
2823
  try {
2824
+ const requestOptions = normalizeRequestOptions(params, headersOrOptions);
2819
2825
  const response = await (path.includes("/auth") ? authApi : api).get(path.replace("/auth", ""), {
2820
- params,
2821
- headers,
2826
+ params: withTokenQueryParams(requestOptions),
2827
+ headers: requestOptions.headers,
2822
2828
  responseType: "text"
2823
2829
  });
2824
2830
  return response.data;
@@ -2826,78 +2832,152 @@ var fetchApi = {
2826
2832
  throw formatAxiosError(e);
2827
2833
  }
2828
2834
  },
2829
- getVoid: async (path, params, headers) => {
2835
+ getVoid: async (path, params, headersOrOptions) => {
2830
2836
  try {
2831
- await (path.includes("/auth") ? authApi : api).get(path.replace("/auth", ""), { params, headers });
2837
+ const requestOptions = normalizeRequestOptions(params, headersOrOptions);
2838
+ await (path.includes("/auth") ? authApi : api).get(path.replace("/auth", ""), {
2839
+ params: withTokenQueryParams(requestOptions),
2840
+ headers: requestOptions.headers
2841
+ });
2832
2842
  } catch (e) {
2833
2843
  throw formatAxiosError(e);
2834
2844
  }
2835
2845
  },
2836
- postJson: async (path, payload, headers) => {
2846
+ postJson: async (path, payload, headersOrOptions) => {
2837
2847
  try {
2838
- const response = await (path.includes("/auth") ? authApi : api).post(path.replace("/auth", ""), payload, { headers });
2848
+ const requestOptions = normalizeRequestOptions(void 0, headersOrOptions);
2849
+ const response = await (path.includes("/auth") ? authApi : api).post(path.replace("/auth", ""), payload, {
2850
+ headers: requestOptions.headers,
2851
+ params: withTokenQueryParams(requestOptions)
2852
+ });
2839
2853
  return response.data;
2840
2854
  } catch (e) {
2841
2855
  throw formatAxiosError(e);
2842
2856
  }
2843
2857
  },
2844
- patchJson: async (path, payload, headers) => {
2858
+ patchJson: async (path, payload, headersOrOptions) => {
2845
2859
  try {
2846
- const response = await (path.includes("/auth") ? authApi : api).patch(path.replace("/auth", ""), payload, { headers });
2860
+ const requestOptions = normalizeRequestOptions(void 0, headersOrOptions);
2861
+ const response = await (path.includes("/auth") ? authApi : api).patch(path.replace("/auth", ""), payload, {
2862
+ headers: requestOptions.headers,
2863
+ params: withTokenQueryParams(requestOptions)
2864
+ });
2847
2865
  return response.data;
2848
2866
  } catch (e) {
2849
2867
  throw formatAxiosError(e);
2850
2868
  }
2851
2869
  },
2852
- putJson: async (path, payload, headers) => {
2870
+ putJson: async (path, payload, headersOrOptions) => {
2853
2871
  try {
2854
- const response = await (path.includes("/auth") ? authApi : api).put(path.replace("/auth", ""), payload, { headers });
2872
+ const requestOptions = normalizeRequestOptions(void 0, headersOrOptions);
2873
+ const response = await (path.includes("/auth") ? authApi : api).put(path.replace("/auth", ""), payload, {
2874
+ headers: requestOptions.headers,
2875
+ params: withTokenQueryParams(requestOptions)
2876
+ });
2855
2877
  return response.data;
2856
2878
  } catch (e) {
2857
2879
  throw formatAxiosError(e);
2858
2880
  }
2859
2881
  },
2860
- deleteJson: async (path, headers) => {
2882
+ deleteJson: async (path, headersOrOptions) => {
2861
2883
  try {
2862
- const response = await (path.includes("/auth") ? authApi : api).delete(path.replace("/auth", ""), { headers });
2884
+ const requestOptions = normalizeRequestOptions(void 0, headersOrOptions);
2885
+ const response = await (path.includes("/auth") ? authApi : api).delete(path.replace("/auth", ""), {
2886
+ headers: requestOptions.headers,
2887
+ params: withTokenQueryParams(requestOptions)
2888
+ });
2863
2889
  return response.data;
2864
2890
  } catch (e) {
2865
2891
  throw formatAxiosError(e);
2866
2892
  }
2867
2893
  },
2868
- deleteVoid: async (path, headers) => {
2894
+ deleteVoid: async (path, headersOrOptions) => {
2869
2895
  try {
2870
- await (path.includes("/auth") ? authApi : api).delete(path.replace("/auth", ""), { headers });
2896
+ const requestOptions = normalizeRequestOptions(void 0, headersOrOptions);
2897
+ await (path.includes("/auth") ? authApi : api).delete(path.replace("/auth", ""), {
2898
+ headers: requestOptions.headers,
2899
+ params: withTokenQueryParams(requestOptions)
2900
+ });
2871
2901
  } catch (e) {
2872
2902
  throw formatAxiosError(e);
2873
2903
  }
2874
2904
  }
2875
2905
  };
2876
- function buildWsUrl(path = "/") {
2906
+ function buildWsUrl(path = "/", options = {}) {
2877
2907
  try {
2878
2908
  const origin2 = new URL(apiOrigin);
2879
2909
  origin2.protocol = origin2.protocol === "https:" ? "wss:" : "ws:";
2880
2910
  if (!path.startsWith("/"))
2881
2911
  path = "/" + path;
2882
2912
  origin2.pathname = path;
2883
- return origin2.toString();
2913
+ return withAccessTokenQuery(origin2.toString(), {
2914
+ headers: options.headers,
2915
+ params: options.query,
2916
+ token: options.token ?? options.bearerToken,
2917
+ tokenQueryParam: options.tokenQueryParam ?? options.bearerQueryParam,
2918
+ includeStoredToken: options.includeStoredToken
2919
+ });
2884
2920
  } catch (e) {
2885
2921
  const proto = apiOrigin.startsWith("https") ? "wss" : "ws";
2886
2922
  const host = apiOrigin.replace(/^https?:\/\//, "").replace(/\/$/, "");
2887
- return `${proto}://${host}${path.startsWith("/") ? path : "/" + path}`;
2923
+ return withAccessTokenQuery(
2924
+ `${proto}://${host}${path.startsWith("/") ? path : "/" + path}`,
2925
+ {
2926
+ headers: options.headers,
2927
+ params: options.query,
2928
+ token: options.token ?? options.bearerToken,
2929
+ tokenQueryParam: options.tokenQueryParam ?? options.bearerQueryParam,
2930
+ includeStoredToken: options.includeStoredToken
2931
+ }
2932
+ );
2888
2933
  }
2889
2934
  }
2890
- function appendWsQueryParam(url, key, value) {
2935
+ function extractBearerToken(headers, explicitToken) {
2936
+ if (explicitToken)
2937
+ return explicitToken;
2938
+ if (!headers)
2939
+ return null;
2940
+ const authHeader = headers.Authorization || headers.authorization;
2941
+ if (!authHeader)
2942
+ return null;
2943
+ const match = authHeader.match(/^Bearer\s+(.+)$/i);
2944
+ return match ? match[1] : null;
2945
+ }
2946
+ function resolveAuthToken(options = {}) {
2947
+ const explicitToken = options.token ?? options.bearerToken ?? null;
2948
+ const headerToken = extractBearerToken(options.headers, explicitToken);
2949
+ if (headerToken)
2950
+ return headerToken;
2951
+ if (options.includeStoredToken === false)
2952
+ return null;
2953
+ return getAccessToken();
2954
+ }
2955
+ function mergeQueryParams(params, key, value) {
2956
+ const nextParams = { ...params ?? {} };
2957
+ if (key && value)
2958
+ nextParams[key] = value;
2959
+ return Object.keys(nextParams).length > 0 ? nextParams : void 0;
2960
+ }
2961
+ function appendQueryParams(url, params) {
2962
+ if (!params || Object.keys(params).length === 0)
2963
+ return url;
2891
2964
  try {
2892
2965
  const parsed = new URL(
2893
2966
  url,
2894
2967
  typeof window !== "undefined" ? window.location.href : void 0
2895
2968
  );
2896
- parsed.searchParams.set(key, value);
2969
+ for (const [key, value] of Object.entries(params)) {
2970
+ if (value === void 0 || value === null)
2971
+ continue;
2972
+ parsed.searchParams.set(key, String(value));
2973
+ }
2897
2974
  return parsed.toString();
2898
2975
  } catch {
2976
+ const search = Object.entries(params).filter(([, value]) => value !== void 0 && value !== null).map(([key, value]) => `${encodeURIComponent(key)}=${encodeURIComponent(String(value))}`).join("&");
2977
+ if (!search)
2978
+ return url;
2899
2979
  const separator = url.includes("?") ? "&" : "?";
2900
- return `${url}${separator}${encodeURIComponent(key)}=${encodeURIComponent(value)}`;
2980
+ return `${url}${separator}${search}`;
2901
2981
  }
2902
2982
  }
2903
2983
  function normalizeProtocols(protocols) {
@@ -2905,6 +2985,39 @@ function normalizeProtocols(protocols) {
2905
2985
  return void 0;
2906
2986
  return Array.isArray(protocols) ? protocols.filter(Boolean) : [protocols];
2907
2987
  }
2988
+ function normalizeRequestOptions(params, headersOrOptions) {
2989
+ const maybeOptions = headersOrOptions;
2990
+ const hasOptionShape = Boolean(
2991
+ maybeOptions && ("headers" in maybeOptions || "params" in maybeOptions || "sendTokenInQuery" in maybeOptions || "token" in maybeOptions || "tokenQueryParam" in maybeOptions || "includeStoredToken" in maybeOptions)
2992
+ );
2993
+ if (hasOptionShape) {
2994
+ return {
2995
+ ...maybeOptions,
2996
+ params: { ...params ?? {}, ...maybeOptions?.params ?? {} }
2997
+ };
2998
+ }
2999
+ return {
3000
+ params,
3001
+ headers: headersOrOptions
3002
+ };
3003
+ }
3004
+ function withTokenQueryParams(options) {
3005
+ if (!options.sendTokenInQuery)
3006
+ return options.params;
3007
+ const token = resolveAuthToken(options);
3008
+ return mergeQueryParams(
3009
+ options.params,
3010
+ options.tokenQueryParam ?? "access_token",
3011
+ token
3012
+ );
3013
+ }
3014
+ function withAccessTokenQuery(url, options = {}) {
3015
+ const token = resolveAuthToken(options);
3016
+ return appendQueryParams(
3017
+ url,
3018
+ mergeQueryParams(options.params, options.tokenQueryParam ?? "access_token", token)
3019
+ );
3020
+ }
2908
3021
  async function encodeFfurl(settings) {
2909
3022
  const { ffurl } = await fetchApi.postJson("/auth/protocols/ffurl/encode", settings);
2910
3023
  return ffurl;
@@ -2913,27 +3026,30 @@ async function decodeFfurl(ffurl) {
2913
3026
  const { settings } = await fetchApi.postJson("/auth/protocols/ffurl/decode", { ffurl });
2914
3027
  return settings;
2915
3028
  }
2916
- function resolveWsBearerToken(options) {
2917
- if (options.bearerToken)
2918
- return options.bearerToken;
2919
- if (options.autoAuth)
2920
- return getAccessToken();
2921
- return null;
2922
- }
2923
3029
  function subscribeToWebsocket(url, onMessage, options = {}) {
2924
- const token = resolveWsBearerToken(options);
2925
- const strategy = options.bearerStrategy ?? "query";
3030
+ const bearerToken = resolveAuthToken({
3031
+ headers: options.headers,
3032
+ token: options.token,
3033
+ bearerToken: options.bearerToken,
3034
+ includeStoredToken: options.includeStoredToken
3035
+ });
3036
+ const bearerStrategy = options.tokenTransport ?? options.bearerStrategy ?? "query";
3037
+ let resolvedUrl = appendQueryParams(url, options.query);
2926
3038
  const protocols = normalizeProtocols(options.protocols) ?? [];
2927
- let resolvedUrl = url;
2928
- if (token) {
2929
- if (strategy === "protocol") {
2930
- protocols.push("bearer", token);
3039
+ if (options.headers && Object.keys(options.headers).length > 0) {
3040
+ console.warn(
3041
+ "WebSocket connections in browsers do not support custom HTTP headers. shared-ui will derive bearer auth from Authorization and forward it using query string or subprotocol."
3042
+ );
3043
+ }
3044
+ if (bearerToken) {
3045
+ if (bearerStrategy === "protocol") {
3046
+ protocols.push("bearer", bearerToken);
2931
3047
  } else {
2932
- resolvedUrl = appendWsQueryParam(
2933
- url,
2934
- options.bearerQueryParam ?? "access_token",
2935
- token
2936
- );
3048
+ resolvedUrl = withAccessTokenQuery(resolvedUrl, {
3049
+ token: bearerToken,
3050
+ tokenQueryParam: options.tokenQueryParam ?? options.bearerQueryParam,
3051
+ includeStoredToken: false
3052
+ });
2937
3053
  }
2938
3054
  }
2939
3055
  const socket = protocols.length > 0 ? new WebSocket(resolvedUrl, protocols) : new WebSocket(resolvedUrl);
@@ -2942,7 +3058,7 @@ function subscribeToWebsocket(url, onMessage, options = {}) {
2942
3058
  const data = JSON.parse(event.data);
2943
3059
  onMessage(data);
2944
3060
  } catch (e) {
2945
- console.error("WebSocket parse error", e);
3061
+ console.error("Parse error", e);
2946
3062
  }
2947
3063
  };
2948
3064
  socket.onerror = (err) => console.error("WebSocket error", err);
package/dist/services.js CHANGED
@@ -2766,19 +2766,24 @@ function formatAxiosError(err) {
2766
2766
  return err instanceof Error ? err : new Error(String(err));
2767
2767
  }
2768
2768
  var fetchApi = {
2769
- getJson: async (path, params, headers) => {
2769
+ getJson: async (path, params, headersOrOptions) => {
2770
2770
  try {
2771
- const response = await (path.includes("/auth") ? authApi : api).get(path.replace("/auth", ""), { params, headers });
2771
+ const requestOptions = normalizeRequestOptions(params, headersOrOptions);
2772
+ const response = await (path.includes("/auth") ? authApi : api).get(path.replace("/auth", ""), {
2773
+ params: withTokenQueryParams(requestOptions),
2774
+ headers: requestOptions.headers
2775
+ });
2772
2776
  return response.data;
2773
2777
  } catch (e) {
2774
2778
  throw formatAxiosError(e);
2775
2779
  }
2776
2780
  },
2777
- getText: async (path, params, headers) => {
2781
+ getText: async (path, params, headersOrOptions) => {
2778
2782
  try {
2783
+ const requestOptions = normalizeRequestOptions(params, headersOrOptions);
2779
2784
  const response = await (path.includes("/auth") ? authApi : api).get(path.replace("/auth", ""), {
2780
- params,
2781
- headers,
2785
+ params: withTokenQueryParams(requestOptions),
2786
+ headers: requestOptions.headers,
2782
2787
  responseType: "text"
2783
2788
  });
2784
2789
  return response.data;
@@ -2786,78 +2791,152 @@ var fetchApi = {
2786
2791
  throw formatAxiosError(e);
2787
2792
  }
2788
2793
  },
2789
- getVoid: async (path, params, headers) => {
2794
+ getVoid: async (path, params, headersOrOptions) => {
2790
2795
  try {
2791
- await (path.includes("/auth") ? authApi : api).get(path.replace("/auth", ""), { params, headers });
2796
+ const requestOptions = normalizeRequestOptions(params, headersOrOptions);
2797
+ await (path.includes("/auth") ? authApi : api).get(path.replace("/auth", ""), {
2798
+ params: withTokenQueryParams(requestOptions),
2799
+ headers: requestOptions.headers
2800
+ });
2792
2801
  } catch (e) {
2793
2802
  throw formatAxiosError(e);
2794
2803
  }
2795
2804
  },
2796
- postJson: async (path, payload, headers) => {
2805
+ postJson: async (path, payload, headersOrOptions) => {
2797
2806
  try {
2798
- const response = await (path.includes("/auth") ? authApi : api).post(path.replace("/auth", ""), payload, { headers });
2807
+ const requestOptions = normalizeRequestOptions(void 0, headersOrOptions);
2808
+ const response = await (path.includes("/auth") ? authApi : api).post(path.replace("/auth", ""), payload, {
2809
+ headers: requestOptions.headers,
2810
+ params: withTokenQueryParams(requestOptions)
2811
+ });
2799
2812
  return response.data;
2800
2813
  } catch (e) {
2801
2814
  throw formatAxiosError(e);
2802
2815
  }
2803
2816
  },
2804
- patchJson: async (path, payload, headers) => {
2817
+ patchJson: async (path, payload, headersOrOptions) => {
2805
2818
  try {
2806
- const response = await (path.includes("/auth") ? authApi : api).patch(path.replace("/auth", ""), payload, { headers });
2819
+ const requestOptions = normalizeRequestOptions(void 0, headersOrOptions);
2820
+ const response = await (path.includes("/auth") ? authApi : api).patch(path.replace("/auth", ""), payload, {
2821
+ headers: requestOptions.headers,
2822
+ params: withTokenQueryParams(requestOptions)
2823
+ });
2807
2824
  return response.data;
2808
2825
  } catch (e) {
2809
2826
  throw formatAxiosError(e);
2810
2827
  }
2811
2828
  },
2812
- putJson: async (path, payload, headers) => {
2829
+ putJson: async (path, payload, headersOrOptions) => {
2813
2830
  try {
2814
- const response = await (path.includes("/auth") ? authApi : api).put(path.replace("/auth", ""), payload, { headers });
2831
+ const requestOptions = normalizeRequestOptions(void 0, headersOrOptions);
2832
+ const response = await (path.includes("/auth") ? authApi : api).put(path.replace("/auth", ""), payload, {
2833
+ headers: requestOptions.headers,
2834
+ params: withTokenQueryParams(requestOptions)
2835
+ });
2815
2836
  return response.data;
2816
2837
  } catch (e) {
2817
2838
  throw formatAxiosError(e);
2818
2839
  }
2819
2840
  },
2820
- deleteJson: async (path, headers) => {
2841
+ deleteJson: async (path, headersOrOptions) => {
2821
2842
  try {
2822
- const response = await (path.includes("/auth") ? authApi : api).delete(path.replace("/auth", ""), { headers });
2843
+ const requestOptions = normalizeRequestOptions(void 0, headersOrOptions);
2844
+ const response = await (path.includes("/auth") ? authApi : api).delete(path.replace("/auth", ""), {
2845
+ headers: requestOptions.headers,
2846
+ params: withTokenQueryParams(requestOptions)
2847
+ });
2823
2848
  return response.data;
2824
2849
  } catch (e) {
2825
2850
  throw formatAxiosError(e);
2826
2851
  }
2827
2852
  },
2828
- deleteVoid: async (path, headers) => {
2853
+ deleteVoid: async (path, headersOrOptions) => {
2829
2854
  try {
2830
- await (path.includes("/auth") ? authApi : api).delete(path.replace("/auth", ""), { headers });
2855
+ const requestOptions = normalizeRequestOptions(void 0, headersOrOptions);
2856
+ await (path.includes("/auth") ? authApi : api).delete(path.replace("/auth", ""), {
2857
+ headers: requestOptions.headers,
2858
+ params: withTokenQueryParams(requestOptions)
2859
+ });
2831
2860
  } catch (e) {
2832
2861
  throw formatAxiosError(e);
2833
2862
  }
2834
2863
  }
2835
2864
  };
2836
- function buildWsUrl(path = "/") {
2865
+ function buildWsUrl(path = "/", options = {}) {
2837
2866
  try {
2838
2867
  const origin2 = new URL(apiOrigin);
2839
2868
  origin2.protocol = origin2.protocol === "https:" ? "wss:" : "ws:";
2840
2869
  if (!path.startsWith("/"))
2841
2870
  path = "/" + path;
2842
2871
  origin2.pathname = path;
2843
- return origin2.toString();
2872
+ return withAccessTokenQuery(origin2.toString(), {
2873
+ headers: options.headers,
2874
+ params: options.query,
2875
+ token: options.token ?? options.bearerToken,
2876
+ tokenQueryParam: options.tokenQueryParam ?? options.bearerQueryParam,
2877
+ includeStoredToken: options.includeStoredToken
2878
+ });
2844
2879
  } catch (e) {
2845
2880
  const proto = apiOrigin.startsWith("https") ? "wss" : "ws";
2846
2881
  const host = apiOrigin.replace(/^https?:\/\//, "").replace(/\/$/, "");
2847
- return `${proto}://${host}${path.startsWith("/") ? path : "/" + path}`;
2882
+ return withAccessTokenQuery(
2883
+ `${proto}://${host}${path.startsWith("/") ? path : "/" + path}`,
2884
+ {
2885
+ headers: options.headers,
2886
+ params: options.query,
2887
+ token: options.token ?? options.bearerToken,
2888
+ tokenQueryParam: options.tokenQueryParam ?? options.bearerQueryParam,
2889
+ includeStoredToken: options.includeStoredToken
2890
+ }
2891
+ );
2848
2892
  }
2849
2893
  }
2850
- function appendWsQueryParam(url, key, value) {
2894
+ function extractBearerToken(headers, explicitToken) {
2895
+ if (explicitToken)
2896
+ return explicitToken;
2897
+ if (!headers)
2898
+ return null;
2899
+ const authHeader = headers.Authorization || headers.authorization;
2900
+ if (!authHeader)
2901
+ return null;
2902
+ const match = authHeader.match(/^Bearer\s+(.+)$/i);
2903
+ return match ? match[1] : null;
2904
+ }
2905
+ function resolveAuthToken(options = {}) {
2906
+ const explicitToken = options.token ?? options.bearerToken ?? null;
2907
+ const headerToken = extractBearerToken(options.headers, explicitToken);
2908
+ if (headerToken)
2909
+ return headerToken;
2910
+ if (options.includeStoredToken === false)
2911
+ return null;
2912
+ return getAccessToken();
2913
+ }
2914
+ function mergeQueryParams(params, key, value) {
2915
+ const nextParams = { ...params ?? {} };
2916
+ if (key && value)
2917
+ nextParams[key] = value;
2918
+ return Object.keys(nextParams).length > 0 ? nextParams : void 0;
2919
+ }
2920
+ function appendQueryParams(url, params) {
2921
+ if (!params || Object.keys(params).length === 0)
2922
+ return url;
2851
2923
  try {
2852
2924
  const parsed = new URL(
2853
2925
  url,
2854
2926
  typeof window !== "undefined" ? window.location.href : void 0
2855
2927
  );
2856
- parsed.searchParams.set(key, value);
2928
+ for (const [key, value] of Object.entries(params)) {
2929
+ if (value === void 0 || value === null)
2930
+ continue;
2931
+ parsed.searchParams.set(key, String(value));
2932
+ }
2857
2933
  return parsed.toString();
2858
2934
  } catch {
2935
+ const search = Object.entries(params).filter(([, value]) => value !== void 0 && value !== null).map(([key, value]) => `${encodeURIComponent(key)}=${encodeURIComponent(String(value))}`).join("&");
2936
+ if (!search)
2937
+ return url;
2859
2938
  const separator = url.includes("?") ? "&" : "?";
2860
- return `${url}${separator}${encodeURIComponent(key)}=${encodeURIComponent(value)}`;
2939
+ return `${url}${separator}${search}`;
2861
2940
  }
2862
2941
  }
2863
2942
  function normalizeProtocols(protocols) {
@@ -2865,6 +2944,39 @@ function normalizeProtocols(protocols) {
2865
2944
  return void 0;
2866
2945
  return Array.isArray(protocols) ? protocols.filter(Boolean) : [protocols];
2867
2946
  }
2947
+ function normalizeRequestOptions(params, headersOrOptions) {
2948
+ const maybeOptions = headersOrOptions;
2949
+ const hasOptionShape = Boolean(
2950
+ maybeOptions && ("headers" in maybeOptions || "params" in maybeOptions || "sendTokenInQuery" in maybeOptions || "token" in maybeOptions || "tokenQueryParam" in maybeOptions || "includeStoredToken" in maybeOptions)
2951
+ );
2952
+ if (hasOptionShape) {
2953
+ return {
2954
+ ...maybeOptions,
2955
+ params: { ...params ?? {}, ...maybeOptions?.params ?? {} }
2956
+ };
2957
+ }
2958
+ return {
2959
+ params,
2960
+ headers: headersOrOptions
2961
+ };
2962
+ }
2963
+ function withTokenQueryParams(options) {
2964
+ if (!options.sendTokenInQuery)
2965
+ return options.params;
2966
+ const token = resolveAuthToken(options);
2967
+ return mergeQueryParams(
2968
+ options.params,
2969
+ options.tokenQueryParam ?? "access_token",
2970
+ token
2971
+ );
2972
+ }
2973
+ function withAccessTokenQuery(url, options = {}) {
2974
+ const token = resolveAuthToken(options);
2975
+ return appendQueryParams(
2976
+ url,
2977
+ mergeQueryParams(options.params, options.tokenQueryParam ?? "access_token", token)
2978
+ );
2979
+ }
2868
2980
  async function encodeFfurl(settings) {
2869
2981
  const { ffurl } = await fetchApi.postJson("/auth/protocols/ffurl/encode", settings);
2870
2982
  return ffurl;
@@ -2873,27 +2985,30 @@ async function decodeFfurl(ffurl) {
2873
2985
  const { settings } = await fetchApi.postJson("/auth/protocols/ffurl/decode", { ffurl });
2874
2986
  return settings;
2875
2987
  }
2876
- function resolveWsBearerToken(options) {
2877
- if (options.bearerToken)
2878
- return options.bearerToken;
2879
- if (options.autoAuth)
2880
- return getAccessToken();
2881
- return null;
2882
- }
2883
2988
  function subscribeToWebsocket(url, onMessage, options = {}) {
2884
- const token = resolveWsBearerToken(options);
2885
- const strategy = options.bearerStrategy ?? "query";
2989
+ const bearerToken = resolveAuthToken({
2990
+ headers: options.headers,
2991
+ token: options.token,
2992
+ bearerToken: options.bearerToken,
2993
+ includeStoredToken: options.includeStoredToken
2994
+ });
2995
+ const bearerStrategy = options.tokenTransport ?? options.bearerStrategy ?? "query";
2996
+ let resolvedUrl = appendQueryParams(url, options.query);
2886
2997
  const protocols = normalizeProtocols(options.protocols) ?? [];
2887
- let resolvedUrl = url;
2888
- if (token) {
2889
- if (strategy === "protocol") {
2890
- protocols.push("bearer", token);
2998
+ if (options.headers && Object.keys(options.headers).length > 0) {
2999
+ console.warn(
3000
+ "WebSocket connections in browsers do not support custom HTTP headers. shared-ui will derive bearer auth from Authorization and forward it using query string or subprotocol."
3001
+ );
3002
+ }
3003
+ if (bearerToken) {
3004
+ if (bearerStrategy === "protocol") {
3005
+ protocols.push("bearer", bearerToken);
2891
3006
  } else {
2892
- resolvedUrl = appendWsQueryParam(
2893
- url,
2894
- options.bearerQueryParam ?? "access_token",
2895
- token
2896
- );
3007
+ resolvedUrl = withAccessTokenQuery(resolvedUrl, {
3008
+ token: bearerToken,
3009
+ tokenQueryParam: options.tokenQueryParam ?? options.bearerQueryParam,
3010
+ includeStoredToken: false
3011
+ });
2897
3012
  }
2898
3013
  }
2899
3014
  const socket = protocols.length > 0 ? new WebSocket(resolvedUrl, protocols) : new WebSocket(resolvedUrl);
@@ -2902,7 +3017,7 @@ function subscribeToWebsocket(url, onMessage, options = {}) {
2902
3017
  const data = JSON.parse(event.data);
2903
3018
  onMessage(data);
2904
3019
  } catch (e) {
2905
- console.error("WebSocket parse error", e);
3020
+ console.error("Parse error", e);
2906
3021
  }
2907
3022
  };
2908
3023
  socket.onerror = (err) => console.error("WebSocket error", err);
@@ -3142,5 +3257,6 @@ export {
3142
3257
  setAccessToken,
3143
3258
  setRefreshToken,
3144
3259
  subscribeToWebsocket,
3145
- userService
3260
+ userService,
3261
+ withAccessTokenQuery
3146
3262
  };
@@ -25,31 +25,21 @@ export interface WebSocketData {
25
25
  };
26
26
  system: SystemInfo;
27
27
  }
28
+ export type AuthTokenTransport = 'query' | 'protocol';
29
+ export interface AuthTokenQueryOptions {
30
+ token?: string | null;
31
+ tokenQueryParam?: string;
32
+ includeStoredToken?: boolean;
33
+ }
28
34
  export interface WebSocketSubscribeOptions {
29
- /**
30
- * Token JWT Bearer explícito. Se fornecido, tem prioridade sobre autoAuth.
31
- */
35
+ headers?: Record<string, string>;
36
+ protocols?: string | string[];
37
+ query?: Record<string, string | number | boolean | null | undefined>;
38
+ tokenTransport?: AuthTokenTransport;
39
+ token?: string | null;
40
+ tokenQueryParam?: string;
41
+ includeStoredToken?: boolean;
32
42
  bearerToken?: string | null;
33
- /**
34
- * Quando `true`, usa automaticamente o accessToken armazenado (localStorage)
35
- * caso `bearerToken` não tenha sido fornecido.
36
- * @default false
37
- */
38
- autoAuth?: boolean;
39
- /**
40
- * Define como o token é enviado ao servidor.
41
- * - `'query'` → parâmetro de query string (padrão, ex.: `?access_token=...`)
42
- * - `'protocol'` → sub-protocolo WebSocket (`Sec-WebSocket-Protocol`)
43
- * @default 'query'
44
- */
45
- bearerStrategy?: 'query' | 'protocol';
46
- /**
47
- * Nome do parâmetro de query usado na estratégia `'query'`.
48
- * @default 'access_token'
49
- */
43
+ bearerStrategy?: AuthTokenTransport;
50
44
  bearerQueryParam?: string;
51
- /**
52
- * Sub-protocolos WebSocket adicionais.
53
- */
54
- protocols?: string | string[];
55
45
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@viasoftbr/shared-ui",
3
- "version": "0.0.7-2",
3
+ "version": "0.0.7-4",
4
4
  "main": "./dist/index.js",
5
5
  "types": "./dist/types/index.d.ts",
6
6
  "exports": {