@shipeasy/sdk 2.1.2 → 2.1.5

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.
@@ -143,6 +143,8 @@ interface BootstrapPayload {
143
143
  /** Set by getBootstrapHtml() for auto-init. Not part of evaluate() output. */
144
144
  apiKey?: string;
145
145
  apiUrl?: string;
146
+ /** When true, tEl() returns marker-wrapped strings for devtools label editing. */
147
+ editLabels?: boolean;
146
148
  }
147
149
  /**
148
150
  * Universal flags facade. Methods return safe defaults when the singleton
@@ -143,6 +143,8 @@ interface BootstrapPayload {
143
143
  /** Set by getBootstrapHtml() for auto-init. Not part of evaluate() output. */
144
144
  apiKey?: string;
145
145
  apiUrl?: string;
146
+ /** When true, tEl() returns marker-wrapped strings for devtools label editing. */
147
+ editLabels?: boolean;
146
148
  }
147
149
  /**
148
150
  * Universal flags facade. Methods return safe defaults when the singleton
@@ -784,9 +784,16 @@ function labelAttrs(key, variables, desc) {
784
784
  }
785
785
  var _createElement = null;
786
786
  var _I18N_SSR_SYM = /* @__PURE__ */ Symbol.for("@shipeasy/sdk:ssr-i18n");
787
+ var _EDIT_MODE_SSR_SYM = /* @__PURE__ */ Symbol.for("@shipeasy/sdk:ssr-edit-mode");
787
788
  function getSSRI18nStore() {
788
789
  return globalThis[_I18N_SSR_SYM]?.() ?? null;
789
790
  }
