@saasquatch/component-environment 1.0.0-4 → 1.0.1-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.d.ts CHANGED
@@ -162,6 +162,72 @@ declare function getTenantAlias(): string;
162
162
  declare function getAppDomain(): string;
163
163
  declare function getEngagementMedium(): EngagementMedium;
164
164
 
165
+ interface PartialPath {
166
+ pathname: string;
167
+ search?: string;
168
+ hash?: string;
169
+ }
170
+ interface HistoryEntry extends PartialPath {
171
+ state?: object;
172
+ }
173
+ declare type To = string | PartialPath;
174
+ interface ListenableHistory {
175
+ listen(fn: () => void): () => void;
176
+ push(to: To, state?: object): void;
177
+ replace(to: To, state?: object): void;
178
+ back(): void;
179
+ forward(): void;
180
+ go(delta?: number): void;
181
+ location: HistoryEntry;
182
+ }
183
+ declare global {
184
+ interface Window {
185
+ squatchHistory: ListenableHistory;
186
+ }
187
+ }
188
+ declare class BrowserHistory implements ListenableHistory {
189
+ private listeners;
190
+ constructor();
191
+ listen(fn: () => void): () => void;
192
+ private notify;
193
+ get location(): {
194
+ pathname: string;
195
+ search: string;
196
+ hash: string;
197
+ state: any;
198
+ };
199
+ back(): void;
200
+ forward(): void;
201
+ go(delta: number): void;
202
+ push(to: To, state?: object): void;
203
+ replace(to: To, state?: object): void;
204
+ }
205
+ declare class MemoryHistory implements ListenableHistory {
206
+ private history;
207
+ private index;
208
+ private listeners;
209
+ listen(fn: () => void): () => void;
210
+ private current;
211
+ get state(): object | undefined;
212
+ notify(): void;
213
+ get location(): HistoryEntry;
214
+ back(): void;
215
+ forward(): void;
216
+ go(delta: number): void;
217
+ push(to: To, state?: object): void;
218
+ replace(to: To, state?: object): void;
219
+ }
220
+ declare class LazyHistory implements ListenableHistory {
221
+ get location(): HistoryEntry;
222
+ listen(fn: () => void): () => void;
223
+ back(): void;
224
+ forward(): void;
225
+ go(delta: number): void;
226
+ push(to: To, state?: object): void;
227
+ replace(to: To, state?: object): void;
228
+ }
229
+ declare const _default: LazyHistory;
230
+
165
231
  /**
166
232
  * Lazily start the user context provider. If it already exists, the existing provider is
167
233
  * returned. This function is safe to call multiple times.
@@ -187,6 +253,7 @@ declare function setUserIdentity(identity?: UserIdentity): void;
187
253
  */
188
254
  declare function getUserIdentity(): UserIdentity | undefined;
189
255
 
256
+ declare function validateLocale(locale?: string): string | undefined;
190
257
  /**
191
258
  * Lazily start the locale context provider. If it already exists, the existing provider is
192
259
  * returned. This function is safe to call multiple times.
@@ -223,4 +290,4 @@ declare function setProgramId(programId: string | undefined): void;
223
290
  */
224
291
  declare function getProgramId(): string | undefined;
225
292
 
226
- export { DEFAULT_MEDIUM, DecodedSquatchJWT, DecodedWidgetAPIJWT, EngagementMedium, Environment, EnvironmentSDK, LOCALE_CONTEXT_NAME, LocaleContextName, PROGRAM_CONTEXT_NAME, PortalEnv, ProgramContextName, SquatchAdmin, SquatchAndroid, SquatchJS2, USER_CONTEXT_NAME, UserContextName, UserId, UserIdentity, WidgetIdent, getAppDomain, getEngagementMedium, getEnvironment, getEnvironmentSDK, getLocale, getProgramId, getTenantAlias, getUserIdentity, isDemo, lazilyStartLocaleContext, lazilyStartProgramContext, lazilyStartUserContext, setLocale, setProgramId, setUserIdentity, userIdentityFromJwt };
293
+ export { BrowserHistory, DEFAULT_MEDIUM, DecodedSquatchJWT, DecodedWidgetAPIJWT, EngagementMedium, Environment, EnvironmentSDK, HistoryEntry, LOCALE_CONTEXT_NAME, LazyHistory, LocaleContextName, MemoryHistory, PROGRAM_CONTEXT_NAME, PortalEnv, ProgramContextName, SquatchAdmin, SquatchAndroid, SquatchJS2, USER_CONTEXT_NAME, UserContextName, UserId, UserIdentity, WidgetIdent, getAppDomain, getEngagementMedium, getEnvironment, getEnvironmentSDK, getLocale, getProgramId, getTenantAlias, getUserIdentity, _default as history, isDemo, lazilyStartLocaleContext, lazilyStartProgramContext, lazilyStartUserContext, setLocale, setProgramId, setUserIdentity, userIdentityFromJwt, validateLocale };
package/dist/index.js CHANGED
@@ -1,7 +1,9 @@
1
1
  "use strict";
