@webority/mobile-core 0.0.24 → 0.0.25

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.
@@ -0,0 +1,21 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.sendFormDataAsMultipart = void 0;
7
+ /**
8
+ * The clients default to a JSON content type, and axios then serialises a FormData body to
9
+ * JSON, which breaks every upload. Dropping the header for FormData lets the platform write
10
+ * the multipart header with its boundary.
11
+ */
12
+ const sendFormDataAsMultipart = client => {
13
+ client.interceptors.request.use(config => {
14
+ if (typeof FormData !== 'undefined' && config.data instanceof FormData) {
15
+ config.headers?.delete?.('Content-Type');
16
+ }
17
+ return config;
18
+ });
19
+ };
20
+ exports.sendFormDataAsMultipart = sendFormDataAsMultipart;
21
+ //# sourceMappingURL=multipart.js.map
@@ -9,6 +9,7 @@ var _index = require("../config/index.js");
9
9
  var _index2 = require("../logger/index.js");
10
10
  var _baseUrl = require("./baseUrl.js");
11
11
  var _curl = require("./curl.js");
12
+ var _multipart = require("./multipart.js");
12
13
  var _retry = require("./retry.js");
13
14
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
14
15
  // Define timeout for requests
@@ -30,6 +31,7 @@ const publicClient = _axios.default.create({
30
31
  timeout: REQUEST_TIMEOUT
31
32
  });
32
33
  (0, _baseUrl.applyConfiguredBaseUrl)(publicClient);
34
+ (0, _multipart.sendFormDataAsMultipart)(publicClient);
33
35
 
34
36
  // Registered before the logging interceptors below so they only ever observe
35
37
  // the final outcome of a request, not its intermediate retries. The policy
@@ -29,6 +29,7 @@ var _index2 = require("../logger/index.js");
29
29
  var _networkStatus = require("../network/networkStatus.js");
30
30
  var _baseUrl = require("./baseUrl.js");
31
31
  var _curl = require("./curl.js");
32
+ var _multipart = require("./multipart.js");
32
33
  var _retry = require("./retry.js");
33
34
  var _tokenRefresh = require("./tokenRefresh.js");
34
35
  function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
