@lionrapid/core 0.6.1 → 0.6.2

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.
Files changed (42) hide show
  1. package/dist/browser/auto-init.d.ts +8 -3
  2. package/dist/browser/auto-init.d.ts.map +1 -1
  3. package/dist/browser/auto-init.js +34 -26
  4. package/dist/browser/auto-init.js.map +1 -1
  5. package/dist/browser/lionrapid.auto.dev.js +264 -24
  6. package/dist/browser/lionrapid.auto.dev.js.map +2 -2
  7. package/dist/browser/lionrapid.auto.js +264 -24
  8. package/dist/browser/lionrapid.auto.js.map +2 -2
  9. package/dist/browser/lionrapid.auto.min.js +4 -4
  10. package/dist/browser/lionrapid.auto.min.js.map +3 -3
  11. package/dist/browser/lionrapid.esm.js +238 -2
  12. package/dist/browser/lionrapid.esm.js.map +2 -2
  13. package/dist/browser/lionrapid.esm.min.js +3 -3
  14. package/dist/browser/lionrapid.esm.min.js.map +3 -3
  15. package/dist/browser/lionrapid.iife.dev.js +238 -2
  16. package/dist/browser/lionrapid.iife.dev.js.map +2 -2
  17. package/dist/browser/lionrapid.iife.js +238 -2
  18. package/dist/browser/lionrapid.iife.js.map +2 -2
  19. package/dist/browser/lionrapid.iife.min.js +3 -3
  20. package/dist/browser/lionrapid.iife.min.js.map +3 -3
  21. package/dist/browser/lionrapid.umd.js +238 -2
  22. package/dist/browser/lionrapid.umd.js.map +2 -2
  23. package/dist/browser/lionrapid.umd.min.js +3 -3
  24. package/dist/browser/lionrapid.umd.min.js.map +3 -3
  25. package/dist/browser/storage/cache-storage-repository.d.ts +65 -0
  26. package/dist/browser/storage/cache-storage-repository.d.ts.map +1 -1
  27. package/dist/browser/storage/cache-storage-repository.js +77 -7
  28. package/dist/browser/storage/cache-storage-repository.js.map +1 -1
  29. package/dist/browser/storage/localstorage-repository.d.ts +62 -0
  30. package/dist/browser/storage/localstorage-repository.d.ts.map +1 -1
  31. package/dist/browser/storage/localstorage-repository.js +71 -4
  32. package/dist/browser/storage/localstorage-repository.js.map +1 -1
  33. package/dist/config/repository.config.d.ts +17 -0
  34. package/dist/config/repository.config.d.ts.map +1 -1
  35. package/dist/index.d.ts +1 -1
  36. package/dist/index.d.ts.map +1 -1
  37. package/dist/index.js.map +1 -1
  38. package/dist/repositories/network-repository.d.ts +42 -1
  39. package/dist/repositories/network-repository.d.ts.map +1 -1
  40. package/dist/repositories/network-repository.js +149 -1
  41. package/dist/repositories/network-repository.js.map +1 -1
  42. package/package.json +1 -1
