@cloudparse/up-miniapps-sdk 0.5.6 → 0.6.0

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.cjs CHANGED
@@ -50,6 +50,7 @@ __export(src_exports, {
50
50
  SDKProvider: () => SDKProvider,
51
51
  SwipeCarousel: () => SwipeCarousel,
52
52
  UIEvent: () => UIEvent,
53
+ createApiService: () => createApiService,
53
54
  default: () => src_default,
54
55
  handleClearRoute: () => handleClearRoute,
55
56
  handleDrawRoute: () => handleDrawRoute,
@@ -125,6 +126,8 @@ var Button = React.forwardRef(
125
126
  Button.displayName = "Button";
126
127
 
127
128
  // src/bridge.ts
129
+ var BridgeTimeoutError = class extends Error {
130
+ };
128
131
  var Bridge = class {
129
132
  callbacks = /* @__PURE__ */ new Map();
130
133
  eventListeners = /* @__PURE__ */ new Map();
@@ -195,18 +198,32 @@ var Bridge = class {
195
198
  * @param type The action type (e.g., "GET_LOCATION").
196
199
  * @param payload Data associated with the action.
197
200
  * @param timeoutMs Time in milliseconds to wait for a response before rejecting.
201
+ * @param retries Number of additional attempts if a request times out (default 1 — one retry).
202
+ * Exists because the response for a request can be lost in transit — e.g. the host's
203
+ * injected response script running before this WebView's own `message` listener has
204
+ * attached, worse under rapid mount/unmount cycles — with no application-visible symptom
205
+ * other than the full 30s timeout. A blind retry self-heals that class of loss without
206
+ * needing to diagnose which specific transport race dropped the original message; every
207
+ * call site benefits automatically instead of each consumer app hand-rolling its own
208
+ * retry-after-catch logic (which previously only covered `initialize()`, and imperfectly).
198
209
  * @returns A promise that resolves with the native response.
199
210
  */
200
- send(type, payload, timeoutMs = 3e4) {
211
+ send(type, payload, timeoutMs = 3e4, retries = 1) {
201
212
  if (!this.isNative()) {
202
213
  return this.handleMockMessage(type, payload);
203
214
  }
215
+ return this.sendOnce(type, payload, timeoutMs).catch((err) => {
216
+ if (retries <= 0 || !(err instanceof BridgeTimeoutError)) throw err;
217
+ return this.send(type, payload, timeoutMs, retries - 1);
218
+ });
219
+ }
220
+ sendOnce(type, payload, timeoutMs) {
204
221
  return new Promise((resolve, reject) => {
205
222
  const callbackId = `${type}_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`;
206
223
  const timeout = setTimeout(() => {
207
224
  if (this.callbacks.has(callbackId)) {
208
225
  this.callbacks.delete(callbackId);
209
- reject(new Error(`Bridge request timeout: ${type}`));
226
+ reject(new BridgeTimeoutError(`Bridge request timeout: ${type}`));
210
227
  }
211
228
  }, timeoutMs);
212
229
  this.callbacks.set(callbackId, {
@@ -3680,7 +3697,7 @@ var RoutingService = {
3680
3697
  };
3681
3698
 
3682
3699
  // package.json
3683
- var version = "0.5.6";
3700
+ var version = "0.6.0";
3684
3701
 
3685
3702
  // src/sdk.ts
3686
3703
  function deepFreeze(obj) {
@@ -3695,6 +3712,7 @@ function deepFreeze(obj) {
3695
3712
  return Object.freeze(obj);
3696
3713
  }
3697
3714
  var globalRoutingConfig = null;
3715
+ var lastKnownEnv = null;
3698
3716
  var MiniAppSDK = class {
3699
3717
  /**
3700
3718
  * Map services.
@@ -4017,7 +4035,14 @@ var MiniAppSDK = class {
4017
4035
  });
4018
4036
  constructor() {
4019
4037
  this.bridge = new Bridge();
4038
+ this.bridge.on(
4039
+ "UPDATE_CONTEXT" /* UPDATE_CONTEXT */,
4040
+ (data) => {
4041
+ if (data?.env) lastKnownEnv = data.env;
4042
+ }
4043
+ );
4020
4044
  this.initialize = this.initialize.bind(this);
4045
+ this.getEnv = this.getEnv.bind(this);
4021
4046
  this.on = this.on.bind(this);
4022
4047
  this.off = this.off.bind(this);
4023
4048
  }
@@ -4041,8 +4066,22 @@ var MiniAppSDK = class {
4041
4066
  * The starting point for the Mini-App. Must be called before any other SDK methods.
4042
4067
  * @param options The options to provide to the shell app
4043
4068
  */
4044
- initialize(options) {
4045
- return this.bridge.send("INITIALIZE", options);
4069
+ async initialize(options) {
4070
+ const res = await this.bridge.send(
4071
+ "INITIALIZE",
4072
+ options
4073
+ );
4074
+ if (res?.env) lastKnownEnv = res.env;
4075
+ return res;
4076
+ }
4077
+ /**
4078
+ * Returns the last known `env` (shell-provided config like `backendUrl`),
4079
+ * refreshed automatically by `initialize()` and every `UPDATE_CONTEXT`
4080
+ * push — read this instead of caching your own copy of `env` values.
4081
+ * Returns `null` before the first successful `initialize()`/context push.
4082
+ */
4083
+ getEnv() {
4084
+ return lastKnownEnv;
4046
4085
  }
4047
4086
  /**
4048
4087
  * Registers a callback for a specific event from the native shell.
@@ -5249,6 +5288,72 @@ function handleClearRoute(map, miniAppId) {
5249
5288
  if (map.getSource(sourceId)) map.removeSource(sourceId);
5250
5289
  }
5251
5290
 
5291
+ // src/services/apiService.ts
5292
+ function buildUrl(baseUrl, path) {
5293
+ if (path.startsWith("http://") || path.startsWith("https://")) {
5294
+ return path;
5295
+ }
5296
+ let cleanBase = baseUrl.trim();
5297
+ while (cleanBase.endsWith("/")) {
5298
+ cleanBase = cleanBase.slice(0, -1);
5299
+ }
5300
+ let cleanPath = path.trim();
5301
+ if (!cleanPath.startsWith("/")) {
5302
+ cleanPath = `/${cleanPath}`;
5303
+ }
5304
+ const baseEndsWithV1 = cleanBase.endsWith("/api/v1");
5305
+ const pathStartsWithV1 = cleanPath.startsWith("/api/v1/") || cleanPath === "/api/v1";
5306
+ if (baseEndsWithV1 && pathStartsWithV1) {
5307
+ const strippedPath = cleanPath.slice(7);
5308
+ return `${cleanBase}${strippedPath}`;
5309
+ }
5310
+ return `${cleanBase}${cleanPath}`;
5311
+ }
5312
+ function getEarlyBackendUrl(kind) {
5313
+ if (typeof window === "undefined") return void 0;
5314
+ const early = window.__UP_BACKEND_URLS__;
5315
+ return early?.[kind] ?? void 0;
5316
+ }
5317
+ function createApiService(options) {
5318
+ const getBaseUrl = () => getEarlyBackendUrl("http") || sdk.getEnv()?.backendUrl || options.defaultBaseUrl;
5319
+ const getWsUrl = () => getEarlyBackendUrl("ws") || sdk.getEnv()?.wsBackendUrl || options.defaultWsBackendUrl;
5320
+ return {
5321
+ get baseUrl() {
5322
+ return getBaseUrl();
5323
+ },
5324
+ delete: (path) => sdk.network.request({
5325
+ method: "DELETE",
5326
+ url: buildUrl(getBaseUrl(), path)
5327
+ }),
5328
+ get: (path) => sdk.network.request({
5329
+ headers: { "Content-Type": "application/json" },
5330
+ method: "GET",
5331
+ url: buildUrl(getBaseUrl(), path)
5332
+ }),
5333
+ graphqlQuery: (query, variables = {}) => sdk.network.request({
5334
+ body: { query, variables },
5335
+ headers: { "Content-Type": "application/json" },
5336
+ method: "POST",
5337
+ url: buildUrl(getBaseUrl(), "/graphql")
5338
+ }),
5339
+ patch: (path, body) => sdk.network.request({
5340
+ body,
5341
+ headers: { "Content-Type": "application/json" },
5342
+ method: "PATCH",
5343
+ url: buildUrl(getBaseUrl(), path)
5344
+ }),
5345
+ post: (path, body) => sdk.network.request({
5346
+ body,
5347
+ headers: { "Content-Type": "application/json" },
5348
+ method: "POST",
5349
+ url: buildUrl(getBaseUrl(), path)
5350
+ }),
5351
+ get wsUrl() {
5352
+ return getWsUrl();
5353
+ }
5354
+ };
5355
+ }
5356
+
5252
5357
  // src/index.ts
5253
5358
  var src_default = sdk;
5254
5359
  // Annotate the CommonJS export names for ESM import in node:
@@ -5273,6 +5378,7 @@ var src_default = sdk;
5273
5378
  SDKProvider,
5274
5379
  SwipeCarousel,
5275
5380
  UIEvent,
5381
+ createApiService,
5276
5382
  handleClearRoute,
5277
5383
  handleDrawRoute,
5278
5384
  handleRouteRequest,