@@ -135,6 +136,7 @@ const isRefreshTokenRequest = url => {
135
136
  // registered run last. The curl line therefore describes a request that already
136
137
  // has both its baseURL and its Authorization header.
137
138
  (0, _baseUrl.applyConfiguredBaseUrl)(userClient);
139
+ (0, _multipart.sendFormDataAsMultipart)(userClient);
138
140
 
139
141
  // Registered BEFORE the auth interceptor below deliberately. Axios builds its
140
142
  // request chain by unshifting, so the FIRST-registered request interceptor runs
@@ -166,7 +166,7 @@ const initPush = next => {
166
166
  return {
167
167
  shouldShowBanner: show,
168
168
  shouldShowList: show,
169
- shouldPlaySound: show,
169
+ shouldPlaySound: show && (config?.playSoundInForeground?.() ?? true),
170
170
  shouldSetBadge: true
171
171
  };
172
172
  }
@@ -238,12 +238,13 @@ const enablePush = async () => {
238
238
  exports.enablePush = enablePush;
239
239
  const disablePush = async () => {
240
240
  const current = requireConfig();
241
- await current.unregister(await current.getInstallationId());
241
+ // Stop following token changes first, so a failed unregister cannot re-register the phone.
242
242
  tokenSubscription?.remove();
243
243
  tokenSubscription = null;
244
244
  setState({
245
245
  enabled: false
246
246
  });
247
+ await current.unregister(await current.getInstallationId());
247
248
  };
248
249
 
249
250
  /** Sets the app icon badge; a no-op where push is unavailable or the launcher has no badge. */
@@ -0,0 +1,16 @@
1
+ "use strict";
2
+
3
+ /**
4
+ * The clients default to a JSON content type, and axios then serialises a FormData body to
5
+ * JSON, which breaks every upload. Dropping the header for FormData lets the platform write
6
+ * the multipart header with its boundary.
7
+ */
8
+ export const sendFormDataAsMultipart = client => {
9
+ client.interceptors.request.use(config => {
10
+ if (typeof FormData !== 'undefined' && config.data instanceof FormData) {
11
+ config.headers?.delete?.('Content-Type');
12
+ }
13
+ return config;
14
+ });
15
+ };
16
+ //# sourceMappingURL=multipart.js.map
@@ -5,6 +5,7 @@ import { getConfigValue } from "../config/index.js";
5
5
  import { Logger } from "../logger/index.js";
6
6
  import { applyConfiguredBaseUrl } from "./baseUrl.js";
7
7
  import { logCurl } from "./curl.js";
8
+ import { sendFormDataAsMultipart } from "./multipart.js";
8
9
  import { attachRetry } from "./retry.js";
9
10
 
10
11
  // Define timeout for requests
@@ -26,6 +27,7 @@ const publicClient = axios.create({
26
27
  timeout: REQUEST_TIMEOUT
27
28
  });
28
29
  applyConfiguredBaseUrl(publicClient);
30
+ sendFormDataAsMultipart(publicClient);
29
31
 
30
32
  // Registered before the logging interceptors below so they only ever observe
31
33
  // the final outcome of a request, not its intermediate retries. The policy
@@ -7,6 +7,7 @@ import { Logger } from "../logger/index.js";
7
7
  import { getNetworkStatus } from "../network/networkStatus.js";
8
8
  import { applyConfiguredBaseUrl } from "./baseUrl.js";
9
9
  import { logCurl } from "./curl.js";
10
+ import { sendFormDataAsMultipart } from "./multipart.js";
10
11
  import { attachRetry } from "./retry.js";
11
12
  import { dispatchLogout, getErrorMessage, getRefreshPath, isRefreshInFlight, queueBehindRefresh, refreshAccessToken, resetRefreshState } from "./tokenRefresh.js";
12
13
  export { injectStore, injectUserAuth, resetRefreshState } from "./tokenRefresh.js";
@@ -113,6 +114,7 @@ const isRefreshTokenRequest = url => {
113
114
  // registered run last. The curl line therefore describes a request that already
114
115
  // has both its baseURL and its Authorization header.
115
116
  applyConfiguredBaseUrl(userClient);
117
+ sendFormDataAsMultipart(userClient);
116
118
 
117
119
  // Registered BEFORE the auth interceptor below deliberately. Axios builds its
118
120
  // request chain by unshifting, so the FIRST-registered request interceptor runs
@@ -162,7 +162,7 @@ export const initPush = next => {
162
162
  return {
163
163
  shouldShowBanner: show,
164
164
  shouldShowList: show,
165
- shouldPlaySound: show,
165
+ shouldPlaySound: show && (config?.playSoundInForeground?.() ?? true),
166
166
  shouldSetBadge: true
167
167
  };
168
168
  }
@@ -232,12 +232,13 @@ export const enablePush = async () => {
232
232
  */
233
233
  export const disablePush = async () => {
234
234
  const current = requireConfig();
235
- await current.unregister(await current.getInstallationId());
235
+ // Stop following token changes first, so a failed unregister cannot re-register the phone.
236
236
  tokenSubscription?.remove();
237
237
  tokenSubscription = null;
238
238
  setState({
239
239
  enabled: false
240
240
  });
241
+ await current.unregister(await current.getInstallationId());
241
242
  };
242
243
 
243
244
  /** Sets the app icon badge; a no-op where push is unavailable or the launcher has no badge. */
@@ -0,0 +1,8 @@
1
+ import type { AxiosInstance } from 'axios';
2
+ /**
3
+ * The clients default to a JSON content type, and axios then serialises a FormData body to
4
+ * JSON, which breaks every upload. Dropping the header for FormData lets the platform write
5
+ * the multipart header with its boundary.
6
+ */
7
+ export declare const sendFormDataAsMultipart: (client: AxiosInstance) => void;
8
+ //# sourceMappingURL=multipart.d.ts.map
@@ -23,6 +23,8 @@ export interface PushConfig {
23
23
  androidChannels?: PushAndroidChannel[];
24
24
  /** Whether a notification arriving while the app is open is shown. Defaults to true. */
25
25
  showInForeground?: () => boolean;
26
+ /** Whether a notification shown while the app is open plays its sound. Defaults to true. */
27
+ playSoundInForeground?: () => boolean;
26
28
  }
27
29
  export type PushStatus = 'unknown' | 'granted' | 'denied' | 'unavailable';
28
30
  export interface PushState {
@@ -0,0 +1,8 @@
1
+ import type { AxiosInstance } from 'axios';
2
+ /**
3
+ * The clients default to a JSON content type, and axios then serialises a FormData body to
4
+ * JSON, which breaks every upload. Dropping the header for FormData lets the platform write
5
+ * the multipart header with its boundary.
6
+ */
7
+ export declare const sendFormDataAsMultipart: (client: AxiosInstance) => void;
8
+ //# sourceMappingURL=multipart.d.ts.map
@@ -23,6 +23,8 @@ export interface PushConfig {
23
23
  androidChannels?: PushAndroidChannel[];
24
24
  /** Whether a notification arriving while the app is open is shown. Defaults to true. */
25
25
  showInForeground?: () => boolean;
26
+ /** Whether a notification shown while the app is open plays its sound. Defaults to true. */
27
+ playSoundInForeground?: () => boolean;
26
28
  }
27
29
  export type PushStatus = 'unknown' | 'granted' | 'denied' | 'unavailable';
28
30
  export interface PushState {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@webority/mobile-core",
3
- "version": "0.0.24",
3
+ "version": "0.0.25",
4
4
  "description": "Platform layer for Webority React Native apps: HTTP clients, auth/token storage, config, logging, formatters, validators, network status, permissions, storage and version checks. No UI.",
5
5
  "keywords": [
6
6
  "react-native",