@@ -3844,6 +3844,31 @@ var __lionrapidAutoExports = (() => {
3844
3844
  * and payload can never desync because they live and die together.
3845
3845
  */
3846
3846
  __publicField(this, "namespaceSnapshots", /* @__PURE__ */ new Map());
3847
+ /**
3848
+ * Miss-path flood protection (READINESS before-scale #1: one cold locale
3849
+ * switch measured ~380 requests in 10 s — every t() miss refired a key GET
3850
+ * and a namespace GET on every re-render, forever on animated pages).
3851
+ */
3852
+ /** GETs currently on the wire, keyed by `url|if-none-match` — identical
3853
+ * concurrent requests share one fetch; each awaiter gets a clone. The
3854
+ * If-None-Match value is part of the key so the 304-without-snapshot
3855
+ * unconditional refetch never coalesces onto a conditional flight. */
3856
+ __publicField(this, "inflightGets", /* @__PURE__ */ new Map());
3857
+ /** URL → 404/423 seen recently: repeats are answered locally (same typed
3858
+ * error, no network) until `until`. 423 honors the server's Retry-After.
3859
+ * Cleared entirely by any successful write — discovery sync keeps its
3860
+ * miss → batch → served-back round-trip. */
3861
+ __publicField(this, "negativeCache", /* @__PURE__ */ new Map());
3862
+ /** One-way latch: a 401 anywhere (or a 403 on a READ) means the key is
3863
+ * wrong or unauthorized for this project, and retrying cannot heal it —
3864
+ * after the first one nothing touches the network again for this
3865
+ * instance (a page reload starts fresh). Holds the status that tripped
3866
+ * it so short-circuits answer honestly. */
3867
+ __publicField(this, "authFailedStatus", null);
3868
+ /** Write-only latch (auth-byok Phase 18): a 403 (scope) or 429 (quota) on
3869
+ * a WRITE degrades this instance to read-only — writes stop, silently
3870
+ * and without retries, while reads keep serving the page. */
3871
+ __publicField(this, "writesFailedStatus", null);
3847
3872
  /**
3848
3873
  * Default endpoint templates with placeholder support
3849
3874
  * Placeholders: :key, :locale, :namespace
@@ -3851,6 +3876,7 @@ var __lionrapidAutoExports = (() => {
3851
3876
  __publicField(this, "DEFAULT_ENDPOINTS", {
3852
3877
  getTranslation: "/api/integrations/translations/:key",
3853
3878
  getNamespace: "/api/integrations/translations/:locale/:namespace",
3879
+ getProjectConfig: "/api/integrations/project-config",
3854
3880
  setTranslation: "/api/integrations/sync/:key",
3855
3881
  setNamespace: "/api/integrations/sync/:locale/:namespace",
3856
3882
  setBatch: "/api/integrations/sync/batch",
@@ -3962,6 +3988,40 @@ var __lionrapidAutoExports = (() => {
3962
3988
  this.handleCaughtError(error);
3963
3989
  }
3964
3990
  }
3991
+ /**
3992
+ * Project-level config for this key — the dashboard's language list,
3993
+ * served under the same trust model as translation reads (docs/20,
3994
+ * companion track). Returns null when the server doesn't expose the
3995
+ * endpoint (404 — older server, feature not deployed) or the payload is
3996
+ * unusable: absence means "keep your local fallback", never an error.
3997
+ */
3998
+ async getProjectConfig() {
3999
+ if (!this.config?.options?.baseUrl) {
4000
+ throw new NetworkError("API base URL is not set");
4001
+ }
4002
+ const url = this.buildUrl("getProjectConfig", {});
4003
+ logger.debug(`API GET ProjectConfig: ${url}`);
4004
+ try {
4005
+ const response = await this.makeRequest(url, "GET");
4006
+ if (response.status === 404) {
4007
+ return null;
4008
+ }
4009
+ if (!response.ok) {
4010
+ this.handleHttpError(response, "project-config");
4011
+ }
4012
+ const data = await response.json();
4013
+ if (!data || typeof data.defaultLocale !== "string" || !Array.isArray(data.languages)) {
4014
+ logger.warn("project-config payload unusable \u2014 keeping local fallback");
4015
+ return null;
4016
+ }
4017
+ return {
4018
+ defaultLocale: data.defaultLocale,
4019
+ languages: data.languages.map(String)
4020
+ };
4021
+ } catch (error) {
4022
+ this.handleCaughtError(error);
4023
+ }
4024
+ }
3965
4025
  /**
3966
4026
  * Shared namespace fetch with the canonical 304 contract:
3967
4027
  * - If-None-Match is sent ONLY when a snapshot (version + payload) is in hand.
@@ -4286,7 +4346,87 @@ var __lionrapidAutoExports = (() => {
4286
4346
  /**
4287
4347
  * Make HTTP request with timeout and headers
4288
4348
  */
4289
- async makeRequest(url, method, body, extraHeaders) {
4349
+ makeRequest(url, method, body, extraHeaders) {
4350
+ if (this.authFailedStatus !== null) {
4351
+ return Promise.resolve(
4352
+ new Response(null, {
4353
+ status: this.authFailedStatus,
4354
+ statusText: `auth latched off after ${this.authFailedStatus}`
4355
+ })
4356
+ );
4357
+ }
4358
+ if (method !== "GET") {
4359
+ if (this.writesFailedStatus !== null) {
4360
+ return Promise.resolve(
4361
+ new Response(null, {
4362
+ status: this.writesFailedStatus,
4363
+ statusText: `writes latched off after ${this.writesFailedStatus}`
4364
+ })
4365
+ );
4366
+ }
4367
+ return this.doFetch(url, method, body, extraHeaders).then(
4368
+ (resp) => this.recordOutcome(url, method, resp)
4369
+ );
4370
+ }
4371
+ const negative = this.negativeCache.get(url);
4372
+ if (negative) {
4373
+ if (Date.now() < negative.until) {
4374
+ logger.debug(`Negative-cache hit (${negative.status}): ${url}`);
4375
+ const headers = negative.status === 423 ? { "Retry-After": String(Math.ceil((negative.until - Date.now()) / 1e3)) } : void 0;
4376
+ return Promise.resolve(
4377
+ new Response(null, { status: negative.status, statusText: "negative cache", headers })
4378
+ );
4379
+ }
4380
+ this.negativeCache.delete(url);
4381
+ }
4382
+ const flightKey = `${url}|${extraHeaders?.["If-None-Match"] ?? ""}`;
4383
+ const existing = this.inflightGets.get(flightKey);
4384
+ if (existing) {
4385
+ return existing.then((resp) => this.cloneResponse(resp));
4386
+ }
4387
+ const flight = this.doFetch(url, method, body, extraHeaders).then((resp) => this.recordOutcome(url, method, resp)).finally(() => this.inflightGets.delete(flightKey));
4388
+ this.inflightGets.set(flightKey, flight);
4389
+ return flight.then((resp) => this.cloneResponse(resp));
4390
+ }
4391
+ /** Bookkeeping on every real (non-synthesized) response — runs once per
4392
+ * physical fetch, never once per coalesced awaiter. */
4393
+ recordOutcome(url, method, response) {
4394
+ const status = response.status;
4395
+ if (status === 401 || status === 403 && method === "GET") {
4396
+ if (this.authFailedStatus === null) {
4397
+ this.authFailedStatus = status;
4398
+ console.warn(
4399
+ `[LionRapid] API key rejected (${status}) \u2014 network translations are disabled for this session. Fix the key and reload; retrying cannot heal an auth failure.`
4400
+ );
4401
+ }
4402
+ return response;
4403
+ }
4404
+ if ((status === 403 || status === 429) && method !== "GET") {
4405
+ if (this.writesFailedStatus === null) {
4406
+ this.writesFailedStatus = status;
4407
+ logger.warn(
4408
+ `Write path disabled after ${status} (scope/quota) \u2014 running read-only`
4409
+ );
4410
+ }
4411
+ return response;
4412
+ }
4413
+ if (method === "GET" && (status === 404 || status === 423)) {
4414
+ const retryAfterSec = status === 423 ? Number(response.headers?.get?.("Retry-After")) : NaN;
4415
+ const ttl = Number.isFinite(retryAfterSec) && retryAfterSec > 0 ? retryAfterSec * 1e3 : this.config.options?.negativeCacheTtlMs ?? _NetworkRepository.DEFAULT_NEGATIVE_TTL_MS;
4416
+ this.negativeCache.set(url, { status, until: Date.now() + ttl });
4417
+ } else if (method !== "GET" && response.ok) {
4418
+ this.negativeCache.clear();
4419
+ } else if (method === "GET" && response.ok) {
4420
+ this.negativeCache.delete(url);
4421
+ }
4422
+ return response;
4423
+ }
4424
+ /** Test doubles (and exotic runtimes) hand us plain objects — only real
4425
+ * Responses need cloning so each coalesced awaiter can read the body. */
4426
+ cloneResponse(response) {
4427
+ return typeof response.clone === "function" ? response.clone() : response;
4428
+ }
4429
+ async doFetch(url, method, body, extraHeaders) {
4290
4430
  const controller = new AbortController();
4291
4431
  const timeout = this.config.options?.timeout ?? 1e4;
4292
4432
  const timeoutId = setTimeout(
@@ -4319,6 +4459,7 @@ var __lionrapidAutoExports = (() => {
4319
4459
  /** Legacy bare-version prefix — a version WITHOUT its payload is exactly the
4320
4460
  * desync the snapshot store exists to prevent; entries are deleted on sight. */
4321
4461
  __publicField(_NetworkRepository, "LEGACY_VERSION_PREFIX", "lionrapid:v:");
4462
+ __publicField(_NetworkRepository, "DEFAULT_NEGATIVE_TTL_MS", 6e4);
4322
4463
  var NetworkRepository = _NetworkRepository;
4323
4464
 
4324
4465
  // src/browser/exclude-filter.ts
@@ -5561,9 +5702,11 @@ var __lionrapidAutoExports = (() => {
5561
5702
  this.config = {
5562
5703
  enabled: config.enabled ?? true,
5563
5704
  priority: config.priority ?? 0,
5705
+ // Use build sequence by default
5564
5706
  options: {
5565
5707
  prefix: config.options?.prefix ?? STORAGE_PREFIX,
5566
5708
  ttl: config.options?.ttl ?? 24 * 60 * 60 * 1e3,
5709
+ // 24 hours default
5567
5710
  maxSize: config.options?.maxSize ?? 500,
5568
5711
  ...config.options
5569
5712
  }
@@ -5576,6 +5719,10 @@ var __lionrapidAutoExports = (() => {
5576
5719
  this.migrateIfNeeded();
5577
5720
  }
5578
5721
  }
5722
+ /**
5723
+ * Check if localStorage is available
5724
+ * Returns false in SSR, private browsing, or when quota is 0
5725
+ */
5579
5726
  checkAvailability() {
5580
5727
  if (typeof window === "undefined") {
5581
5728
  return false;
@@ -5589,6 +5736,9 @@ var __lionrapidAutoExports = (() => {
5589
5736
  return false;
5590
5737
  }
5591
5738
  }
5739
+ /**
5740
+ * Handle version migrations - clear cache when version changes
5741
+ */
5592
5742
  migrateIfNeeded() {
5593
5743
  try {
5594
5744
  const storedVersion = window.localStorage.getItem(VERSION_KEY);
@@ -5599,6 +5749,10 @@ var __lionrapidAutoExports = (() => {
5599
5749
  } catch {
5600
5750
  }
5601
5751
  }
5752
+ /**
5753
+ * Get a translation value by key
5754
+ * Returns null if not found or expired
5755
+ */
5602
5756
  get(key) {
5603
5757
  if (!this.available) return null;
5604
5758
  try {
@@ -5615,6 +5769,10 @@ var __lionrapidAutoExports = (() => {
5615
5769
  return null;
5616
5770
  }
5617
5771
  }
5772
+ /**
5773
+ * Set a translation value
5774
+ * Automatically handles quota exceeded by evicting oldest entries
5775
+ */
5618
5776
  set(key, value) {
5619
5777
  if (!this.available) return;
5620
5778
  const fullKey = this.prefix + key;
@@ -5639,6 +5797,9 @@ var __lionrapidAutoExports = (() => {
5639
5797
  }
5640
5798
  }
5641
5799
  }
5800
+ /**
5801
+ * Remove a translation by key
5802
+ */
5642
5803
  remove(key) {
5643
5804
  if (!this.available) return;
5644
5805
  try {
@@ -5646,6 +5807,10 @@ var __lionrapidAutoExports = (() => {
5646
5807
  } catch {
5647
5808
  }
5648
5809
  }
5810
+ /**
5811
+ * Clear all LionRapid entries from localStorage
5812
+ * Preserves entries from other applications
5813
+ */
5649
5814
  clear() {
5650
5815
  if (!this.available) return;
5651
5816
  try {
@@ -5660,6 +5825,9 @@ var __lionrapidAutoExports = (() => {
5660
5825
  } catch {
5661
5826
  }
5662
5827
  }
5828
+ /**
5829
+ * Clear all entries for a specific namespace
5830
+ */
5663
5831
  clearNamespace(locale, namespace) {
5664
5832
  if (!this.available) return;
5665
5833
  const namespaceCacheKey = `@${locale}:${namespace}`;
@@ -5678,6 +5846,9 @@ var __lionrapidAutoExports = (() => {
5678
5846
  } catch {
5679
5847
  }
5680
5848
  }
5849
+ /**
5850
+ * Get namespace translations
5851
+ */
5681
5852
  getNamespace(locale, namespace) {
5682
5853
  const namespaceCacheKey = `@${locale}:${namespace}`;
5683
5854
  const value = this.get(namespaceCacheKey);
@@ -5689,10 +5860,16 @@ var __lionrapidAutoExports = (() => {
5689
5860
  return null;
5690
5861
  }
5691
5862
  }
5863
+ /**
5864
+ * Set namespace translations
5865
+ */
5692
5866
  setNamespace(locale, namespace, translations) {
5693
5867
  const namespaceCacheKey = `@${locale}:${namespace}`;
5694
5868
  this.set(namespaceCacheKey, JSON.stringify(translations));
5695
5869
  }
5870
+ /**
5871
+ * Get all cache entries for debugging
5872
+ */
5696
5873
  getEntries() {
5697
5874
  const entries = {};
5698
5875
  if (!this.available) return entries;
@@ -5712,12 +5889,21 @@ var __lionrapidAutoExports = (() => {
5712
5889
  }
5713
5890
  return entries;
5714
5891
  }
5892
+ /**
5893
+ * Get repository configuration
5894
+ */
5715
5895
  getConfig() {
5716
5896
  return this.config;
5717
5897
  }
5898
+ /**
5899
+ * Check if localStorage is available
5900
+ */
5718
5901
  isAvailable() {
5719
5902
  return this.available;
5720
5903
  }
5904
+ /**
5905
+ * Get the number of entries in the cache
5906
+ */
5721
5907
  getEntryCount() {
5722
5908
  if (!this.available) return 0;
5723
5909
  let count = 0;
@@ -5732,12 +5918,18 @@ var __lionrapidAutoExports = (() => {
5732
5918
  }
5733
5919
  return count;
5734
5920
  }
5921
+ /**
5922
+ * Check if error is a quota exceeded error
5923
+ */
5735
5924
  isQuotaError(error) {
5736
5925
  if (error instanceof DOMException) {
5737
5926
  return error.name === "QuotaExceededError" || error.name === "NS_ERROR_DOM_QUOTA_REACHED";
5738
5927
  }
5739
5928
  return false;
5740
5929
  }
5930
+ /**
5931
+ * Evict oldest 25% of entries when quota is exceeded
5932
+ */
5741
5933
  evictOldest() {
5742
5934
  if (!this.available) return;
5743
5935
  try {
@@ -5765,6 +5957,9 @@ var __lionrapidAutoExports = (() => {
5765
5957
  } catch {
5766
5958
  }
5767
5959
  }
5960
+ /**
5961
+ * Get cache statistics
5962
+ */
5768
5963
  getCacheStats() {
5769
5964
  const size = this.getEntryCount();
5770
5965
  const usage = this.maxSize > 0 ? `${Math.round(size / this.maxSize * 100)}%` : "0%";
@@ -5778,7 +5973,7 @@ var __lionrapidAutoExports = (() => {
5778
5973
 
5779
5974
  // src/browser/storage/cache-storage-repository.ts
5780
5975
  var CACHE_NAME = "lionrapid-v1";
5781
- var CACHE_PREFIX = "lionrapid:";
5976
+ var CACHE_PREFIX = "https://cache.lionrapid.internal/";
5782
5977
  var CacheStorageRepository = class {
5783
5978
  constructor(config = {}) {
5784
5979
  __publicField(this, "name", "CacheStorageRepository");
@@ -5793,6 +5988,7 @@ var __lionrapidAutoExports = (() => {
5793
5988
  options: {
5794
5989
  cacheName: config.options?.cacheName ?? CACHE_NAME,
5795
5990
  ttl: config.options?.ttl ?? 7 * 24 * 60 * 60 * 1e3,
5991
+ // 7 days default
5796
5992
  ...config.options
5797
5993
  }
5798
5994
  };
@@ -5800,9 +5996,17 @@ var __lionrapidAutoExports = (() => {
5800
5996
  this.defaultTTL = this.config.options?.ttl ?? 7 * 24 * 60 * 60 * 1e3;
5801
5997
  this.available = this.checkAvailability();
5802
5998
  }
5999
+ /**
6000
+ * Check if Cache API is available
6001
+ * Returns false in SSR, old browsers, or insecure contexts
6002
+ */
5803
6003
  checkAvailability() {
5804
6004
  return typeof caches !== "undefined";
5805
6005
  }
6006
+ /**
6007
+ * Get a translation value by key
6008
+ * @throws {TranslationNotFoundError} When translation doesn't exist or is expired
6009
+ */
5806
6010
  async get(key) {
5807
6011
  if (!this.available) {
5808
6012
  throw new TranslationNotFoundError(key);
@@ -5826,6 +6030,9 @@ var __lionrapidAutoExports = (() => {
5826
6030
  throw new TranslationNotFoundError(key);
5827
6031
  }
5828
6032
  }
6033
+ /**
6034
+ * Set a translation value
6035
+ */
5829
6036
  async set(key, value) {
5830
6037
  if (!this.available) return;
5831
6038
  try {
@@ -5844,6 +6051,9 @@ var __lionrapidAutoExports = (() => {
5844
6051
  } catch {
5845
6052
  }
5846
6053
  }
6054
+ /**
6055
+ * Remove a translation by key
6056
+ */
5847
6057
  async remove(key) {
5848
6058
  if (!this.available) return;
5849
6059
  try {
@@ -5852,6 +6062,9 @@ var __lionrapidAutoExports = (() => {
5852
6062
  } catch {
5853
6063
  }
5854
6064
  }
6065
+ /**
6066
+ * Clear all LionRapid entries from the cache
6067
+ */
5855
6068
  async clear() {
5856
6069
  if (!this.available) return;
5857
6070
  try {
@@ -5863,6 +6076,9 @@ var __lionrapidAutoExports = (() => {
5863
6076
  } catch {
5864
6077
  }
5865
6078
  }
6079
+ /**
6080
+ * Clear all entries for a specific namespace
6081
+ */
5866
6082
  async clearNamespace(locale, namespace) {
5867
6083
  if (!this.available) return;
5868
6084
  const namespaceCacheKey = `@${locale}:${namespace}`;
@@ -5880,6 +6096,10 @@ var __lionrapidAutoExports = (() => {
5880
6096
  } catch {
5881
6097
  }
5882
6098
  }
6099
+ /**
6100
+ * Get namespace translations
6101
+ * @throws {TranslationNotFoundError} When namespace doesn't exist
6102
+ */
5883
6103
  async getNamespace(locale, namespace) {
5884
6104
  const namespaceCacheKey = `@${locale}:${namespace}`;
5885
6105
  const value = await this.get(namespaceCacheKey);
@@ -5890,16 +6110,29 @@ var __lionrapidAutoExports = (() => {
5890
6110
  throw new TranslationNotFoundError(namespaceCacheKey);
5891
6111
  }
5892
6112
  }
6113
+ /**
6114
+ * Set namespace translations
6115
+ */
5893
6116
  async setNamespace(locale, namespace, translations) {
5894
6117
  const namespaceCacheKey = `@${locale}:${namespace}`;
5895
6118
  await this.set(namespaceCacheKey, JSON.stringify(translations));
5896
6119
  }
6120
+ /**
6121
+ * Get repository configuration
6122
+ */
5897
6123
  getConfig() {
5898
6124
  return this.config;
5899
6125
  }
6126
+ /**
6127
+ * Check if Cache API is available
6128
+ */
5900
6129
  isAvailable() {
5901
6130
  return this.available;
5902
6131
  }
6132
+ /**
6133
+ * Get all cached entries (for debugging)
6134
+ * Returns an object mapping keys to values
6135
+ */
5903
6136
  async getEntries() {
5904
6137
  const entries = {};
5905
6138
  if (!this.available) return entries;
@@ -5922,6 +6155,9 @@ var __lionrapidAutoExports = (() => {
5922
6155
  }
5923
6156
  return entries;
5924
6157
  }
6158
+ /**
6159
+ * Get cache statistics
6160
+ */
5925
6161
  async getCacheStats() {
5926
6162
  if (!this.available) {
5927
6163
  return { size: 0, cacheName: this.cacheName };
@@ -5941,8 +6177,9 @@ var __lionrapidAutoExports = (() => {
5941
6177
  function resolveWritePolicy(apiKey) {
5942
6178
  const isPublishable = apiKey.startsWith("pk_");
5943
6179
  return {
6180
+ bootNetwork: isPublishable,
5944
6181
  syncMissing: { enabled: isPublishable },
5945
- warnReadOnly: !isPublishable
6182
+ warnRefused: !isPublishable
5946
6183
  };
5947
6184
  }
5948
6185
  function configForWindow(config) {
@@ -6091,9 +6328,9 @@ var __lionrapidAutoExports = (() => {
6091
6328
  return;
6092
6329
  }
6093
6330
  const writePolicy = resolveWritePolicy(config.apiKey);
6094
- if (writePolicy.warnReadOnly) {
6331
+ if (writePolicy.warnRefused) {
6095
6332
  console.error(
6096
- "[LionRapid] data-api-key must be a publishable pk_ key; running read-only"
6333
+ "[LionRapid] data-api-key must be a publishable pk_ key \u2014 network translations are disabled. Copy the snippet from the integration hub to get the pk_ key for this project."
6097
6334
  );
6098
6335
  }
6099
6336
  const initialLocale = resolveInitialLocale(config);
@@ -6147,25 +6384,28 @@ var __lionrapidAutoExports = (() => {
6147
6384
  })
6148
6385
  );
6149
6386
  }
6150
- const core = await builder.use(
6151
- new NetworkRepository({
6152
- enabled: true,
6153
- options: {
6154
- baseUrl: config.baseUrl,
6155
- apiKey: config.apiKey,
6156
- // pk_ keys sync missing source strings (discovery); anything else
6157
- // runs read-only — see resolveWritePolicy.
6158
- syncMissing: writePolicy.syncMissing,
6159
- preloadNamespaces: [
6160
- {
6161
- locale: initialLocale,
6162
- namespace: config.namespace,
6163
- eager: true
6164
- }
6165
- ]
6166
- }
6167
- })
6168
- ).build();
6387
+ if (writePolicy.bootNetwork) {
6388
+ builder.use(
6389
+ new NetworkRepository({
6390
+ enabled: true,
6391
+ options: {
6392
+ baseUrl: config.baseUrl,
6393
+ apiKey: config.apiKey,
6394
+ // pk_ keys sync missing source strings (discovery) — see
6395
+ // resolveWritePolicy.
6396
+ syncMissing: writePolicy.syncMissing,
6397
+ preloadNamespaces: [
6398
+ {
6399
+ locale: initialLocale,
6400
+ namespace: config.namespace,
6401
+ eager: true
6402
+ }
6403
+ ]
6404
+ }
6405
+ })
6406
+ );
6407
+ }
6408
+ const core = await builder.build();
6169
6409
  const autoTranslator = new AutoTranslator({
6170
6410
  excludeSelectors: config.excludeSelectors
6171
6411
  });