791
+ function isEditLabelsMode() {
792
+ if (typeof window !== "undefined") {
793
+ return !!window.__SE_BOOTSTRAP?.editLabels || new URLSearchParams(location.search).has("se_edit_labels");
794
+ }
795
+ return globalThis[_EDIT_MODE_SSR_SYM]?.() ?? false;
796
+ }
790
797
  function interpolate(raw, variables) {
791
798
  if (!variables) return raw;
792
799
  return raw.replace(/\{\{(\w+)\}\}/g, (_, k) => String(variables[k] ?? `{{${k}}}`));
@@ -812,9 +819,11 @@ var i18n = {
812
819
  */
813
820
  tEl(key, fallback, variables, desc) {
814
821
  const hasTranslation = typeof window !== "undefined" && Boolean(window.i18n) || Boolean(getSSRI18nStore()?.strings[key]);
815
- const text = hasTranslation ? this.t(key, variables) || fallback : fallback;
816
- if (!_createElement) return text;
817
- return _createElement("span", labelAttrs(key, variables, desc), text);
822
+ const translated = hasTranslation ? this.t(key, variables) : void 0;
823
+ const text = translated && translated !== key ? translated : fallback;
824
+ if (isEditLabelsMode()) return encodeLabelMarker(key, text);
825
+ if (_createElement) return _createElement("span", labelAttrs(key, variables, desc), text);
826
+ return text;
818
827
  },
819
828
  /** Wire up the element creator once at app startup (call before any tEl use). */
820
829
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
@@ -741,9 +741,16 @@ function labelAttrs(key, variables, desc) {
741
741
  }
742
742
  var _createElement = null;
743
743
  var _I18N_SSR_SYM = /* @__PURE__ */ Symbol.for("@shipeasy/sdk:ssr-i18n");
744
+ var _EDIT_MODE_SSR_SYM = /* @__PURE__ */ Symbol.for("@shipeasy/sdk:ssr-edit-mode");
744
745
  function getSSRI18nStore() {
745
746
  return globalThis[_I18N_SSR_SYM]?.() ?? null;
746
747
  }
748
+ function isEditLabelsMode() {
749
+ if (typeof window !== "undefined") {
750
+ return !!window.__SE_BOOTSTRAP?.editLabels || new URLSearchParams(location.search).has("se_edit_labels");
751
+ }
752
+ return globalThis[_EDIT_MODE_SSR_SYM]?.() ?? false;
753
+ }
747
754
  function interpolate(raw, variables) {
748
755
  if (!variables) return raw;
749
756
  return raw.replace(/\{\{(\w+)\}\}/g, (_, k) => String(variables[k] ?? `{{${k}}}`));
@@ -769,9 +776,11 @@ var i18n = {
769
776
  */
770
777
  tEl(key, fallback, variables, desc) {
771
778
  const hasTranslation = typeof window !== "undefined" && Boolean(window.i18n) || Boolean(getSSRI18nStore()?.strings[key]);
772
- const text = hasTranslation ? this.t(key, variables) || fallback : fallback;
773
- if (!_createElement) return text;
774
- return _createElement("span", labelAttrs(key, variables, desc), text);
779
+ const translated = hasTranslation ? this.t(key, variables) : void 0;
780
+ const text = translated && translated !== key ? translated : fallback;
781
+ if (isEditLabelsMode()) return encodeLabelMarker(key, text);
782
+ if (_createElement) return _createElement("span", labelAttrs(key, variables, desc), text);
783
+ return text;
775
784
  },
776
785
  /** Wire up the element creator once at app startup (call before any tEl use). */
777
786
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
@@ -136,6 +136,8 @@ interface BootstrapHtmlOptions {
136
136
  apiKey: string;
137
137
  /** i18n profile fed to the loader script. Defaults to "en:prod". */
138
138
  i18nProfile?: string;
139
+ /** When true, tEl() embeds label markers so the devtools can highlight them. */
140
+ editLabels?: boolean;
139
141
  }
140
142
  /**
141
143
  * Returns a vanilla-JS script string for a single <script> tag.
@@ -136,6 +136,8 @@ interface BootstrapHtmlOptions {
136
136
  apiKey: string;
137
137
  /** i18n profile fed to the loader script. Defaults to "en:prod". */
138
138
  i18nProfile?: string;
139
+ /** When true, tEl() embeds label markers so the devtools can highlight them. */
140
+ editLabels?: boolean;
139
141
  }
140
142
  /**
141
143
  * Returns a vanilla-JS script string for a single <script> tag.
@@ -191,7 +191,7 @@ var FlagsClient = class {
191
191
  initialized = false;
192
192
  constructor(opts) {
193
193
  this.apiKey = opts.apiKey;
194
- this.baseUrl = (opts.baseUrl ?? "https://edge.shipeasy.dev").replace(/\/$/, "");
194
+ this.baseUrl = (opts.baseUrl ?? "https://cdn.shipeasy.ai").replace(/\/$/, "");
195
195
  this.env = opts.env ?? "prod";
196
196
  }
197
197
  async init() {
@@ -354,8 +354,11 @@ var FlagsClient = class {
354
354
  }
355
355
  };
356
356
  var _I18N_SSR_SYM = /* @__PURE__ */ Symbol.for("@shipeasy/sdk:ssr-i18n");
357
+ var _EDIT_MODE_SSR_SYM = /* @__PURE__ */ Symbol.for("@shipeasy/sdk:ssr-edit-mode");
357
358
  var _i18nALS = new import_node_async_hooks.AsyncLocalStorage();
359
+ var _editModeALS = new import_node_async_hooks.AsyncLocalStorage();
358
360
  globalThis[_I18N_SSR_SYM] = () => _i18nALS.getStore() ?? null;
361
+ globalThis[_EDIT_MODE_SSR_SYM] = () => _editModeALS.getStore() ?? false;
359
362
  var i18n = {
360
363
  /**
361
364
  * Fetch translation labels for the current request and store them in an
@@ -438,6 +441,8 @@ async function shipeasy(opts) {
438
441
  const clientKey = opts.clientKey ?? opts.apiKey ?? "";
439
442
  const profile = opts.i18nDefaultProfile ?? "en:prod";
440
443
  flags.configure({ apiKey });
444
+ const editLabels = opts.urlOverrides ? new URLSearchParams(opts.urlOverrides).has("se_edit_labels") : false;
445
+ _editModeALS.enterWith(editLabels);
441
446
  await Promise.allSettled([flags.initOnce(), i18n.init(clientKey, profile)]);
442
447
  const bootstrap = flags.evaluate(opts.user ?? {}, opts.urlOverrides);
443
448
  const i18nData = i18n.getForRequest();
@@ -446,7 +451,7 @@ async function shipeasy(opts) {
446
451
  configs: bootstrap.configs,
447
452
  experiments: bootstrap.experiments,
448
453
  getBootstrapHtml() {
449
- return getBootstrapHtml(bootstrap, i18nData, { apiKey: clientKey });
454
+ return getBootstrapHtml(bootstrap, i18nData, { apiKey: clientKey, editLabels });
450
455
  }
451
456
  };
452
457
  }
@@ -462,6 +467,7 @@ function getBootstrapHtml(bootstrap, i18nData, opts) {
462
467
  apiUrl
463
468
  };
464
469
  if (i18nData) payload.i18n = i18nData;
470
+ if (opts.editLabels) payload.editLabels = true;
465
471
  parts.push(`window.__SE_BOOTSTRAP=${JSON.stringify(payload)};`);
466
472
  if (i18nData?.strings && Object.keys(i18nData.strings).length > 0) {
467
473
  parts.push(
@@ -471,6 +477,9 @@ function getBootstrapHtml(bootstrap, i18nData, opts) {
471
477
  parts.push(
472
478
  `(function(){var s=document.createElement('script');s.src=${JSON.stringify(`${apiUrl}/sdk/i18n/loader.js`)};s.setAttribute('data-key',${JSON.stringify(opts.apiKey)});s.setAttribute('data-profile',${JSON.stringify(profile)});document.head.appendChild(s);})();`
473
479
  );
480
+ parts.push(
481
+ `(function(){var p=new URLSearchParams(location.search);if(p.has('se')||p.has('se_devtools')){var d=document.createElement('script');d.src='https://shipeasy.ai/se-devtools.js';document.head.appendChild(d);}})();`
482
+ );
474
483
  return parts.join("");
475
484
  }
476
485
  var flags = {
@@ -158,7 +158,7 @@ var FlagsClient = class {
158
158
  initialized = false;
159
159
  constructor(opts) {
160
160
  this.apiKey = opts.apiKey;
161
- this.baseUrl = (opts.baseUrl ?? "https://edge.shipeasy.dev").replace(/\/$/, "");
161
+ this.baseUrl = (opts.baseUrl ?? "https://cdn.shipeasy.ai").replace(/\/$/, "");
162
162
  this.env = opts.env ?? "prod";
163
163
  }
164
164
  async init() {
@@ -321,8 +321,11 @@ var FlagsClient = class {
321
321
  }
322
322
  };
323
323
  var _I18N_SSR_SYM = /* @__PURE__ */ Symbol.for("@shipeasy/sdk:ssr-i18n");
324
+ var _EDIT_MODE_SSR_SYM = /* @__PURE__ */ Symbol.for("@shipeasy/sdk:ssr-edit-mode");
324
325
  var _i18nALS = new AsyncLocalStorage();
326
+ var _editModeALS = new AsyncLocalStorage();
325
327
  globalThis[_I18N_SSR_SYM] = () => _i18nALS.getStore() ?? null;
328
+ globalThis[_EDIT_MODE_SSR_SYM] = () => _editModeALS.getStore() ?? false;
326
329
  var i18n = {
327
330
  /**
328
331
  * Fetch translation labels for the current request and store them in an
@@ -405,6 +408,8 @@ async function shipeasy(opts) {
405
408
  const clientKey = opts.clientKey ?? opts.apiKey ?? "";
406
409
  const profile = opts.i18nDefaultProfile ?? "en:prod";
407
410
  flags.configure({ apiKey });
411
+ const editLabels = opts.urlOverrides ? new URLSearchParams(opts.urlOverrides).has("se_edit_labels") : false;
412
+ _editModeALS.enterWith(editLabels);
408
413
  await Promise.allSettled([flags.initOnce(), i18n.init(clientKey, profile)]);
409
414
  const bootstrap = flags.evaluate(opts.user ?? {}, opts.urlOverrides);
410
415
  const i18nData = i18n.getForRequest();
@@ -413,7 +418,7 @@ async function shipeasy(opts) {
413
418
  configs: bootstrap.configs,
414
419
  experiments: bootstrap.experiments,
415
420
  getBootstrapHtml() {
416
- return getBootstrapHtml(bootstrap, i18nData, { apiKey: clientKey });
421
+ return getBootstrapHtml(bootstrap, i18nData, { apiKey: clientKey, editLabels });
417
422
  }
418
423
  };
419
424
  }
@@ -429,6 +434,7 @@ function getBootstrapHtml(bootstrap, i18nData, opts) {
429
434
  apiUrl
430
435
  };
431
436
  if (i18nData) payload.i18n = i18nData;
437
+ if (opts.editLabels) payload.editLabels = true;
432
438
  parts.push(`window.__SE_BOOTSTRAP=${JSON.stringify(payload)};`);
433
439
  if (i18nData?.strings && Object.keys(i18nData.strings).length > 0) {
434
440
  parts.push(
@@ -438,6 +444,9 @@ function getBootstrapHtml(bootstrap, i18nData, opts) {
438
444
  parts.push(
439
445
  `(function(){var s=document.createElement('script');s.src=${JSON.stringify(`${apiUrl}/sdk/i18n/loader.js`)};s.setAttribute('data-key',${JSON.stringify(opts.apiKey)});s.setAttribute('data-profile',${JSON.stringify(profile)});document.head.appendChild(s);})();`
440
446
  );
447
+ parts.push(
448
+ `(function(){var p=new URLSearchParams(location.search);if(p.has('se')||p.has('se_devtools')){var d=document.createElement('script');d.src='https://shipeasy.ai/se-devtools.js';document.head.appendChild(d);}})();`
449
+ );
441
450
  return parts.join("");
442
451
  }
443
452
  var flags = {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@shipeasy/sdk",
3
- "version": "2.1.2",
3
+ "version": "2.1.5",
4
4
  "description": "Shipeasy SDK — feature gates, runtime configs, experiments, and metrics for the Shipeasy hosted service.",
5
5
  "license": "SEE LICENSE IN LICENSE",
6
6
  "homepage": "https://shipeasy.ai",