2
2
  var __create = Object.create;
3
3
  var __defProp = Object.defineProperty;
4
+ var __defProps = Object.defineProperties;
4
5
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6
+ var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
5
7
  var __getOwnPropNames = Object.getOwnPropertyNames;
6
8
  var __getOwnPropSymbols = Object.getOwnPropertySymbols;
7
9
  var __getProtoOf = Object.getPrototypeOf;
@@ -19,6 +21,7 @@ var __spreadValues = (a, b) => {
19
21
  }
20
22
  return a;
21
23
  };
24
+ var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
22
25
  var __export = (target, all) => {
23
26
  for (var name in all)
24
27
  __defProp(target, name, { get: all[name], enumerable: true });
@@ -37,8 +40,11 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
37
40
  // src/index.ts
38
41
  var src_exports = {};
39
42
  __export(src_exports, {
43
+ BrowserHistory: () => BrowserHistory,
40
44
  DEFAULT_MEDIUM: () => DEFAULT_MEDIUM,
41
45
  LOCALE_CONTEXT_NAME: () => LOCALE_CONTEXT_NAME,
46
+ LazyHistory: () => LazyHistory,
47
+ MemoryHistory: () => MemoryHistory,
42
48
  PROGRAM_CONTEXT_NAME: () => PROGRAM_CONTEXT_NAME,
43
49
  USER_CONTEXT_NAME: () => USER_CONTEXT_NAME,
44
50
  getAppDomain: () => getAppDomain,
@@ -49,6 +55,7 @@ __export(src_exports, {
49
55
  getProgramId: () => getProgramId,
50
56
  getTenantAlias: () => getTenantAlias,
51
57
  getUserIdentity: () => getUserIdentity,
58
+ history: () => history_default,
52
59
  isDemo: () => isDemo,
53
60
  lazilyStartLocaleContext: () => lazilyStartLocaleContext,
54
61
  lazilyStartProgramContext: () => lazilyStartProgramContext,
@@ -56,7 +63,8 @@ __export(src_exports, {
56
63
  setLocale: () => setLocale,
57
64
  setProgramId: () => setProgramId,
58
65
  setUserIdentity: () => setUserIdentity,
59
- userIdentityFromJwt: () => userIdentityFromJwt
66
+ userIdentityFromJwt: () => userIdentityFromJwt,
67
+ validateLocale: () => validateLocale
60
68
  });
61
69
  module.exports = __toCommonJS(src_exports);
62
70
 
@@ -148,6 +156,199 @@ function getEngagementMedium() {
148
156
  }
149
157
  }
150
158
 
159
+ // src/debug.ts
160
+ var debugEnabled = (() => {
161
+ var _a;
162
+ try {
163
+ return (_a = window == null ? void 0 : window.localStorage) == null ? void 0 : _a.getItem("debug");
164
+ } catch (e) {
165
+ return false;
166
+ }
167
+ })();
168
+ function debug(ns, ...args) {
169
+ if (debugEnabled) {
170
+ console.debug(`sq:environment:${ns}`, ...args);
171
+ }
172
+ }
173
+
174
+ // src/history.ts
175
+ var debug2 = (...args) => debug("history", ...args);
176
+ function normalizeTo(to) {
177
+ if (typeof to === "string")
178
+ return to;
179
+ const url = new URL(to.pathname, window.origin);
180
+ if (to.search)
181
+ url.search = to.search;
182
+ if (to.hash)
183
+ url.hash = to.hash;
184
+ return url;
185
+ }
186
+ var BrowserHistory = class {
187
+ constructor() {
188
+ this.listeners = /* @__PURE__ */ new Set();
189
+ window.addEventListener("popstate", this.notify.bind(this));
190
+ window.addEventListener("pushState", this.notify.bind(this));
191
+ window.addEventListener("replaceState", this.notify.bind(this));
192
+ }
193
+ listen(fn) {
194
+ this.listeners.add(fn);
195
+ return () => {
196
+ this.listeners.delete(fn);
197
+ };
198
+ }
199
+ notify() {
200
+ debug2("notifying listeners of route change", this.location);
201
+ if (this.listeners) {
202
+ this.listeners.forEach((listener) => listener());
203
+ }
204
+ }
205
+ get location() {
206
+ return {
207
+ pathname: window.location.pathname,
208
+ search: window.location.search,
209
+ hash: window.location.hash,
210
+ state: window.history.state
211
+ };
212
+ }
213
+ back() {
214
+ this.go(-1);
215
+ }
216
+ forward() {
217
+ this.go(1);
218
+ }
219
+ go(delta) {
220
+ window.history.go(delta);
221
+ }
222
+ push(to, state) {
223
+ const url = normalizeTo(to);
224
+ window.history.pushState(state, "", url);
225
+ }
226
+ replace(to, state) {
227
+ const url = normalizeTo(to);
228
+ window.history.replaceState(state, "", url);
229
+ }
230
+ };
231
+ var MemoryHistory = class {
232
+ constructor() {
233
+ this.history = [{ pathname: "/", search: "", hash: "" }];
234
+ this.index = 0;
235
+ this.listeners = /* @__PURE__ */ new Set();
236
+ }
237
+ listen(fn) {
238
+ this.listeners.add(fn);
239
+ return () => {
240
+ this.listeners.delete(fn);
241
+ };
242
+ }
243
+ current() {
244
+ return this.history[this.index];
245
+ }
246
+ get state() {
247
+ return this.current().state;
248
+ }
249
+ notify() {
250
+ debug2("notifying listeners of route change", this.location);
251
+ this.listeners.forEach((listener) => listener());
252
+ }
253
+ get location() {
254
+ return this.history[this.index];
255
+ }
256
+ back() {
257
+ this.go(-1);
258
+ }
259
+ forward() {
260
+ this.go(1);
261
+ }
262
+ go(delta) {
263
+ this.index += delta;
264
+ if (this.index < 0)
265
+ this.index = 0;
266
+ if (this.index >= this.history.length)
267
+ this.index = this.history.length - 1;
268
+ this.notify();
269
+ }
270
+ push(to, state) {
271
+ let entry;
272
+ if (typeof to === "string") {
273
+ entry = {
274
+ pathname: to,
275
+ search: this.history[this.index].search,
276
+ hash: this.history[this.index].hash,
277
+ state
278
+ };
279
+ } else {
280
+ entry = __spreadProps(__spreadValues({}, to), {
281
+ state
282
+ });
283
+ }
284
+ this.index++;
285
+ this.history.splice(this.index, this.history.length, entry);
286
+ this.notify();
287
+ }
288
+ replace(to, state) {
289
+ if (typeof to === "string") {
290
+ this.history[this.index] = {
291
+ pathname: to,
292
+ search: "",
293
+ hash: "",
294
+ state
295
+ };
296
+ } else {
297
+ this.history[this.index] = __spreadProps(__spreadValues({}, to), {
298
+ state
299
+ });
300
+ }
301
+ this.notify();
302
+ }
303
+ };
304
+ function createHistory() {
305
+ if (getEnvironment() === "SquatchPortal") {
306
+ let wrapHistoryFunction2 = function(functionName) {
307
+ const orig = window.history[functionName];
308
+ return function(...args) {
309
+ const returnValue = orig.apply(window.history, args);
310
+ const event = new Event(functionName);
311
+ window.dispatchEvent(event);
312
+ return returnValue;
313
+ };
314
+ };
315
+ var wrapHistoryFunction = wrapHistoryFunction2;
316
+ window.history.pushState = wrapHistoryFunction2("pushState");
317
+ window.history.replaceState = wrapHistoryFunction2("replaceState");
318
+ return new BrowserHistory();
319
+ } else {
320
+ return new MemoryHistory();
321
+ }
322
+ }
323
+ function lazyHistory() {
324
+ window.squatchHistory = window.squatchHistory || createHistory();
325
+ return window.squatchHistory;
326
+ }
327
+ var LazyHistory = class {
328
+ get location() {
329
+ return lazyHistory().location;
330
+ }
331
+ listen(fn) {
332
+ return lazyHistory().listen(fn);
333
+ }
334
+ back() {
335
+ lazyHistory().back();
336
+ }
337
+ forward() {
338
+ lazyHistory().forward();
339
+ }
340
+ go(delta) {
341
+ lazyHistory().go(delta);
342
+ }
343
+ push(to, state) {
344
+ lazyHistory().push(to, state);
345
+ }
346
+ replace(to, state) {
347
+ lazyHistory().replace(to, state);
348
+ }
349
+ };
350
+ var history_default = new LazyHistory();
351
+
151
352
  // src/contexts/UserIdentityContext.ts
152
353
  var import_jwt_decode = __toESM(require("jwt-decode"));
153
354
  var import_dom_context3 = require("dom-context");
@@ -158,25 +359,21 @@ var import_dom_context2 = require("dom-context");
158
359
 
159
360
  // src/contexts/LocaleContext.ts
160
361
  var import_dom_context = require("dom-context");
161
-
162
- // src/debug.ts
163
- var debugEnabled = localStorage.getItem("debug");
164
- function debug(ns, ...args) {
165
- if (debugEnabled) {
166
- console.debug(`sq:environment:${ns}`, ...args);
362
+ var debug3 = (...args) => debug(LOCALE_CONTEXT_NAME, ...args);
363
+ function validateLocale(locale) {
364
+ if (locale && /[a-z]{2}_[A-Z]{2}/.test(locale)) {
365
+ return locale;
167
366
  }
168
367
  }
169
-
170
- // src/contexts/LocaleContext.ts
171
- var debug2 = (...args) => debug(LOCALE_CONTEXT_NAME, ...args);
172
368
  function lazilyStartLocaleContext() {
173
369
  var _a;
174
370
  let globalProvider = window.squatchLocale;
175
371
  if (!globalProvider) {
176
- debug2("Creating locale context provider");
372
+ debug3("Creating locale context provider");
373
+ const locale = ((_a = window.widgetIdent) == null ? void 0 : _a.locale) ?? validateLocale(navigator.language.replace("-", "_"));
177
374
  globalProvider = new import_dom_context.ContextProvider({
178
375
  element: document.documentElement,
179
- initialState: ((_a = window.widgetIdent) == null ? void 0 : _a.locale) || navigator.language.replace("-", "_"),
376
+ initialState: locale,
180
377
  contextName: LOCALE_CONTEXT_NAME
181
378
  }).start();
182
379
  window.squatchLocale = globalProvider;
@@ -186,7 +383,7 @@ function lazilyStartLocaleContext() {
186
383
  function setLocale(locale) {
187
384
  const globalProvider = lazilyStartLocaleContext();
188
385
  if (globalProvider.context !== locale) {
189
- debug2(`Setting locale context value [${locale}]`);
386
+ debug3(`Setting locale context value [${locale}]`);
190
387
  globalProvider.context = locale;
191
388
  }
192
389
  }
@@ -196,7 +393,7 @@ function getLocale() {
196
393
  }
197
394
 
198
395
  // src/fetchLocale.ts
199
- var debug3 = (...args) => debug(LOCALE_CONTEXT_NAME, ...args);
396
+ var debug4 = (...args) => debug(LOCALE_CONTEXT_NAME, ...args);
200
397
  var GET_LOCALE = `
201
398
  query {
202
399
  viewer {
@@ -208,7 +405,7 @@ var GET_LOCALE = `
208
405
  `;
209
406
  async function fetchLocale() {
210
407
  var _a;
211
- debug3("Fetching locale from GraphQL for current user");
408
+ debug4("Fetching locale from GraphQL for current user");
212
409
  try {
213
410
  const result = await fetch(`${getAppDomain()}/api/v1/${getTenantAlias()}/graphql`, {
214
411
  method: "POST",
@@ -229,13 +426,13 @@ async function fetchLocale() {
229
426
  }
230
427
  return json.data.viewer.locale || void 0;
231
428
  } catch (e) {
232
- debug3(`Failed to fetch locale for current user`, e.message);
429
+ debug4(`Failed to fetch locale for current user`, e.message);
233
430
  return void 0;
234
431
  }
235
432
  }
236
433
 
237
434
  // src/listeners.ts
238
- var debug4 = (...args) => debug(LOCALE_CONTEXT_NAME, ...args);
435
+ var debug5 = (...args) => debug(LOCALE_CONTEXT_NAME, ...args);
239
436
  var userContextListenerDiv = (() => {
240
437
  const id = "__environment_context_listener";
241
438
  let div = document.getElementById(id);
@@ -255,30 +452,30 @@ var userContextListenerForLocale = new import_dom_context2.ContextListener({
255
452
  const defaultLocale = ((_a = window.widgetIdent) == null ? void 0 : _a.locale) || navigator.language.replace("-", "_");
256
453
  let newLocale;
257
454
  if (next) {
258
- debug4("User context changed, refetching locale");
455
+ debug5("User context changed, refetching locale");
259
456
  const locale = await fetchLocale();
260
457
  if (localeProvider.context !== locale) {
261
- debug4(`New value fetched from GraphQL [${locale}]`);
458
+ debug5(`New value fetched from GraphQL [${locale}]`);
262
459
  newLocale = locale || defaultLocale;
263
460
  }
264
461
  } else {
265
462
  newLocale = defaultLocale;
266
463
  }
267
- debug4(`Setting locale context to [${newLocale}]`);
464
+ debug5(`Setting locale context to [${newLocale}]`);
268
465
  localeProvider.context = newLocale;
269
466
  }
270
467
  });
271
468
  function startUserContextListenerForLocale() {
272
- debug4("Starting user context listener for locale updates");
469
+ debug5("Starting user context listener for locale updates");
273
470
  userContextListenerForLocale.start();
274
471
  }
275
472
 
276
473
  // src/contexts/UserIdentityContext.ts
277
- var debug5 = (...args) => debug(USER_CONTEXT_NAME, ...args);
474
+ var debug6 = (...args) => debug(USER_CONTEXT_NAME, ...args);
278
475
  function lazilyStartUserContext() {
279
476
  let globalProvider = window.squatchUserIdentity;
280
477
  if (!globalProvider) {
281
- debug5("Creating user context provider");
478
+ debug6("Creating user context provider");
282
479
  globalProvider = new import_dom_context3.ContextProvider({
283
480
  element: document.documentElement,
284
481
  initialState: _getInitialValue(),
@@ -364,7 +561,7 @@ function _getInitialValue() {
364
561
  function setUserIdentity(identity) {
365
562
  const globalProvider = lazilyStartUserContext();
366
563
  if (!(0, import_equality.equal)(globalProvider.context, identity)) {
367
- debug5(`Setting user context value [${JSON.stringify(identity)}]`);
564
+ debug6(`Setting user context value [${JSON.stringify(identity)}]`);
368
565
  globalProvider.context = identity;
369
566
  }
370
567
  if (identity && getEnvironmentSDK().type === "SquatchPortal") {
@@ -380,12 +577,12 @@ function getUserIdentity() {
380
577
 
381
578
  // src/contexts/ProgramContext.ts
382
579
  var import_dom_context4 = require("dom-context");
383
- var debug6 = (...args) => debug(PROGRAM_CONTEXT_NAME, ...args);
580
+ var debug7 = (...args) => debug(PROGRAM_CONTEXT_NAME, ...args);
384
581
  function lazilyStartProgramContext() {
385
582
  var _a;
386
583
  let globalProvider = window.squatchProgramId;
387
584
  if (!globalProvider) {
388
- debug6("Creating program context provider");
585
+ debug7("Creating program context provider");
389
586
  globalProvider = new import_dom_context4.ContextProvider({
390
587
  element: document.documentElement,
391
588
  initialState: ((_a = window.widgetIdent) == null ? void 0 : _a.programId) || void 0,
@@ -398,18 +595,21 @@ function lazilyStartProgramContext() {
398
595
  function setProgramId(programId) {
399
596
  const globalProvider = lazilyStartProgramContext();
400
597
  if (globalProvider.context !== programId) {
401
- debug6(`Setting program context value [${programId}]`);
598
+ debug7(`Setting program context value [${programId}]`);
402
599
  globalProvider.context = programId;
403
600
  }
404
601
  }
405
602
  function getProgramId() {
406
603
  var _a;
407
- return (_a = window.squatchLocale) == null ? void 0 : _a.context;
604
+ return (_a = window.squatchProgramId) == null ? void 0 : _a.context;
408
605
  }
409
606
  // Annotate the CommonJS export names for ESM import in node:
410
607
  0 && (module.exports = {
608
+ BrowserHistory,
411
609
  DEFAULT_MEDIUM,
412
610
  LOCALE_CONTEXT_NAME,
611
+ LazyHistory,
612
+ MemoryHistory,
413
613
  PROGRAM_CONTEXT_NAME,
414
614
  USER_CONTEXT_NAME,
415
615
  getAppDomain,
@@ -420,6 +620,7 @@ function getProgramId() {
420
620
  getProgramId,
421
621
  getTenantAlias,
422
622
  getUserIdentity,
623
+ history,
423
624
  isDemo,
424
625
  lazilyStartLocaleContext,
425
626
  lazilyStartProgramContext,
@@ -427,5 +628,6 @@ function getProgramId() {
427
628
  setLocale,
428
629
  setProgramId,
429
630
  setUserIdentity,
430
- userIdentityFromJwt
631
+ userIdentityFromJwt,
632
+ validateLocale
431
633
  });
package/dist/index.mjs CHANGED
@@ -1,5 +1,7 @@
1
1
  "use strict";
2
2
  var __defProp = Object.defineProperty;
3
+ var __defProps = Object.defineProperties;
4
+ var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
3
5
  var __getOwnPropSymbols = Object.getOwnPropertySymbols;
4
6
  var __hasOwnProp = Object.prototype.hasOwnProperty;
5
7
  var __propIsEnum = Object.prototype.propertyIsEnumerable;
@@ -15,6 +17,7 @@ var __spreadValues = (a, b) => {
15
17
  }
16
18
  return a;
17
19
  };
20
+ var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
18
21
 
19
22
  // src/types.ts
20
23
  var USER_CONTEXT_NAME = "sq:user-identity";
@@ -104,6 +107,199 @@ function getEngagementMedium() {
104
107
  }
105
108
  }
106
109
 
110
+ // src/debug.ts
111
+ var debugEnabled = (() => {
112
+ var _a;
113
+ try {
114
+ return (_a = window == null ? void 0 : window.localStorage) == null ? void 0 : _a.getItem("debug");
115
+ } catch (e) {
116
+ return false;
117
+ }
118
+ })();
119
+ function debug(ns, ...args) {
120
+ if (debugEnabled) {
121
+ console.debug(`sq:environment:${ns}`, ...args);
122
+ }
123
+ }
124
+
125
+ // src/history.ts
126
+ var debug2 = (...args) => debug("history", ...args);
127
+ function normalizeTo(to) {
128
+ if (typeof to === "string")
129
+ return to;
130
+ const url = new URL(to.pathname, window.origin);
131
+ if (to.search)
132
+ url.search = to.search;
133
+ if (to.hash)
134
+ url.hash = to.hash;
135
+ return url;
136
+ }
137
+ var BrowserHistory = class {
138
+ constructor() {
139
+ this.listeners = /* @__PURE__ */ new Set();
140
+ window.addEventListener("popstate", this.notify.bind(this));
141
+ window.addEventListener("pushState", this.notify.bind(this));
142
+ window.addEventListener("replaceState", this.notify.bind(this));
143
+ }
144
+ listen(fn) {
145
+ this.listeners.add(fn);
146
+ return () => {
147
+ this.listeners.delete(fn);
148
+ };
149
+ }
150
+ notify() {
151
+ debug2("notifying listeners of route change", this.location);
152
+ if (this.listeners) {
153
+ this.listeners.forEach((listener) => listener());
154
+ }
155
+ }
156
+ get location() {
157
+ return {
158
+ pathname: window.location.pathname,
159
+ search: window.location.search,
160
+ hash: window.location.hash,
161
+ state: window.history.state
162
+ };
163
+ }
164
+ back() {
165
+ this.go(-1);
166
+ }
167
+ forward() {
168
+ this.go(1);
169
+ }
170
+ go(delta) {
171
+ window.history.go(delta);
172
+ }
173
+ push(to, state) {
174
+ const url = normalizeTo(to);
175
+ window.history.pushState(state, "", url);
176
+ }
177
+ replace(to, state) {
178
+ const url = normalizeTo(to);
179
+ window.history.replaceState(state, "", url);
180
+ }
181
+ };
182
+ var MemoryHistory = class {
183
+ constructor() {
184
+ this.history = [{ pathname: "/", search: "", hash: "" }];
185
+ this.index = 0;
186
+ this.listeners = /* @__PURE__ */ new Set();
187
+ }
188
+ listen(fn) {
189
+ this.listeners.add(fn);
190
+ return () => {
191
+ this.listeners.delete(fn);
192
+ };
193
+ }
194
+ current() {
195
+ return this.history[this.index];
196
+ }
197
+ get state() {
198
+ return this.current().state;
199
+ }
200
+ notify() {
201
+ debug2("notifying listeners of route change", this.location);
202
+ this.listeners.forEach((listener) => listener());
203
+ }
204
+ get location() {
205
+ return this.history[this.index];
206
+ }
207
+ back() {
208
+ this.go(-1);
209
+ }
210
+ forward() {
211
+ this.go(1);
212
+ }
213
+ go(delta) {
214
+ this.index += delta;
215
+ if (this.index < 0)
216
+ this.index = 0;
217
+ if (this.index >= this.history.length)
218
+ this.index = this.history.length - 1;
219
+ this.notify();
220
+ }
221
+ push(to, state) {
222
+ let entry;
223
+ if (typeof to === "string") {
224
+ entry = {
225
+ pathname: to,
226
+ search: this.history[this.index].search,
227
+ hash: this.history[this.index].hash,
228
+ state
229
+ };
230
+ } else {
231
+ entry = __spreadProps(__spreadValues({}, to), {
232
+ state
233
+ });
234
+ }
235
+ this.index++;
236
+ this.history.splice(this.index, this.history.length, entry);
237
+ this.notify();
238
+ }
239
+ replace(to, state) {
240
+ if (typeof to === "string") {
241
+ this.history[this.index] = {
242
+ pathname: to,
243
+ search: "",
244
+ hash: "",
245
+ state
246
+ };
247
+ } else {
248
+ this.history[this.index] = __spreadProps(__spreadValues({}, to), {
249
+ state
250
+ });
251
+ }
252
+ this.notify();
253
+ }
254
+ };
255
+ function createHistory() {
256
+ if (getEnvironment() === "SquatchPortal") {
257
+ let wrapHistoryFunction2 = function(functionName) {
258
+ const orig = window.history[functionName];
259
+ return function(...args) {
260
+ const returnValue = orig.apply(window.history, args);
261
+ const event = new Event(functionName);
262
+ window.dispatchEvent(event);
263
+ return returnValue;
264
+ };
265
+ };
266
+ var wrapHistoryFunction = wrapHistoryFunction2;
267
+ window.history.pushState = wrapHistoryFunction2("pushState");
268
+ window.history.replaceState = wrapHistoryFunction2("replaceState");
269
+ return new BrowserHistory();
270
+ } else {
271
+ return new MemoryHistory();
272
+ }
273
+ }
274
+ function lazyHistory() {
275
+ window.squatchHistory = window.squatchHistory || createHistory();
276
+ return window.squatchHistory;
277
+ }
278
+ var LazyHistory = class {
279
+ get location() {
280
+ return lazyHistory().location;
281
+ }
282
+ listen(fn) {
283
+ return lazyHistory().listen(fn);
284
+ }
285
+ back() {
286
+ lazyHistory().back();
287
+ }
288
+ forward() {
289
+ lazyHistory().forward();
290
+ }
291
+ go(delta) {
292
+ lazyHistory().go(delta);
293
+ }
294
+ push(to, state) {
295
+ lazyHistory().push(to, state);
296
+ }
297
+ replace(to, state) {
298
+ lazyHistory().replace(to, state);
299
+ }
300
+ };
301
+ var history_default = new LazyHistory();
302
+
107
303
  // src/contexts/UserIdentityContext.ts
108
304
  import decode from "jwt-decode";
109
305
  import { ContextProvider as ContextProvider2 } from "dom-context";
@@ -114,25 +310,21 @@ import { ContextListener } from "dom-context";
114
310
 
115
311
  // src/contexts/LocaleContext.ts
116
312
  import { ContextProvider } from "dom-context";
117
-
118
- // src/debug.ts
119
- var debugEnabled = localStorage.getItem("debug");
120
- function debug(ns, ...args) {
121
- if (debugEnabled) {
122
- console.debug(`sq:environment:${ns}`, ...args);
313
+ var debug3 = (...args) => debug(LOCALE_CONTEXT_NAME, ...args);
314
+ function validateLocale(locale) {
315
+ if (locale && /[a-z]{2}_[A-Z]{2}/.test(locale)) {
316
+ return locale;
123
317
  }
124
318
  }
125
-
126
- // src/contexts/LocaleContext.ts
127
- var debug2 = (...args) => debug(LOCALE_CONTEXT_NAME, ...args);
128
319
  function lazilyStartLocaleContext() {
129
320
  var _a;
130
321
  let globalProvider = window.squatchLocale;
131
322
  if (!globalProvider) {
132
- debug2("Creating locale context provider");
323
+ debug3("Creating locale context provider");
324
+ const locale = ((_a = window.widgetIdent) == null ? void 0 : _a.locale) ?? validateLocale(navigator.language.replace("-", "_"));
133
325
  globalProvider = new ContextProvider({
134
326
  element: document.documentElement,
135
- initialState: ((_a = window.widgetIdent) == null ? void 0 : _a.locale) || navigator.language.replace("-", "_"),
327
+ initialState: locale,
136
328
  contextName: LOCALE_CONTEXT_NAME
137
329
  }).start();
138
330
  window.squatchLocale = globalProvider;
@@ -142,7 +334,7 @@ function lazilyStartLocaleContext() {
142
334
  function setLocale(locale) {
143
335
  const globalProvider = lazilyStartLocaleContext();
144
336
  if (globalProvider.context !== locale) {
145
- debug2(`Setting locale context value [${locale}]`);
337
+ debug3(`Setting locale context value [${locale}]`);
146
338
  globalProvider.context = locale;
147
339
  }
148
340
  }
@@ -152,7 +344,7 @@ function getLocale() {
152
344
  }
153
345
 
154
346
  // src/fetchLocale.ts
155
- var debug3 = (...args) => debug(LOCALE_CONTEXT_NAME, ...args);
347
+ var debug4 = (...args) => debug(LOCALE_CONTEXT_NAME, ...args);
156
348
  var GET_LOCALE = `
157
349
  query {
158
350
  viewer {
@@ -164,7 +356,7 @@ var GET_LOCALE = `
164
356
  `;
165
357
  async function fetchLocale() {
166
358
  var _a;
167
- debug3("Fetching locale from GraphQL for current user");
359
+ debug4("Fetching locale from GraphQL for current user");
168
360
  try {
169
361
  const result = await fetch(`${getAppDomain()}/api/v1/${getTenantAlias()}/graphql`, {
170
362
  method: "POST",
@@ -185,13 +377,13 @@ async function fetchLocale() {
185
377
  }
186
378
  return json.data.viewer.locale || void 0;
187
379
  } catch (e) {
188
- debug3(`Failed to fetch locale for current user`, e.message);
380
+ debug4(`Failed to fetch locale for current user`, e.message);
189
381
  return void 0;
190
382
  }
191
383
  }
192
384
 
193
385
  // src/listeners.ts
194
- var debug4 = (...args) => debug(LOCALE_CONTEXT_NAME, ...args);
386
+ var debug5 = (...args) => debug(LOCALE_CONTEXT_NAME, ...args);
195
387
  var userContextListenerDiv = (() => {
196
388
  const id = "__environment_context_listener";
197
389
  let div = document.getElementById(id);
@@ -211,30 +403,30 @@ var userContextListenerForLocale = new ContextListener({
211
403
  const defaultLocale = ((_a = window.widgetIdent) == null ? void 0 : _a.locale) || navigator.language.replace("-", "_");
212
404
  let newLocale;
213
405
  if (next) {
214
- debug4("User context changed, refetching locale");
406
+ debug5("User context changed, refetching locale");
215
407
  const locale = await fetchLocale();
216
408
  if (localeProvider.context !== locale) {
217
- debug4(`New value fetched from GraphQL [${locale}]`);
409
+ debug5(`New value fetched from GraphQL [${locale}]`);
218
410
  newLocale = locale || defaultLocale;
219
411
  }
220
412
  } else {
221
413
  newLocale = defaultLocale;
222
414
  }
223
- debug4(`Setting locale context to [${newLocale}]`);
415
+ debug5(`Setting locale context to [${newLocale}]`);
224
416
  localeProvider.context = newLocale;
225
417
  }
226
418
  });
227
419
  function startUserContextListenerForLocale() {
228
- debug4("Starting user context listener for locale updates");
420
+ debug5("Starting user context listener for locale updates");
229
421
  userContextListenerForLocale.start();
230
422
  }
231
423
 
232
424
  // src/contexts/UserIdentityContext.ts
233
- var debug5 = (...args) => debug(USER_CONTEXT_NAME, ...args);
425
+ var debug6 = (...args) => debug(USER_CONTEXT_NAME, ...args);
234
426
  function lazilyStartUserContext() {
235
427
  let globalProvider = window.squatchUserIdentity;
236
428
  if (!globalProvider) {
237
- debug5("Creating user context provider");
429
+ debug6("Creating user context provider");
238
430
  globalProvider = new ContextProvider2({
239
431
  element: document.documentElement,
240
432
  initialState: _getInitialValue(),
@@ -320,7 +512,7 @@ function _getInitialValue() {
320
512
  function setUserIdentity(identity) {
321
513
  const globalProvider = lazilyStartUserContext();
322
514
  if (!equal(globalProvider.context, identity)) {
323
- debug5(`Setting user context value [${JSON.stringify(identity)}]`);
515
+ debug6(`Setting user context value [${JSON.stringify(identity)}]`);
324
516
  globalProvider.context = identity;
325
517
  }
326
518
  if (identity && getEnvironmentSDK().type === "SquatchPortal") {
@@ -336,12 +528,12 @@ function getUserIdentity() {
336
528
 
337
529
  // src/contexts/ProgramContext.ts
338
530
  import { ContextProvider as ContextProvider3 } from "dom-context";
339
- var debug6 = (...args) => debug(PROGRAM_CONTEXT_NAME, ...args);
531
+ var debug7 = (...args) => debug(PROGRAM_CONTEXT_NAME, ...args);
340
532
  function lazilyStartProgramContext() {
341
533
  var _a;
342
534
  let globalProvider = window.squatchProgramId;
343
535
  if (!globalProvider) {
344
- debug6("Creating program context provider");
536
+ debug7("Creating program context provider");
345
537
  globalProvider = new ContextProvider3({
346
538
  element: document.documentElement,
347
539
  initialState: ((_a = window.widgetIdent) == null ? void 0 : _a.programId) || void 0,
@@ -354,17 +546,20 @@ function lazilyStartProgramContext() {
354
546
  function setProgramId(programId) {
355
547
  const globalProvider = lazilyStartProgramContext();
356
548
  if (globalProvider.context !== programId) {
357
- debug6(`Setting program context value [${programId}]`);
549
+ debug7(`Setting program context value [${programId}]`);
358
550
  globalProvider.context = programId;
359
551
  }
360
552
  }
361
553
  function getProgramId() {
362
554
  var _a;
363
- return (_a = window.squatchLocale) == null ? void 0 : _a.context;
555
+ return (_a = window.squatchProgramId) == null ? void 0 : _a.context;
364
556
  }
365
557
  export {
558
+ BrowserHistory,
366
559
  DEFAULT_MEDIUM,
367
560
  LOCALE_CONTEXT_NAME,
561
+ LazyHistory,
562
+ MemoryHistory,
368
563
  PROGRAM_CONTEXT_NAME,
369
564
  USER_CONTEXT_NAME,
370
565
  getAppDomain,
@@ -375,6 +570,7 @@ export {
375
570
  getProgramId,
376
571
  getTenantAlias,
377
572
  getUserIdentity,
573
+ history_default as history,
378
574
  isDemo,
379
575
  lazilyStartLocaleContext,
380
576
  lazilyStartProgramContext,
@@ -382,5 +578,6 @@ export {
382
578
  setLocale,
383
579
  setProgramId,
384
580
  setUserIdentity,
385
- userIdentityFromJwt
581
+ userIdentityFromJwt,
582
+ validateLocale
386
583
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@saasquatch/component-environment",
3
- "version": "1.0.0-4",
3
+ "version": "1.0.1-0",
4
4
  "description": "Environment and contexts for SaaSquatch components",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",
@@ -9,7 +9,7 @@
9
9
  ],
10
10
  "scripts": {
11
11
  "build": "tsup src/index.ts --format esm,cjs --dts",
12
- "test": "echo \"Error: no test specified\" && exit 1"
12
+ "test": "jest"
13
13
  },
14
14
  "engines": {
15
15
  "node": ">=16.15"
@@ -22,6 +22,11 @@
22
22
  "author": "Johan Venter <johan@saasquatch.com>",
23
23
  "license": "ISC",
24
24
  "devDependencies": {
25
+ "@types/jest": "^28.1.4",
26
+ "jest": "^28.1.2",
27
+ "jest-environment-jsdom": "^28.1.2",
28
+ "ts-jest": "^28.0.5",
29
+ "ts-node": "^10.8.2",
25
30
  "tsup": "^6.1.2",
26
31
  "typescript": "^4.7.3"
27
32
  },