@carlonicora/nextjs-jsonapi 6.13.1 → 6.14.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.
Files changed (149) hide show
  1. package/dist/{BlockNoteEditor-UBVEUFNR.js → BlockNoteEditor-CUNH4LSQ.js} +25 -25
  2. package/dist/{BlockNoteEditor-UBVEUFNR.js.map → BlockNoteEditor-CUNH4LSQ.js.map} +1 -1
  3. package/dist/{BlockNoteEditor-VXMDSQAA.mjs → BlockNoteEditor-QIVV2OB4.mjs} +10 -10
  4. package/dist/{BlockNoteViewer-2XYASA5Y.js → BlockNoteViewer-APBOPT4B.js} +8 -8
  5. package/dist/{BlockNoteViewer-2XYASA5Y.js.map → BlockNoteViewer-APBOPT4B.js.map} +1 -1
  6. package/dist/{BlockNoteViewer-NBW2H6LC.mjs → BlockNoteViewer-HIUAJQRI.mjs} +7 -7
  7. package/dist/JsonApiRequest-G4J2WTSU.js +26 -0
  8. package/dist/{JsonApiRequest-WISJZSDE.js.map → JsonApiRequest-G4J2WTSU.js.map} +1 -1
  9. package/dist/{JsonApiRequest-F6TMJ42G.mjs → JsonApiRequest-IKKHWCPB.mjs} +2 -2
  10. package/dist/billing/index.js +497 -497
  11. package/dist/billing/index.mjs +9 -9
  12. package/dist/{chunk-7DBJTNSU.mjs → chunk-4RPGFQBA.mjs} +2 -2
  13. package/dist/{chunk-BZ5J2FIV.js → chunk-4XLDBOSE.js} +11 -11
  14. package/dist/{chunk-BZ5J2FIV.js.map → chunk-4XLDBOSE.js.map} +1 -1
  15. package/dist/{chunk-27LQDGNP.mjs → chunk-4ZJIUTIV.mjs} +6 -1
  16. package/dist/chunk-4ZJIUTIV.mjs.map +1 -0
  17. package/dist/{chunk-PXDUJ47N.js → chunk-6RCZ64BQ.js} +18 -18
  18. package/dist/{chunk-PXDUJ47N.js.map → chunk-6RCZ64BQ.js.map} +1 -1
  19. package/dist/{chunk-7JZHPMGW.mjs → chunk-A3RB47X4.mjs} +44 -20
  20. package/dist/chunk-A3RB47X4.mjs.map +1 -0
  21. package/dist/{chunk-DOCIFE6A.mjs → chunk-AUD6ZLBB.mjs} +3 -3
  22. package/dist/{chunk-GB6DBFYY.js → chunk-DGN3PR2F.js} +3 -3
  23. package/dist/{chunk-GB6DBFYY.js.map → chunk-DGN3PR2F.js.map} +1 -1
  24. package/dist/{chunk-7ZHTPFFT.js → chunk-DJXSCARG.js} +15 -15
  25. package/dist/{chunk-7ZHTPFFT.js.map → chunk-DJXSCARG.js.map} +1 -1
  26. package/dist/{chunk-QKNGZDSQ.js → chunk-GM4VZTWL.js} +2 -2
  27. package/dist/{chunk-QKNGZDSQ.js.map → chunk-GM4VZTWL.js.map} +1 -1
  28. package/dist/{chunk-PYRZCKC2.js → chunk-GSRTVIIK.js} +923 -923
  29. package/dist/{chunk-PYRZCKC2.js.map → chunk-GSRTVIIK.js.map} +1 -1
  30. package/dist/{chunk-47BBY5KA.mjs → chunk-HAW5PNJG.mjs} +4 -4
  31. package/dist/{chunk-YRKIFYOE.mjs → chunk-KTGKW72G.mjs} +27 -8
  32. package/dist/chunk-KTGKW72G.mjs.map +1 -0
  33. package/dist/{chunk-PV4Z5W6V.js → chunk-KV4N7DEG.js} +19 -19
  34. package/dist/{chunk-PV4Z5W6V.js.map → chunk-KV4N7DEG.js.map} +1 -1
  35. package/dist/{chunk-ZLTOUZN2.mjs → chunk-M3N7LPHX.mjs} +4 -4
  36. package/dist/{chunk-DGWOVYEC.mjs → chunk-MQ7TXALH.mjs} +2 -2
  37. package/dist/{chunk-W62MHDWM.js → chunk-N5ZE2Z6I.js} +58 -34
  38. package/dist/chunk-N5ZE2Z6I.js.map +1 -0
  39. package/dist/{chunk-2SV4SS6N.js → chunk-OQQ7CZWT.js} +12 -12
  40. package/dist/{chunk-2SV4SS6N.js.map → chunk-OQQ7CZWT.js.map} +1 -1
  41. package/dist/{chunk-JJMMT24D.mjs → chunk-OUEYZOLB.mjs} +2 -2
  42. package/dist/{chunk-XXP3TQHF.mjs → chunk-OY65RYD3.mjs} +2 -2
  43. package/dist/{chunk-MOGEGWXW.js → chunk-PMESKNKL.js} +868 -868
  44. package/dist/{chunk-MOGEGWXW.js.map → chunk-PMESKNKL.js.map} +1 -1
  45. package/dist/{chunk-B6JGKDP2.js → chunk-QGVVF77L.js} +48 -29
  46. package/dist/chunk-QGVVF77L.js.map +1 -0
  47. package/dist/{chunk-BH6JWIKI.mjs → chunk-QIEF7HIL.mjs} +2 -2
  48. package/dist/{chunk-P445QGOC.mjs → chunk-RFKSJIQB.mjs} +7 -7
  49. package/dist/{chunk-6JUCIWDC.mjs → chunk-UOTHRJD2.mjs} +2 -2
  50. package/dist/{chunk-KMW7UNL2.js → chunk-WCEYT3GG.js} +8 -8
  51. package/dist/{chunk-KMW7UNL2.js.map → chunk-WCEYT3GG.js.map} +1 -1
  52. package/dist/{chunk-MHB36MYE.js → chunk-WUNSG3IN.js} +7 -2
  53. package/dist/chunk-WUNSG3IN.js.map +1 -0
  54. package/dist/{chunk-N4RZZKL5.mjs → chunk-YKNULEHB.mjs} +12 -12
  55. package/dist/{chunk-Z4POQWFG.js → chunk-ZYSNJKOP.js} +4 -4
  56. package/dist/{chunk-Z4POQWFG.js.map → chunk-ZYSNJKOP.js.map} +1 -1
  57. package/dist/client/index.js +10 -10
  58. package/dist/client/index.mjs +9 -9
  59. package/dist/components/index.js +10 -10
  60. package/dist/components/index.mjs +9 -9
  61. package/dist/contexts/index.js +10 -10
  62. package/dist/contexts/index.mjs +9 -9
  63. package/dist/core/index.js +7 -7
  64. package/dist/core/index.mjs +6 -6
  65. package/dist/email-automations/index.js +99 -99
  66. package/dist/email-automations/index.mjs +9 -9
  67. package/dist/features/analytics/index.js +126 -126
  68. package/dist/features/analytics/index.mjs +9 -9
  69. package/dist/features/analytics/server.js +10 -10
  70. package/dist/features/analytics/server.mjs +8 -8
  71. package/dist/features/blog/index.js +156 -156
  72. package/dist/features/blog/index.mjs +9 -9
  73. package/dist/features/blog/server.js +28 -28
  74. package/dist/features/blog/server.mjs +7 -7
  75. package/dist/features/help/index.js +43 -43
  76. package/dist/features/help/index.mjs +9 -9
  77. package/dist/features/tokenusage/index.js +132 -132
  78. package/dist/features/tokenusage/index.mjs +9 -9
  79. package/dist/index.js +8 -8
  80. package/dist/index.mjs +7 -7
  81. package/dist/{lifecycle-LKGPRBS7.mjs → lifecycle-KI3PCJSE.mjs} +3 -3
  82. package/dist/lifecycle-TO65I7TO.js +23 -0
  83. package/dist/{lifecycle-4GUOTB46.js.map → lifecycle-TO65I7TO.js.map} +1 -1
  84. package/dist/local-transport-4YDJ6FQG.js +15 -0
  85. package/dist/{local-transport-7H3SPZSA.js.map → local-transport-4YDJ6FQG.js.map} +1 -1
  86. package/dist/local-transport-C7YTA4I7.mjs +15 -0
  87. package/dist/offline/index.d.mts +160 -4
  88. package/dist/offline/index.d.ts +160 -4
  89. package/dist/offline/index.js +210 -163
  90. package/dist/offline/index.js.map +1 -1
  91. package/dist/offline/index.mjs +76 -29
  92. package/dist/offline/index.mjs.map +1 -1
  93. package/dist/request-66FGJIHB.mjs +10 -0
  94. package/dist/request-6W6UGKJV.js +10 -0
  95. package/dist/{request-KTBV6HHH.js.map → request-6W6UGKJV.js.map} +1 -1
  96. package/dist/server/index.js +9 -9
  97. package/dist/server/index.mjs +8 -8
  98. package/dist/write-through-BAPS24GL.js +15 -0
  99. package/dist/{write-through-FDQ7N4YI.js.map → write-through-BAPS24GL.js.map} +1 -1
  100. package/dist/write-through-IWQKXYHE.mjs +15 -0
  101. package/package.json +1 -1
  102. package/src/offline/__tests__/generic-answers.spec.ts +146 -3
  103. package/src/offline/__tests__/local-transport.spec.ts +15 -1
  104. package/src/offline/__tests__/offline-fixtures.ts +29 -2
  105. package/src/offline/__tests__/write-through.spec.ts +27 -1
  106. package/src/offline/config.ts +9 -0
  107. package/src/offline/generic-answers.ts +44 -17
  108. package/src/offline/index.ts +2 -0
  109. package/src/offline/local-transport.ts +5 -3
  110. package/src/offline/sync/__tests__/runtime.spec.ts +30 -1
  111. package/src/offline/sync/__tests__/sync-fixtures.ts +22 -0
  112. package/src/offline/sync/__tests__/sync-root.spec.ts +184 -1
  113. package/src/offline/sync/known-roots.ts +29 -7
  114. package/src/offline/sync/runtime.ts +3 -2
  115. package/src/offline/sync/sync-root.ts +70 -19
  116. package/src/offline/types.ts +39 -1
  117. package/src/offline/write-through.ts +6 -3
  118. package/dist/JsonApiRequest-WISJZSDE.js +0 -26
  119. package/dist/chunk-27LQDGNP.mjs.map +0 -1
  120. package/dist/chunk-7JZHPMGW.mjs.map +0 -1
  121. package/dist/chunk-B6JGKDP2.js.map +0 -1
  122. package/dist/chunk-MHB36MYE.js.map +0 -1
  123. package/dist/chunk-W62MHDWM.js.map +0 -1
  124. package/dist/chunk-YRKIFYOE.mjs.map +0 -1
  125. package/dist/lifecycle-4GUOTB46.js +0 -23
  126. package/dist/local-transport-7H3SPZSA.js +0 -15
  127. package/dist/local-transport-QYFKA6AN.mjs +0 -15
  128. package/dist/request-KTBV6HHH.js +0 -10
  129. package/dist/request-SQOUNWZ4.mjs +0 -10
  130. package/dist/write-through-FDQ7N4YI.js +0 -15
  131. package/dist/write-through-R25VQMH6.mjs +0 -15
  132. /package/dist/{BlockNoteEditor-VXMDSQAA.mjs.map → BlockNoteEditor-QIVV2OB4.mjs.map} +0 -0
  133. /package/dist/{BlockNoteViewer-NBW2H6LC.mjs.map → BlockNoteViewer-HIUAJQRI.mjs.map} +0 -0
  134. /package/dist/{JsonApiRequest-F6TMJ42G.mjs.map → JsonApiRequest-IKKHWCPB.mjs.map} +0 -0
  135. /package/dist/{chunk-7DBJTNSU.mjs.map → chunk-4RPGFQBA.mjs.map} +0 -0
  136. /package/dist/{chunk-DOCIFE6A.mjs.map → chunk-AUD6ZLBB.mjs.map} +0 -0
  137. /package/dist/{chunk-47BBY5KA.mjs.map → chunk-HAW5PNJG.mjs.map} +0 -0
  138. /package/dist/{chunk-ZLTOUZN2.mjs.map → chunk-M3N7LPHX.mjs.map} +0 -0
  139. /package/dist/{chunk-DGWOVYEC.mjs.map → chunk-MQ7TXALH.mjs.map} +0 -0
  140. /package/dist/{chunk-JJMMT24D.mjs.map → chunk-OUEYZOLB.mjs.map} +0 -0
  141. /package/dist/{chunk-XXP3TQHF.mjs.map → chunk-OY65RYD3.mjs.map} +0 -0
  142. /package/dist/{chunk-BH6JWIKI.mjs.map → chunk-QIEF7HIL.mjs.map} +0 -0
  143. /package/dist/{chunk-P445QGOC.mjs.map → chunk-RFKSJIQB.mjs.map} +0 -0
  144. /package/dist/{chunk-6JUCIWDC.mjs.map → chunk-UOTHRJD2.mjs.map} +0 -0
  145. /package/dist/{chunk-N4RZZKL5.mjs.map → chunk-YKNULEHB.mjs.map} +0 -0
  146. /package/dist/{lifecycle-LKGPRBS7.mjs.map → lifecycle-KI3PCJSE.mjs.map} +0 -0
  147. /package/dist/{local-transport-QYFKA6AN.mjs.map → local-transport-C7YTA4I7.mjs.map} +0 -0
  148. /package/dist/{request-SQOUNWZ4.mjs.map → request-66FGJIHB.mjs.map} +0 -0
  149. /package/dist/{write-through-R25VQMH6.mjs.map → write-through-IWQKXYHE.mjs.map} +0 -0
@@ -81,11 +81,11 @@ import {
81
81
  useCurrentUserContext,
82
82
  useDataListRetriever,
83
83
  usePageUrlGenerator
84
- } from "../chunk-N4RZZKL5.mjs";
84
+ } from "../chunk-YKNULEHB.mjs";
85
85
  import "../chunk-VOXD3ZLY.mjs";
86
86
  import {
87
87
  getStripePublishableKey
88
- } from "../chunk-47BBY5KA.mjs";
88
+ } from "../chunk-HAW5PNJG.mjs";
89
89
  import {
90
90
  getRoleId
91
91
  } from "../chunk-PW42LRSL.mjs";
@@ -112,17 +112,17 @@ import {
112
112
  resolveChangePlanTarget,
113
113
  showToast,
114
114
  toPromotionCodeResult
115
- } from "../chunk-P445QGOC.mjs";
116
- import "../chunk-XXP3TQHF.mjs";
115
+ } from "../chunk-RFKSJIQB.mjs";
116
+ import "../chunk-OY65RYD3.mjs";
117
117
  import {
118
118
  Modules,
119
119
  useI18nLocale,
120
120
  useI18nRouter
121
- } from "../chunk-6JUCIWDC.mjs";
122
- import "../chunk-DOCIFE6A.mjs";
123
- import "../chunk-ZLTOUZN2.mjs";
124
- import "../chunk-27LQDGNP.mjs";
125
- import "../chunk-DGWOVYEC.mjs";
121
+ } from "../chunk-UOTHRJD2.mjs";
122
+ import "../chunk-AUD6ZLBB.mjs";
123
+ import "../chunk-M3N7LPHX.mjs";
124
+ import "../chunk-4ZJIUTIV.mjs";
125
+ import "../chunk-MQ7TXALH.mjs";
126
126
  import "../chunk-AUXK7QSA.mjs";
127
127
  import {
128
128
  __name
@@ -9,7 +9,7 @@ import {
9
9
  markOfflineUnavailable,
10
10
  refreshOfflineDeviceState,
11
11
  unblockOfflineStore
12
- } from "./chunk-27LQDGNP.mjs";
12
+ } from "./chunk-4ZJIUTIV.mjs";
13
13
  import {
14
14
  __name
15
15
  } from "./chunk-PAWJFY3S.mjs";
@@ -1046,4 +1046,4 @@ export {
1046
1046
  onUserSignedIn,
1047
1047
  isRootLocked
1048
1048
  };
1049
- //# sourceMappingURL=chunk-7DBJTNSU.mjs.map
1049
+ //# sourceMappingURL=chunk-4RPGFQBA.mjs.map
@@ -2,7 +2,7 @@
2
2
 
3
3
 
4
4
 
5
- var _chunkQKNGZDSQjs = require('./chunk-QKNGZDSQ.js');
5
+ var _chunkGM4VZTWLjs = require('./chunk-GM4VZTWL.js');
6
6
 
7
7
 
8
8
  var _chunk7QVYU63Ejs = require('./chunk-7QVYU63E.js');
@@ -30,11 +30,11 @@ var RehydrationFactory = class {
30
30
  _chunk7QVYU63Ejs.__name.call(void 0, this, "RehydrationFactory");
31
31
  }
32
32
  static rehydrate(classKey, data) {
33
- const factoryClass = _chunkQKNGZDSQjs.DataClassRegistry.get(classKey);
33
+ const factoryClass = _chunkGM4VZTWLjs.DataClassRegistry.get(classKey);
34
34
  return guarded(data, () => new factoryClass().rehydrate(data));
35
35
  }
36
36
  static rehydrateList(classKey, data) {
37
- const factoryClass = _chunkQKNGZDSQjs.DataClassRegistry.get(classKey);
37
+ const factoryClass = _chunkGM4VZTWLjs.DataClassRegistry.get(classKey);
38
38
  return data.map(
39
39
  (item) => guarded(item, () => new factoryClass().rehydrate(item))
40
40
  );
@@ -336,13 +336,13 @@ var ModuleRegistryClass = class {
336
336
  get(name) {
337
337
  let module = this._modules.get(name);
338
338
  if (!module) {
339
- const didBootstrap = _chunkQKNGZDSQjs.tryBootstrap.call(void 0, );
339
+ const didBootstrap = _chunkGM4VZTWLjs.tryBootstrap.call(void 0, );
340
340
  if (didBootstrap) {
341
341
  module = this._modules.get(name);
342
342
  }
343
343
  }
344
344
  if (!module) {
345
- const hint = _chunkQKNGZDSQjs.hasBootstrapper.call(void 0, ) ? "Bootstrap was called but module still not found. Check module registration." : "No bootstrapper registered. Ensure configureJsonApi({ bootstrapper }) is called before accessing modules.";
345
+ const hint = _chunkGM4VZTWLjs.hasBootstrapper.call(void 0, ) ? "Bootstrap was called but module still not found. Check module registration." : "No bootstrapper registered. Ensure configureJsonApi({ bootstrapper }) is called before accessing modules.";
346
346
  throw new Error(`Module "${String(name)}" not registered. ${hint}`);
347
347
  }
348
348
  return module;
@@ -352,12 +352,12 @@ var ModuleRegistryClass = class {
352
352
  * can check for an opt-in module the app may not have registered.
353
353
  */
354
354
  has(name) {
355
- if (this._modules.size === 0) _chunkQKNGZDSQjs.tryBootstrap.call(void 0, );
355
+ if (this._modules.size === 0) _chunkGM4VZTWLjs.tryBootstrap.call(void 0, );
356
356
  return this._modules.has(name);
357
357
  }
358
358
  findByName(moduleName) {
359
359
  if (this._modules.size === 0) {
360
- _chunkQKNGZDSQjs.tryBootstrap.call(void 0, );
360
+ _chunkGM4VZTWLjs.tryBootstrap.call(void 0, );
361
361
  }
362
362
  for (const module of this._modules.values()) {
363
363
  if (module.name === moduleName) {
@@ -368,7 +368,7 @@ var ModuleRegistryClass = class {
368
368
  }
369
369
  getAllPageUrls() {
370
370
  if (this._modules.size === 0) {
371
- _chunkQKNGZDSQjs.tryBootstrap.call(void 0, );
371
+ _chunkGM4VZTWLjs.tryBootstrap.call(void 0, );
372
372
  }
373
373
  const seen = /* @__PURE__ */ new Set();
374
374
  const result = [];
@@ -385,7 +385,7 @@ var ModuleRegistryClass = class {
385
385
  findByModelName(modelName) {
386
386
  let module = this._modules.get(modelName);
387
387
  if (!module) {
388
- const didBootstrap = _chunkQKNGZDSQjs.tryBootstrap.call(void 0, );
388
+ const didBootstrap = _chunkGM4VZTWLjs.tryBootstrap.call(void 0, );
389
389
  if (didBootstrap) {
390
390
  module = this._modules.get(modelName);
391
391
  }
@@ -407,7 +407,7 @@ var ModuleRegistryClass = class {
407
407
  }
408
408
  getAll() {
409
409
  if (this._modules.size === 0) {
410
- _chunkQKNGZDSQjs.tryBootstrap.call(void 0, );
410
+ _chunkGM4VZTWLjs.tryBootstrap.call(void 0, );
411
411
  }
412
412
  return Array.from(this._modules.values());
413
413
  }
@@ -567,4 +567,4 @@ var RootSync = (_class2 = class extends AbstractApiData {constructor(...args) {
567
567
 
568
568
 
569
569
  exports.RehydrationFactory = RehydrationFactory; exports.AbstractApiData = AbstractApiData; exports.configureI18n = configureI18n; exports.useI18nRouter = useI18nRouter; exports.useI18nTranslations = useI18nTranslations; exports.getI18nLink = getI18nLink; exports.useI18nLocale = useI18nLocale; exports.getI18nServerLocale = getI18nServerLocale; exports.useI18nDateFnsLocale = useI18nDateFnsLocale; exports.getI18nSupportedLocales = getI18nSupportedLocales; exports.getI18nDefaultLocale = getI18nDefaultLocale; exports.ModuleRegistry = ModuleRegistry; exports.Modules = Modules; exports.EndpointCreator = EndpointCreator; exports.ROOT_SYNC_ENDPOINT = ROOT_SYNC_ENDPOINT; exports.RootSync = RootSync;
570
- //# sourceMappingURL=chunk-BZ5J2FIV.js.map
570
+ //# sourceMappingURL=chunk-4XLDBOSE.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["/home/runner/work/nextjs-jsonapi/nextjs-jsonapi/dist/chunk-BZ5J2FIV.js","../src/core/factories/RehydrationFactory.ts","../src/core/abstracts/AbstractApiData.ts","../src/i18n/config.ts","../src/core/registry/ModuleRegistry.ts","../src/core/endpoint/EndpointCreator.ts","../src/offline/sync/models/RootSync.ts"],"names":["includedData","includedItem","module","entity"],"mappings":"AAAA;AACE;AACA;AACA;AACF,sDAA4B;AAC5B;AACE;AACF,sDAA4B;AAC5B;AACA;ACCA,IAAM,WAAA,kBAAa,IAAI,GAAA,CAAY,CAAA;AAEnC,IAAM,MAAA,kBAAQ,qCAAA,CAAC,IAAA,EAAA,GAA2D;AACxE,EAAA,MAAM,SAAA,kBAAW,IAAA,6BAAM,SAAA;AACvB,EAAA,uBAAO,QAAA,6BAAU,OAAA,mBAAQ,QAAA,6BAAU,KAAA,EAAK,CAAA,EAAA;AAF5B;AAK2D;AACjD,EAAA;AACD,EAAA;AACW,EAAA;AACd,EAAA;AACd,EAAA;AACS,IAAA;AACX,EAAA;AACqB,IAAA;AACvB,EAAA;AACF;AAVS;AAYuB;AAAA,EAAA;AAAA,IAAA;AAAA,EAAA;AAIzB,EAAA;AACoC,IAAA;AAER,IAAA;AACjC,EAAA;AAKO,EAAA;AACkC,IAAA;AAE3B,IAAA;AACc,MAAA;AAC1B,IAAA;AACF,EAAA;AACF;ADP2C;AACA;AEtCrB;AAA4C,EAAA;AAAA,IAAA;AAAA,EAAA;AACrB,EAAA;AAElB,EAAA;AACqC,IAAA;AAErC,IAAA;AAGzB,EAAA;AAEU,EAAA;AACA,EAAA;AAEA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AAEA,EAAA;AAES,EAAA;AACgB,IAAA;AACrB,IAAA;AACd,EAAA;AAEiB,EAAA;AACgB,IAAA;AACnB,IAAA;AACd,EAAA;AAE+B,EAAA;AACjB,IAAA;AACd,EAAA;AAEsB,EAAA;AACM,IAAA;AAC5B,EAAA;AAEsB,EAAA;AACM,IAAA;AAC5B,EAAA;AAEsB,EAAA;AACM,IAAA;AAC5B,EAAA;AAEmB,EAAA;AACL,IAAA;AACd,EAAA;AAEyD,EAAA;AAAC,EAAA;AAEpB,EAAA;AACpB,IAAA;AAClB,EAAA;AAEgC,EAAA;AACd,IAAA;AAClB,EAAA;AAMuB,EAAA;AAGd,IAAA;AAKE,MAAA;AACT,IAAA;AAE+B,IAAA;AACM,MAAA;AACP,QAAA;AACY,UAAA;AACtC,QAAA;AAEgC,QAAA;AAEN,QAAA;AACfA,UAAAA;AACM,UAAA;AAChB,QAAA;AACF,MAAA;AAE+C,MAAA;AAClD,IAAA;AAEmC,IAAA;AAElB,MAAA;AAEjB,IAAA;AAEuC,IAAA;AAEH,MAAA;AAEjB,QAAA;AAEjB,MAAA;AACgC,MAAA;AACJ,QAAA;AACf,UAAA;AACM,UAAA;AAChB,QAAA;AACH,MAAA;AACF,IAAA;AAEuC,IAAA;AAEH,IAAA;AACzB,MAAA;AACM,MAAA;AAChB,IAAA;AACH,EAAA;AAAA;AAAA;AAAA;AAAA;AAQE,EAAA;AAIoC,IAAA;AAC3B,MAAA;AACT,IAAA;AAE6B,IAAA;AAGR,IAAA;AACe,IAAA;AACJ,MAAA;AAChC,IAAA;AAE4B,IAAA;AAEL,MAAA;AACO,MAAA;AACA,QAAA;AACP,QAAA;AAGaC,QAAAA;AACnB,QAAA;AAEN,QAAA;AACwBC,UAAAA;AAClBD,YAAAA;AACM,YAAA;AAChB,UAAA;AACH,QAAA;AACF,MAAA;AACoC,MAAA;AACtC,IAAA;AAGmC,IAAA;AACT,IAAA;AAEM,IAAA;AACZ,IAAA;AAEgB,IAAA;AACzB,MAAA;AACM,MAAA;AAChB,IAAA;AACH,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAiBE,EAAA;AAKO,IAAA;AAKE,MAAA;AACT,IAAA;AAEsC,IAAA;AAGD,IAAA;AACR,MAAA;AAEU,MAAA;AACT,QAAA;AAEP,QAAA;AAEe,QAAA;AACvBD,UAAAA;AACM,UAAA;AAChB,QAAA;AAGc,QAAA;AACcG,UAAAA;AAC7B,QAAA;AAE2B,QAAA;AAC7B,MAAA;AAEO,MAAA;AACT,IAAA;AAGmC,IAAA;AACS,MAAA;AAC5C,IAAA;AAEmB,IAAA;AAEe,MAAA;AACI,QAAA;AACP,UAAA;AAC3B,QAAA;AACkB,QAAA;AACD,UAAA;AACJ,YAAA;AACM,YAAA;AAChB,UAAA;AAG6B,UAAA;AACR,UAAA;AACOA,YAAAA;AAC7B,UAAA;AACOA,UAAAA;AACT,QAAA;AACF,MAAA;AACO,MAAA;AACT,IAAA;AAEkC,IAAA;AACvB,MAAA;AACM,MAAA;AAChB,IAAA;AAGqC,IAAA;AAChB,IAAA;AACe,MAAA;AACrC,IAAA;AAEO,IAAA;AACT,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAO2E,EAAA;AACvC,IAAA;AACK,MAAA;AACvC,IAAA;AACF,EAAA;AAE0C,EAAA;AACjC,IAAA;AACS,MAAA;AACe,MAAA;AAC/B,IAAA;AACF,EAAA;AAEoD,EAAA;AAC7B,IAAA;AACC,IAAA;AAEK,IAAA;AACF,IAAA;AACa,IAAA;AACA,IAAA;AAEJ,IAAA;AAE3B,IAAA;AACT,EAAA;AACF;AFrD2C;AACA;AGxNV;AAGuB;AAC5C,EAAA;AACZ;AAFgB;AAK4B;AACjB,EAAA;AACP,IAAA;AAClB,EAAA;AACyB,EAAA;AAC3B;AALgB;AAO+F;AAC9E,EAAA;AAEL,IAAA;AAC1B,EAAA;AACwC,EAAA;AAC1C;AANgB;AAQ6B;AACvB,EAAA;AACF,IAAA;AAClB,EAAA;AACe,EAAA;AACjB;AALgB;AAOwB;AACd,EAAA;AACG,IAAA;AAC3B,EAAA;AAEO,EAAA;AACT;AANgB;AAS6C;AAClC,EAAA;AACP,IAAA;AAClB,EAAA;AACyB,EAAA;AAC3B;AALsB;AAOsB;AACX,EAAA;AACG,IAAA;AAClC,EAAA;AAEO,EAAA;AACT;AANgB;AASoC;AACT,EAAA;AACxB,IAAA;AACjB,EAAA;AACY,EAAA;AACd;AALgB;AAQ+B;AACX,EAAA;AACpC;AAFgB;AHoN2B;AACA;AIrMhB;AAGP;AAKW;AACF,EAAA;AAC7B;AAE0B;AAAA,EAAA;AAAA,IAAA;AAAA,EAAA;AACyC,EAAA;AACjC,IAAA;AAChC,EAAA;AAE+E,EAAA;AAC/C,IAAA;AAChC,EAAA;AAEsE,EAAA;AACvB,IAAA;AAGhC,IAAA;AACuB,MAAA;AAChB,MAAA;AAEyB,QAAA;AAC3C,MAAA;AACF,IAAA;AAEa,IAAA;AAGP,MAAA;AAE8B,MAAA;AACpC,IAAA;AAEO,IAAA;AACT,EAAA;AAAA;AAAA;AAAA;AAAA;AAM2B,EAAA;AAGK,IAAA;AACD,IAAA;AAC/B,EAAA;AAEsD,EAAA;AAEtB,IAAA;AACf,MAAA;AACf,IAAA;AAGmC,IAAA;AAC0B,MAAA;AAClD,QAAA;AACT,MAAA;AACF,IAAA;AACqC,IAAA;AACvC,EAAA;AAEiD,EAAA;AACjB,IAAA;AACf,MAAA;AACf,IAAA;AAE6B,IAAA;AACmB,IAAA;AACf,IAAA;AACrB,MAAA;AAC0B,MAAA;AAChB,QAAA;AACiB,QAAA;AACL,QAAA;AAChC,MAAA;AACF,IAAA;AACoC,IAAA;AACtC,EAAA;AAE0D,EAAA;AAEzB,IAAA;AAGlB,IAAA;AACuB,MAAA;AAChB,MAAA;AACW,QAAA;AAC7B,MAAA;AACF,IAAA;AAEa,IAAA;AACK,MAAA;AAClB,IAAA;AACO,IAAA;AACT,EAAA;AAEwD,EAAA;AACX,IAAA;AAER,IAAA;AACvB,MAAA;AACiB,MAAA;AACV,QAAA;AACjB,MAAA;AACF,IAAA;AAEO,IAAA;AACT,EAAA;AAEwC,EAAA;AACR,IAAA;AACf,MAAA;AACf,IAAA;AACuC,IAAA;AACzC,EAAA;AACF;AAEkC;AAGwB;AACnC,EAAA;AACQ,IAAA;AACe,MAAA;AAC1C,IAAA;AACgC,IAAA;AACU,MAAA;AAC1C,IAAA;AAC8B,IAAA;AACe,MAAA;AAC7C,IAAA;AACyD,IAAA;AAC3D,EAAA;AACD;AJoK0C;AACA;AKnad;AAAA,EAAA;AAAA,IAAA;AAAA,EAAA;AACnB,EAAA;AAQL,EAAA;AACgB,IAAA;AACE,MAAA;AACN,MAAA;AACW,MAAA;AACN,MAAA;AACS,MAAA;AAC3B,IAAA;AACF,EAAA;AAEuE,EAAA;AAC3C,IAAA;AACnB,IAAA;AACT,EAAA;AAEmC,EAAA;AACb,IAAA;AACb,IAAA;AACT,EAAA;AAE4E,EAAA;AAC3C,IAAA;AACxB,IAAA;AACT,EAAA;AAEwC,EAAA;AACb,IAAA;AAClB,IAAA;AACT,EAAA;AAE8D,EAAA;AAC1B,IAAA;AACpC,EAAA;AAE2E,EAAA;AACnC,IAAA;AACC,IAAA;AAChC,IAAA;AACT,EAAA;AAEuC,EAAA;AACF,IAAA;AAC5B,IAAA;AACT,EAAA;AAEqD,EAAA;AAChB,IAAA;AAEH,IAAA;AACM,MAAA;AACF,MAAA;AACnC,IAAA;AAEM,IAAA;AACT,EAAA;AAEmB,EAAA;AACM,IAAA;AACc,IAAA;AACD,MAAA;AACpC,IAAA;AAEe,IAAA;AAES,IAAA;AAEe,IAAA;AACL,IAAA;AAElB,MAAA;AAIhB,IAAA;AAC4B,IAAA;AACU,IAAA;AAE/B,IAAA;AACT,EAAA;AACF;AL8Y2C;AACA;AMzeT;AAGJ;AAA6C,EAAA;AAAA,IAAA;AAAA,EAAA;AACjE,EAAA;AACmB,iBAAA;AACnB,EAAA;AACA,EAAA;AACA,EAAA;AAEe,EAAA;AACkB,IAAA;AAC3B,IAAA;AACd,EAAA;AAEsB,EAAA;AACR,IAAA;AACd,EAAA;AAEmC,EAAA;AACrB,IAAA;AACd,EAAA;AAE+B,EAAA;AACJ,IAAA;AAC3B,EAAA;AAE4B,EAAA;AACH,IAAA;AACzB,EAAA;AAEoD,EAAA;AAC9B,IAAA;AAEY,IAAA;AACF,IAAA;AACI,IAAA;AACJ,IAAA;AACS,IAAA;AACzB,MAAA;AACF,MAAA;AACyB,MAAA;AACnC,IAAA;AACqC,IAAA;AACtB,MAAA;AACF,MAAA;AACA,MAAA;AACF,MAAA;AACA,MAAA;AACW,MAAA;AACtB,IAAA;AAEK,IAAA;AACT,EAAA;AAEgC,EAAA;AACd,IAAA;AAClB,EAAA;AACF;ANme2C;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA","file":"/home/runner/work/nextjs-jsonapi/nextjs-jsonapi/dist/chunk-BZ5J2FIV.js","sourcesContent":[null,"import { ApiDataInterface } from \"../interfaces/ApiDataInterface\";\nimport { ApiRequestDataTypeInterface } from \"../interfaces/ApiRequestDataTypeInterface\";\nimport { JsonApiHydratedDataInterface } from \"../interfaces/JsonApiHydratedDataInterface\";\nimport { DataClassRegistry } from \"../registry/DataClassRegistry\";\n\n/**\n * The resources being rehydrated right now, along the current chain of relationships. A resource\n * met again inside its own chain (A's relationship leads to B, B's back to A) is a circle in the\n * `included` data: following it would recurse until the stack overflows, so it is skipped there.\n */\nconst inProgress = new Set<string>();\n\nconst keyOf = (data: JsonApiHydratedDataInterface): string | undefined => {\n const resource = data?.jsonApi;\n return resource?.type && resource?.id ? `${resource.type}:${resource.id}` : undefined;\n};\n\nfunction guarded<T>(data: JsonApiHydratedDataInterface, run: () => T): T {\n const key = keyOf(data);\n if (!key) return run();\n if (inProgress.has(key)) return undefined as T;\n inProgress.add(key);\n try {\n return run();\n } finally {\n inProgress.delete(key);\n }\n}\n\nexport class RehydrationFactory {\n public static rehydrate<T extends ApiDataInterface>(\n classKey: ApiRequestDataTypeInterface,\n data: JsonApiHydratedDataInterface,\n ): T {\n const factoryClass = DataClassRegistry.get(classKey);\n\n return guarded(data, () => new factoryClass().rehydrate(data) as T);\n }\n\n public static rehydrateList<T extends ApiDataInterface>(\n classKey: ApiRequestDataTypeInterface,\n data: JsonApiHydratedDataInterface[],\n ): T[] {\n const factoryClass = DataClassRegistry.get(classKey);\n\n return data.map((item: JsonApiHydratedDataInterface) =>\n guarded(item, () => new factoryClass().rehydrate(item) as T),\n );\n }\n}\n","import { RehydrationFactory } from \"../factories/RehydrationFactory\";\nimport { ApiDataInterface } from \"../interfaces/ApiDataInterface\";\nimport { ApiRequestDataTypeInterface } from \"../interfaces/ApiRequestDataTypeInterface\";\nimport { JsonApiHydratedDataInterface } from \"../interfaces/JsonApiHydratedDataInterface\";\n\nexport abstract class AbstractApiData implements ApiDataInterface {\n static identifierFields: string[] = [\"name\"];\n\n get identifier(): string {\n const fields = (this.constructor as typeof AbstractApiData).identifierFields;\n return fields\n .map((field) => this._jsonApi?.attributes?.[field])\n .filter((v) => v != null && v !== \"\")\n .join(\" \");\n }\n\n protected _jsonApi?: any;\n protected _included?: any[];\n\n protected _id?: string;\n protected _type?: string;\n protected _createdAt?: Date;\n protected _updatedAt?: Date;\n\n protected _self?: string;\n\n get type(): string {\n if (!this._type) throw new Error(\"Type is not set.\");\n return this._type;\n }\n\n get id(): string {\n if (!this._id) throw new Error(\"Id is not set.\");\n return this._id;\n }\n\n get self(): string | undefined {\n return this._self;\n }\n\n get createdAt(): Date {\n return this._createdAt ?? new Date();\n }\n\n get updatedAt(): Date {\n return this._updatedAt ?? new Date();\n }\n\n get included(): any[] {\n return this._included ?? [];\n }\n\n get jsonApi(): any {\n return this._jsonApi;\n }\n\n ingestJsonApi(_data: JsonApiHydratedDataInterface): void {}\n\n generateApiUrl(_params?: any): string {\n throw new Error(\"Method not implemented.\");\n }\n\n createJsonApi(_data?: any): any {\n throw new Error(\"Method not implemented.\");\n }\n\n protected _readIncluded<T extends ApiDataInterface>(\n data: JsonApiHydratedDataInterface,\n type: string,\n dataType: ApiRequestDataTypeInterface,\n ): T | T[] | undefined {\n if (\n data.included === undefined ||\n data.included.length === 0 ||\n data.jsonApi.relationships === undefined ||\n data.jsonApi.relationships[type] === undefined ||\n data.jsonApi.relationships[type].data === undefined\n ) {\n return undefined;\n }\n\n if (Array.isArray(data.jsonApi.relationships[type].data)) {\n const response: T[] = data.jsonApi.relationships[type].data.map((jsonApiData: any) => {\n const includedData = data.included.find(\n (includedData: any) => includedData.id === jsonApiData.id && includedData.type === jsonApiData.type,\n );\n\n if (includedData === undefined) return undefined;\n\n return RehydrationFactory.rehydrate(dataType, {\n jsonApi: includedData,\n included: data.included,\n }) as T;\n });\n\n return response.filter((item: T | undefined) => item !== undefined) as T[];\n }\n\n const includedData = data.included.find(\n (includedData: any) =>\n includedData.id === data.jsonApi.relationships[type].data.id &&\n includedData.type === data.jsonApi.relationships[type].data.type,\n );\n\n if (includedData === undefined && data.allData !== undefined) {\n // Try to find in allData as a fallback\n const fallbackData = data.allData.find(\n (includedData: any) =>\n includedData.id === data.jsonApi.relationships[type].data.id &&\n includedData.type === data.jsonApi.relationships[type].data.type,\n );\n if (fallbackData !== undefined) {\n return RehydrationFactory.rehydrate(dataType, {\n jsonApi: fallbackData,\n included: data.included,\n }) as T;\n }\n }\n\n if (includedData === undefined) return undefined;\n\n return RehydrationFactory.rehydrate(dataType, {\n jsonApi: includedData,\n included: data.included,\n }) as T;\n }\n\n /**\n * Read included relationships with polymorphic type resolution.\n * Determines the correct model class based on the JSON:API type in included data.\n */\n protected _readIncludedPolymorphic<T extends ApiDataInterface>(\n data: JsonApiHydratedDataInterface,\n relationshipKey: string,\n candidateModules: ApiRequestDataTypeInterface[],\n ): T | T[] | undefined {\n // Validate relationship exists\n if (!data.included?.length || !data.jsonApi.relationships?.[relationshipKey]?.data) {\n return undefined;\n }\n\n const relData = data.jsonApi.relationships[relationshipKey].data;\n\n // Build lookup map: JSON:API type -> module\n const typeToModule = new Map<string, ApiRequestDataTypeInterface>();\n for (const mod of candidateModules) {\n typeToModule.set(mod.name, mod);\n }\n\n if (Array.isArray(relData)) {\n // Many relationship\n const result: T[] = [];\n for (const item of relData) {\n const includedItem = data.included.find((inc: any) => inc.id === item.id && inc.type === item.type);\n if (!includedItem) continue;\n\n // Resolve module by JSON:API type\n const module = typeToModule.get(includedItem.type);\n if (!module) continue;\n\n result.push(\n RehydrationFactory.rehydrate(module, {\n jsonApi: includedItem,\n included: data.included,\n }) as T,\n );\n }\n return result.length > 0 ? result : undefined;\n }\n\n // Single relationship\n const includedItem = data.included.find((inc: any) => inc.id === relData.id && inc.type === relData.type);\n if (!includedItem) return undefined;\n\n const module = typeToModule.get(includedItem.type);\n if (!module) return undefined;\n\n return RehydrationFactory.rehydrate(module, {\n jsonApi: includedItem,\n included: data.included,\n }) as T;\n }\n\n /**\n * Read included relationship data and augment with relationship meta properties.\n * Handles both single relationships (one-to-one) and array relationships (one-to-many).\n *\n * For single relationships: meta is read from `relationships[type].meta`\n * For array relationships: per-item meta is read from `relationships[type].data[].meta`\n *\n * @param data - Hydrated JSON:API data\n * @param type - Relationship type key (e.g., \"guide\", \"persons\")\n * @param dataType - Module reference for rehydration\n * @returns Related object(s) augmented with meta properties, or undefined\n */\n protected _readIncludedWithMeta<T extends ApiDataInterface, M extends Record<string, any>>(\n data: JsonApiHydratedDataInterface,\n type: string,\n dataType: ApiRequestDataTypeInterface,\n ): (T & M) | (T & M)[] | undefined {\n // Check if relationship exists\n if (\n data.included === undefined ||\n data.included.length === 0 ||\n data.jsonApi.relationships === undefined ||\n data.jsonApi.relationships[type] === undefined ||\n data.jsonApi.relationships[type].data === undefined\n ) {\n return undefined;\n }\n\n const relationshipData = data.jsonApi.relationships[type].data;\n\n // Handle array relationships with per-item meta\n if (Array.isArray(relationshipData)) {\n const result: (T & M)[] = [];\n\n for (const item of relationshipData) {\n const includedData = data.included.find((inc: any) => inc.id === item.id && inc.type === item.type);\n\n if (!includedData) continue;\n\n const entity = RehydrationFactory.rehydrate(dataType, {\n jsonApi: includedData,\n included: data.included,\n }) as T;\n\n // Merge per-item meta from relationships[type].data[].meta\n if (item.meta) {\n AbstractApiData._mergeMeta(entity, item.meta);\n }\n\n result.push(entity as T & M);\n }\n\n return result;\n }\n\n // Handle single relationship\n const includedData = data.included.find(\n (inc: any) => inc.id === relationshipData.id && inc.type === relationshipData.type,\n );\n\n if (!includedData) {\n // Try to find in allData as a fallback\n if (data.allData !== undefined) {\n const fallbackData = data.allData.find(\n (inc: any) => inc.id === relationshipData.id && inc.type === relationshipData.type,\n );\n if (fallbackData) {\n const entity = RehydrationFactory.rehydrate(dataType, {\n jsonApi: fallbackData,\n included: data.included,\n }) as T;\n\n // Merge relationship-level meta for single relationships\n const relationshipMeta = data.jsonApi.relationships[type].meta;\n if (relationshipMeta) {\n AbstractApiData._mergeMeta(entity, relationshipMeta);\n }\n return entity as T & M;\n }\n }\n return undefined;\n }\n\n const entity = RehydrationFactory.rehydrate(dataType, {\n jsonApi: includedData,\n included: data.included,\n }) as T;\n\n // Merge relationship-level meta for single relationships\n const relationshipMeta = data.jsonApi.relationships[type].meta;\n if (relationshipMeta) {\n AbstractApiData._mergeMeta(entity, relationshipMeta);\n }\n\n return entity as T & M;\n }\n\n /**\n * Copies relationship meta onto a rehydrated entity as own data properties. Object.assign throws\n * when the model declares a getter-only accessor of the same name (an app's `Chunk` with\n * `get relevance()`); an own property shadows that getter, so the model reads the meta value.\n */\n private static _mergeMeta(entity: object, meta: Record<string, any>): void {\n for (const [key, value] of Object.entries(meta)) {\n Object.defineProperty(entity, key, { value, writable: true, enumerable: true, configurable: true });\n }\n }\n\n dehydrate(): JsonApiHydratedDataInterface {\n return {\n jsonApi: this._jsonApi,\n included: this._included ?? [],\n };\n }\n\n rehydrate(data: JsonApiHydratedDataInterface): this {\n this._jsonApi = data.jsonApi;\n this._included = data.included;\n\n this._type = this._jsonApi.type;\n this._id = this._jsonApi.id;\n this._createdAt = this._jsonApi.meta?.createdAt !== undefined ? new Date(this._jsonApi.meta.createdAt) : undefined;\n this._updatedAt = this._jsonApi.meta?.updatedAt !== undefined ? new Date(this._jsonApi.meta.updatedAt) : undefined;\n\n this._self = this._jsonApi.links?.self ?? undefined;\n\n return this;\n }\n}\n","import { ComponentType } from \"react\";\n\n// Types for injected hooks\nexport interface I18nRouter {\n push: (href: string) => void;\n replace: (href: string) => void;\n back: () => void;\n forward: () => void;\n refresh: () => void;\n prefetch: (href: string) => void;\n}\n\nexport type UseRouterHook = () => I18nRouter;\nexport type UseTranslationsHook = (namespace?: string) => (key: string, values?: Record<string, any>) => string;\nexport type UseLocaleHook = () => string;\nexport type GetLocaleFunction = () => Promise<string>;\n\nexport type UseDateFnsLocaleHook = () => any; // date-fns Locale type\nexport type LinkComponent = ComponentType<{ href: string; children: React.ReactNode; [key: string]: any }>;\n\nexport interface I18nConfig {\n useRouter: UseRouterHook;\n useTranslations: UseTranslationsHook;\n useLocale?: UseLocaleHook;\n useDateFnsLocale?: UseDateFnsLocaleHook;\n Link: LinkComponent;\n usePathname: () => string;\n /**\n * Server-side locale for API requests (pass next-intl's `getLocale` from `next-intl/server`).\n *\n * The library never imports next-intl itself: instrumentation loads the library, and\n * next-intl's `getLocale` pulls in the app's `i18n/request.ts`, which reads\n * `next/root-params` — a module only allowed inside the app directory.\n */\n getLocale: GetLocaleFunction;\n /**\n * Locales the app supports. The first entry is the fallback.\n * Defaults to `[\"en\"]` when omitted.\n */\n supportedLocales?: string[];\n}\n\n// Private storage\nlet _config: I18nConfig | null = null;\n\n// Configuration function (called by app at startup)\nexport function configureI18n(config: I18nConfig): void {\n _config = config;\n}\n\n// Hooks for library components to use\nexport function useI18nRouter(): I18nRouter {\n if (!_config?.useRouter) {\n throw new Error(\"i18n not configured. Call configureI18n() at app startup.\");\n }\n return _config.useRouter();\n}\n\nexport function useI18nTranslations(namespace?: string): (key: string, values?: Record<string, any>) => string {\n if (!_config?.useTranslations) {\n // Fallback: return key as-is (safe for server/client)\n return (key: string) => key;\n }\n return _config.useTranslations(namespace);\n}\n\nexport function getI18nLink(): LinkComponent {\n if (!_config?.Link) {\n throw new Error(\"i18n not configured. Call configureI18n() at app startup.\");\n }\n return _config.Link;\n}\n\nexport function useI18nLocale(): string {\n if (_config?.useLocale) {\n return _config.useLocale();\n }\n // Fallback to English (safe for server/client)\n return \"en\";\n}\n\n/** The server-side locale from the app's `getLocale`. Throws when `configureI18n` has not run. */\nexport async function getI18nServerLocale(): Promise<string> {\n if (!_config?.getLocale) {\n throw new Error(\"i18n not configured. Call configureI18n() with getLocale at app startup.\");\n }\n return _config.getLocale();\n}\n\nexport function useI18nDateFnsLocale(): any {\n if (_config?.useDateFnsLocale) {\n return _config.useDateFnsLocale();\n }\n // Fallback to undefined (Calendar will use default)\n return undefined;\n}\n\n/** The app's supported locales. Defaults to `[\"en\"]` when not configured. */\nexport function getI18nSupportedLocales(): string[] {\n if (_config?.supportedLocales && _config.supportedLocales.length > 0) {\n return _config.supportedLocales;\n }\n return [\"en\"];\n}\n\n/** The app's default locale: the first supported locale (`\"en\"` when not configured). */\nexport function getI18nDefaultLocale(): string {\n return getI18nSupportedLocales()[0];\n}\n","import { ModuleWithPermissions } from \"../../permissions/types\";\nimport { ApiRequestDataTypeInterface } from \"../interfaces/ApiRequestDataTypeInterface\";\nimport { hasBootstrapper, tryBootstrap } from \"./bootstrapStore\";\n\n// Foundation module types - defined by LIBRARY\nexport interface FoundationModuleDefinitions {\n S3: ModuleWithPermissions;\n Auth: ModuleWithPermissions;\n User: ModuleWithPermissions;\n Author: ModuleWithPermissions;\n Company: ModuleWithPermissions;\n Role: ModuleWithPermissions;\n Notification: ModuleWithPermissions;\n Push: ModuleWithPermissions;\n Feature: ModuleWithPermissions;\n Module: ModuleWithPermissions;\n Content: ModuleWithPermissions;\n HowTo: ModuleWithPermissions;\n HandbookPage: ModuleWithPermissions;\n HandbookSection: ModuleWithPermissions;\n HandbookThread: ModuleWithPermissions;\n HandbookThreadMessage: ModuleWithPermissions;\n Assistant: ModuleWithPermissions;\n AssistantMessage: ModuleWithPermissions;\n AssistantAction: ModuleWithPermissions;\n Chunk: ModuleWithPermissions;\n // Billing modules - READ: all users, UPDATE: CompanyAdministrator, ADMIN: Administrator\n Billing: ModuleWithPermissions;\n StripeCustomer: ModuleWithPermissions;\n StripePaymentMethod: ModuleWithPermissions;\n StripeSubscription: ModuleWithPermissions;\n StripeInvoice: ModuleWithPermissions;\n StripeProduct: ModuleWithPermissions;\n StripePrice: ModuleWithPermissions;\n StripeUsage: ModuleWithPermissions;\n StripePromotionCode: ModuleWithPermissions;\n StripeCoupon: ModuleWithPermissions;\n StripeCouponCode: ModuleWithPermissions;\n StripeCouponOffer: ModuleWithPermissions;\n // AI connection administration\n AiConnection: ModuleWithPermissions;\n // OAuth modules\n OAuth: ModuleWithPermissions;\n // Waitlist modules\n Waitlist: ModuleWithPermissions;\n WaitlistStats: ModuleWithPermissions;\n // Email automation modules\n EmailAutomation: ModuleWithPermissions;\n EmailAutomationStep: ModuleWithPermissions;\n EmailAutomationEnrollment: ModuleWithPermissions;\n EmailAutomationTrigger: ModuleWithPermissions;\n // Email blast modules\n EmailBlast: ModuleWithPermissions;\n EmailBlastDelivery: ModuleWithPermissions;\n EmailBlastAudience: ModuleWithPermissions;\n // Blog modules\n BlogPost: ModuleWithPermissions;\n BlogPostTranslation: ModuleWithPermissions;\n BlogCategory: ModuleWithPermissions;\n BlogCategoryTranslation: ModuleWithPermissions;\n BlogSettings: ModuleWithPermissions;\n // Referral modules\n Referral: ModuleWithPermissions;\n ReferralStats: ModuleWithPermissions;\n // Referral link visits and the administrative referral report (opt-in: registered by apps that spread referralAdminModules)\n ReferralVisit: ModuleWithPermissions;\n ReferralAdminSummary: ModuleWithPermissions;\n ReferralAdminReferrer: ModuleWithPermissions;\n ReferralAdminReferral: ModuleWithPermissions;\n // Two-factor authentication modules\n TotpAuthenticator: ModuleWithPermissions;\n TotpSetup: ModuleWithPermissions;\n TotpVerify: ModuleWithPermissions;\n TotpVerifyLogin: ModuleWithPermissions;\n Passkey: ModuleWithPermissions;\n PasskeyRegistrationOptions: ModuleWithPermissions;\n PasskeyRegistrationVerify: ModuleWithPermissions;\n PasskeyRename: ModuleWithPermissions;\n PasskeyVerifyLogin: ModuleWithPermissions;\n PasskeyAuthenticationOptions: ModuleWithPermissions;\n TwoFactorEnable: ModuleWithPermissions;\n TwoFactorChallenge: ModuleWithPermissions;\n TwoFactorStatus: ModuleWithPermissions;\n BackupCodeVerify: ModuleWithPermissions;\n // OAuth sign-up awaiting consent\n PendingRegistration: ModuleWithPermissions;\n // RBAC modules\n PermissionMapping: ModuleWithPermissions;\n ModulePaths: ModuleWithPermissions;\n RbacMatrix: ModuleWithPermissions;\n // Audit modules\n AuditLog: ModuleWithPermissions;\n // Administrative token-usage reporting modules\n TokenUsageAdminSummary: ModuleWithPermissions;\n TokenUsageAdminTimeline: ModuleWithPermissions;\n TokenUsageAdminBreakdown: ModuleWithPermissions;\n // Self-service token-usage reporting modules\n TokenUsageReportSummary: ModuleWithPermissions;\n TokenUsageReportTimeline: ModuleWithPermissions;\n TokenUsageReportBreakdown: ModuleWithPermissions;\n // First-party web analytics modules (tracker + administrative dashboard)\n AnalyticsEvent: ModuleWithPermissions;\n AnalyticsSummary: ModuleWithPermissions;\n AnalyticsTimeline: ModuleWithPermissions;\n AnalyticsBreakdown: ModuleWithPermissions;\n AnalyticsSession: ModuleWithPermissions;\n AnalyticsPageView: ModuleWithPermissions;\n // Account deletion (opt-in: registered only by apps that enable it)\n AccountDeletion: ModuleWithPermissions;\n // Offline mode (opt-in: registered by apps that spread offlineModules)\n OfflineChangeSet: ModuleWithPermissions;\n RootSync: ModuleWithPermissions;\n}\n\n// App-specific modules - apps will augment this interface ONLY\n\nexport interface AppModuleDefinitions {}\n\n// Combined type for full autocompletion\nexport type ModuleDefinitions = FoundationModuleDefinitions & AppModuleDefinitions;\n\n// Symbol key to avoid conflicts with other globals\nconst MODULES_KEY = Symbol.for(\"nextjs-jsonapi:modules\");\n\n// Use globalThis to persist module registry across HMR reloads\nconst globalStore = globalThis as unknown as {\n [MODULES_KEY]?: Map<string, ApiRequestDataTypeInterface>;\n};\n\n// Initialize global modules map if not set\nif (!globalStore[MODULES_KEY]) {\n globalStore[MODULES_KEY] = new Map();\n}\n\nclass ModuleRegistryClass {\n private get _modules(): Map<string, ApiRequestDataTypeInterface> {\n return globalStore[MODULES_KEY]!;\n }\n\n register<K extends string>(name: K, module: ApiRequestDataTypeInterface): void {\n this._modules.set(name, module);\n }\n\n get<K extends keyof ModuleDefinitions>(name: K): ModuleDefinitions[K] {\n let module = this._modules.get(name as string);\n\n // Self-healing: if module not found, try bootstrapping first\n if (!module) {\n const didBootstrap = tryBootstrap();\n if (didBootstrap) {\n // Retry after bootstrap\n module = this._modules.get(name as string);\n }\n }\n\n if (!module) {\n // Provide helpful error message based on state\n const hint = hasBootstrapper()\n ? \"Bootstrap was called but module still not found. Check module registration.\"\n : \"No bootstrapper registered. Ensure configureJsonApi({ bootstrapper }) is called before accessing modules.\";\n throw new Error(`Module \"${String(name)}\" not registered. ${hint}`);\n }\n\n return module as ModuleDefinitions[K];\n }\n\n /**\n * True when a module is registered under `name`. Never throws, so a component\n * can check for an opt-in module the app may not have registered.\n */\n has(name: string): boolean {\n // Bootstrap only an empty registry (as findByName does): an app that never\n // registers `name` must not re-run its bootstrapper on every check.\n if (this._modules.size === 0) tryBootstrap();\n return this._modules.has(name);\n }\n\n findByName(moduleName: string): ModuleWithPermissions {\n // Self-healing: try bootstrap if registry is empty\n if (this._modules.size === 0) {\n tryBootstrap();\n }\n\n // Search by module's name property (e.g., \"topics\", \"articles\")\n for (const module of this._modules.values()) {\n if ((module as ModuleWithPermissions).name === moduleName) {\n return module as ModuleWithPermissions;\n }\n }\n throw new Error(`Module not found: ${moduleName}`);\n }\n\n getAllPageUrls(): { id: string; text: string }[] {\n if (this._modules.size === 0) {\n tryBootstrap();\n }\n\n const seen = new Set<string>();\n const result: { id: string; text: string }[] = [];\n for (const [key, module] of this._modules.entries()) {\n const m = module as ModuleWithPermissions;\n if (m.pageUrl && !seen.has(m.pageUrl)) {\n seen.add(m.pageUrl);\n result.push({ id: m.pageUrl, text: key });\n result.push({ id: `${m.pageUrl}/:id`, text: `${key} (detail)` });\n }\n }\n return result.sort((a, b) => a.text.localeCompare(b.text));\n }\n\n findByModelName(modelName: string): ModuleWithPermissions {\n // Direct lookup by registry key (e.g., \"Article\", \"Document\")\n let module = this._modules.get(modelName);\n\n // Self-healing: if not found, try bootstrapping\n if (!module) {\n const didBootstrap = tryBootstrap();\n if (didBootstrap) {\n module = this._modules.get(modelName);\n }\n }\n\n if (!module) {\n throw new Error(`Module not found for model: ${modelName}`);\n }\n return module as ModuleWithPermissions;\n }\n\n findByFeature(feature: string): ModuleWithPermissions[] {\n const response: ModuleWithPermissions[] = [];\n\n for (const module of this._modules.values()) {\n const m = module as ModuleWithPermissions;\n if (m.feature === feature) {\n response.push(m);\n }\n }\n\n return response;\n }\n\n getAll(): ApiRequestDataTypeInterface[] {\n if (this._modules.size === 0) {\n tryBootstrap();\n }\n return Array.from(this._modules.values());\n }\n}\n\nexport const ModuleRegistry = new ModuleRegistryClass();\n\n// Proxy object for Modules.X syntax with autocompletion\nexport const Modules = new Proxy({} as ModuleDefinitions, {\n get(_, prop: string) {\n if (prop === \"findByName\") {\n return (name: string) => ModuleRegistry.findByName(name);\n }\n if (prop === \"findByModelName\") {\n return (name: string) => ModuleRegistry.findByModelName(name);\n }\n if (prop === \"findByFeature\") {\n return (feature: string) => ModuleRegistry.findByFeature(feature);\n }\n return ModuleRegistry.get(prop as keyof ModuleDefinitions);\n },\n}) as ModuleDefinitions & {\n findByName: (name: string) => ModuleWithPermissions;\n findByModelName: (name: string) => ModuleWithPermissions;\n findByFeature: (feature: string) => ModuleWithPermissions[];\n};\n","import { FieldSelector } from \"../fields/FieldSelector\";\nimport { ApiRequestDataTypeInterface } from \"../interfaces/ApiRequestDataTypeInterface\";\n\nexport type EndpointQuery = {\n endpoint: ApiRequestDataTypeInterface | string;\n id?: string;\n childEndpoint?: ApiRequestDataTypeInterface | string;\n childId?: string;\n additionalParams?: { key: string; value: string | string[] }[];\n};\n\nexport class EndpointCreator {\n private _endpoint: EndpointQuery;\n\n constructor(params: {\n endpoint: ApiRequestDataTypeInterface | string;\n id?: string;\n childEndpoint?: ApiRequestDataTypeInterface | string;\n childId?: string;\n additionalParams?: { key: string; value: string }[];\n }) {\n this._endpoint = {\n endpoint: params.endpoint,\n id: params.id,\n childEndpoint: params.childEndpoint,\n childId: params.childId,\n additionalParams: params.additionalParams ?? [],\n };\n }\n\n endpoint(value: ApiRequestDataTypeInterface | string): EndpointCreator {\n this._endpoint.endpoint = value;\n return this;\n }\n\n id(value: string): EndpointCreator {\n this._endpoint.id = value;\n return this;\n }\n\n childEndpoint(value: ApiRequestDataTypeInterface | string): EndpointCreator {\n this._endpoint.childEndpoint = value;\n return this;\n }\n\n childId(value: string): EndpointCreator {\n this._endpoint.childId = value;\n return this;\n }\n\n set additionalParams(value: { key: string; value: string }[]) {\n this._endpoint.additionalParams = value;\n }\n\n addAdditionalParam(key: string, value: string | string[]): EndpointCreator {\n if (!this._endpoint.additionalParams) this._endpoint.additionalParams = [];\n this._endpoint.additionalParams.push({ key, value });\n return this;\n }\n\n limitToType(selectors: string[]): this {\n this.addAdditionalParam(`include`, selectors.join(\",\"));\n return this;\n }\n\n limitToFields(selectors: FieldSelector<any>[]): this {\n if (selectors.length === 0) return this;\n\n selectors.forEach((selector) => {\n const fieldString = selector.fields.join(\",\");\n this.addAdditionalParam(`fields[${selector.type}]`, fieldString);\n });\n\n return this;\n }\n\n generate(): string {\n let additionalParams = \"\";\n if (this._endpoint.additionalParams) {\n additionalParams = this._endpoint.additionalParams.map((param) => `${param.key}=${param.value}`).join(\"&\");\n }\n\n let response = ``;\n response += `${\n typeof this._endpoint.endpoint === \"string\" ? this._endpoint.endpoint : this._endpoint.endpoint.name\n }`;\n if (this._endpoint.id) response += `/${this._endpoint.id}`;\n if (this._endpoint.childEndpoint) {\n response += `/${\n typeof this._endpoint.childEndpoint === \"string\"\n ? this._endpoint.childEndpoint\n : this._endpoint.childEndpoint.name\n }`;\n }\n if (this._endpoint.childId) response += `/${this._endpoint.childId}`;\n if (additionalParams) response += `?${additionalParams}`;\n\n return response;\n }\n}\n","import { AbstractApiData } from \"../../../core/abstracts/AbstractApiData\";\nimport { JsonApiHydratedDataInterface } from \"../../../core/interfaces/JsonApiHydratedDataInterface\";\nimport { RootSyncEntry, RootSyncInterface, RootSyncLink } from \"./RootSyncInterface\";\n\n/**\n * Child path of the sync answer under the root module record\n * (`GET /<root endpoint>/:id/sync`), the same value as the app API's sync meta endpoint\n * (in Wyrdli, `campaignSyncMeta.endpoint`).\n */\nexport const ROOT_SYNC_ENDPOINT = \"sync\";\n\n/** The sync answer for one root record (`root-syncs`, id = root record id). Read-only. */\nexport class RootSync extends AbstractApiData implements RootSyncInterface {\n private _serverTime?: Date;\n private _locked: boolean = false;\n private _lockedFrom?: Date;\n private _entries?: RootSyncEntry[];\n private _links?: RootSyncLink[];\n\n get serverTime(): Date {\n if (!this._serverTime) throw new Error(\"serverTime is not set.\");\n return this._serverTime;\n }\n\n get locked(): boolean {\n return this._locked;\n }\n\n get lockedFrom(): Date | undefined {\n return this._lockedFrom;\n }\n\n get entries(): RootSyncEntry[] {\n return this._entries ?? [];\n }\n\n get links(): RootSyncLink[] {\n return this._links ?? [];\n }\n\n rehydrate(data: JsonApiHydratedDataInterface): this {\n super.rehydrate(data);\n\n const attributes = data.jsonApi.attributes ?? {};\n this._serverTime = attributes.serverTime ? new Date(attributes.serverTime) : undefined;\n this._locked = Boolean(attributes.locked);\n this._lockedFrom = attributes.lockedFrom ? new Date(attributes.lockedFrom) : undefined;\n this._entries = (attributes.entries ?? []).map((entry: { type: string; id: string; updatedAt: string }) => ({\n type: entry.type,\n id: entry.id,\n updatedAt: new Date(entry.updatedAt),\n }));\n this._links = (attributes.links ?? []).map((link: RootSyncLink) => ({\n fromType: link.fromType,\n fromId: link.fromId,\n toType: link.toType,\n toId: link.toId,\n kind: link.kind,\n props: link.props ?? {},\n }));\n\n return this;\n }\n\n createJsonApi(_data?: any): any {\n throw new Error(\"RootSync is read-only and cannot be created\");\n }\n}\n"]}
1
+ {"version":3,"sources":["/home/runner/work/nextjs-jsonapi/nextjs-jsonapi/dist/chunk-4XLDBOSE.js","../src/core/factories/RehydrationFactory.ts","../src/core/abstracts/AbstractApiData.ts","../src/i18n/config.ts","../src/core/registry/ModuleRegistry.ts","../src/core/endpoint/EndpointCreator.ts","../src/offline/sync/models/RootSync.ts"],"names":["includedData","includedItem","module","entity"],"mappings":"AAAA;AACE;AACA;AACA;AACF,sDAA4B;AAC5B;AACE;AACF,sDAA4B;AAC5B;AACA;ACCA,IAAM,WAAA,kBAAa,IAAI,GAAA,CAAY,CAAA;AAEnC,IAAM,MAAA,kBAAQ,qCAAA,CAAC,IAAA,EAAA,GAA2D;AACxE,EAAA,MAAM,SAAA,kBAAW,IAAA,6BAAM,SAAA;AACvB,EAAA,uBAAO,QAAA,6BAAU,OAAA,mBAAQ,QAAA,6BAAU,KAAA,EAAK,CAAA,EAAA;AAF5B;AAK2D;AACjD,EAAA;AACD,EAAA;AACW,EAAA;AACd,EAAA;AACd,EAAA;AACS,IAAA;AACX,EAAA;AACqB,IAAA;AACvB,EAAA;AACF;AAVS;AAYuB;AAAA,EAAA;AAAA,IAAA;AAAA,EAAA;AAIzB,EAAA;AACoC,IAAA;AAER,IAAA;AACjC,EAAA;AAKO,EAAA;AACkC,IAAA;AAE3B,IAAA;AACc,MAAA;AAC1B,IAAA;AACF,EAAA;AACF;ADP2C;AACA;AEtCrB;AAA4C,EAAA;AAAA,IAAA;AAAA,EAAA;AACrB,EAAA;AAElB,EAAA;AACqC,IAAA;AAErC,IAAA;AAGzB,EAAA;AAEU,EAAA;AACA,EAAA;AAEA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AAEA,EAAA;AAES,EAAA;AACgB,IAAA;AACrB,IAAA;AACd,EAAA;AAEiB,EAAA;AACgB,IAAA;AACnB,IAAA;AACd,EAAA;AAE+B,EAAA;AACjB,IAAA;AACd,EAAA;AAEsB,EAAA;AACM,IAAA;AAC5B,EAAA;AAEsB,EAAA;AACM,IAAA;AAC5B,EAAA;AAEsB,EAAA;AACM,IAAA;AAC5B,EAAA;AAEmB,EAAA;AACL,IAAA;AACd,EAAA;AAEyD,EAAA;AAAC,EAAA;AAEpB,EAAA;AACpB,IAAA;AAClB,EAAA;AAEgC,EAAA;AACd,IAAA;AAClB,EAAA;AAMuB,EAAA;AAGd,IAAA;AAKE,MAAA;AACT,IAAA;AAE+B,IAAA;AACM,MAAA;AACP,QAAA;AACY,UAAA;AACtC,QAAA;AAEgC,QAAA;AAEN,QAAA;AACfA,UAAAA;AACM,UAAA;AAChB,QAAA;AACF,MAAA;AAE+C,MAAA;AAClD,IAAA;AAEmC,IAAA;AAElB,MAAA;AAEjB,IAAA;AAEuC,IAAA;AAEH,MAAA;AAEjB,QAAA;AAEjB,MAAA;AACgC,MAAA;AACJ,QAAA;AACf,UAAA;AACM,UAAA;AAChB,QAAA;AACH,MAAA;AACF,IAAA;AAEuC,IAAA;AAEH,IAAA;AACzB,MAAA;AACM,MAAA;AAChB,IAAA;AACH,EAAA;AAAA;AAAA;AAAA;AAAA;AAQE,EAAA;AAIoC,IAAA;AAC3B,MAAA;AACT,IAAA;AAE6B,IAAA;AAGR,IAAA;AACe,IAAA;AACJ,MAAA;AAChC,IAAA;AAE4B,IAAA;AAEL,MAAA;AACO,MAAA;AACA,QAAA;AACP,QAAA;AAGaC,QAAAA;AACnB,QAAA;AAEN,QAAA;AACwBC,UAAAA;AAClBD,YAAAA;AACM,YAAA;AAChB,UAAA;AACH,QAAA;AACF,MAAA;AACoC,MAAA;AACtC,IAAA;AAGmC,IAAA;AACT,IAAA;AAEM,IAAA;AACZ,IAAA;AAEgB,IAAA;AACzB,MAAA;AACM,MAAA;AAChB,IAAA;AACH,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAiBE,EAAA;AAKO,IAAA;AAKE,MAAA;AACT,IAAA;AAEsC,IAAA;AAGD,IAAA;AACR,MAAA;AAEU,MAAA;AACT,QAAA;AAEP,QAAA;AAEe,QAAA;AACvBD,UAAAA;AACM,UAAA;AAChB,QAAA;AAGc,QAAA;AACcG,UAAAA;AAC7B,QAAA;AAE2B,QAAA;AAC7B,MAAA;AAEO,MAAA;AACT,IAAA;AAGmC,IAAA;AACS,MAAA;AAC5C,IAAA;AAEmB,IAAA;AAEe,MAAA;AACI,QAAA;AACP,UAAA;AAC3B,QAAA;AACkB,QAAA;AACD,UAAA;AACJ,YAAA;AACM,YAAA;AAChB,UAAA;AAG6B,UAAA;AACR,UAAA;AACOA,YAAAA;AAC7B,UAAA;AACOA,UAAAA;AACT,QAAA;AACF,MAAA;AACO,MAAA;AACT,IAAA;AAEkC,IAAA;AACvB,MAAA;AACM,MAAA;AAChB,IAAA;AAGqC,IAAA;AAChB,IAAA;AACe,MAAA;AACrC,IAAA;AAEO,IAAA;AACT,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAO2E,EAAA;AACvC,IAAA;AACK,MAAA;AACvC,IAAA;AACF,EAAA;AAE0C,EAAA;AACjC,IAAA;AACS,MAAA;AACe,MAAA;AAC/B,IAAA;AACF,EAAA;AAEoD,EAAA;AAC7B,IAAA;AACC,IAAA;AAEK,IAAA;AACF,IAAA;AACa,IAAA;AACA,IAAA;AAEJ,IAAA;AAE3B,IAAA;AACT,EAAA;AACF;AFrD2C;AACA;AGxNV;AAGuB;AAC5C,EAAA;AACZ;AAFgB;AAK4B;AACjB,EAAA;AACP,IAAA;AAClB,EAAA;AACyB,EAAA;AAC3B;AALgB;AAO+F;AAC9E,EAAA;AAEL,IAAA;AAC1B,EAAA;AACwC,EAAA;AAC1C;AANgB;AAQ6B;AACvB,EAAA;AACF,IAAA;AAClB,EAAA;AACe,EAAA;AACjB;AALgB;AAOwB;AACd,EAAA;AACG,IAAA;AAC3B,EAAA;AAEO,EAAA;AACT;AANgB;AAS6C;AAClC,EAAA;AACP,IAAA;AAClB,EAAA;AACyB,EAAA;AAC3B;AALsB;AAOsB;AACX,EAAA;AACG,IAAA;AAClC,EAAA;AAEO,EAAA;AACT;AANgB;AASoC;AACT,EAAA;AACxB,IAAA;AACjB,EAAA;AACY,EAAA;AACd;AALgB;AAQ+B;AACX,EAAA;AACpC;AAFgB;AHoN2B;AACA;AIrMhB;AAGP;AAKW;AACF,EAAA;AAC7B;AAE0B;AAAA,EAAA;AAAA,IAAA;AAAA,EAAA;AACyC,EAAA;AACjC,IAAA;AAChC,EAAA;AAE+E,EAAA;AAC/C,IAAA;AAChC,EAAA;AAEsE,EAAA;AACvB,IAAA;AAGhC,IAAA;AACuB,MAAA;AAChB,MAAA;AAEyB,QAAA;AAC3C,MAAA;AACF,IAAA;AAEa,IAAA;AAGP,MAAA;AAE8B,MAAA;AACpC,IAAA;AAEO,IAAA;AACT,EAAA;AAAA;AAAA;AAAA;AAAA;AAM2B,EAAA;AAGK,IAAA;AACD,IAAA;AAC/B,EAAA;AAEsD,EAAA;AAEtB,IAAA;AACf,MAAA;AACf,IAAA;AAGmC,IAAA;AAC0B,MAAA;AAClD,QAAA;AACT,MAAA;AACF,IAAA;AACqC,IAAA;AACvC,EAAA;AAEiD,EAAA;AACjB,IAAA;AACf,MAAA;AACf,IAAA;AAE6B,IAAA;AACmB,IAAA;AACf,IAAA;AACrB,MAAA;AAC0B,MAAA;AAChB,QAAA;AACiB,QAAA;AACL,QAAA;AAChC,MAAA;AACF,IAAA;AACoC,IAAA;AACtC,EAAA;AAE0D,EAAA;AAEzB,IAAA;AAGlB,IAAA;AACuB,MAAA;AAChB,MAAA;AACW,QAAA;AAC7B,MAAA;AACF,IAAA;AAEa,IAAA;AACK,MAAA;AAClB,IAAA;AACO,IAAA;AACT,EAAA;AAEwD,EAAA;AACX,IAAA;AAER,IAAA;AACvB,MAAA;AACiB,MAAA;AACV,QAAA;AACjB,MAAA;AACF,IAAA;AAEO,IAAA;AACT,EAAA;AAEwC,EAAA;AACR,IAAA;AACf,MAAA;AACf,IAAA;AACuC,IAAA;AACzC,EAAA;AACF;AAEkC;AAGwB;AACnC,EAAA;AACQ,IAAA;AACe,MAAA;AAC1C,IAAA;AACgC,IAAA;AACU,MAAA;AAC1C,IAAA;AAC8B,IAAA;AACe,MAAA;AAC7C,IAAA;AACyD,IAAA;AAC3D,EAAA;AACD;AJoK0C;AACA;AKnad;AAAA,EAAA;AAAA,IAAA;AAAA,EAAA;AACnB,EAAA;AAQL,EAAA;AACgB,IAAA;AACE,MAAA;AACN,MAAA;AACW,MAAA;AACN,MAAA;AACS,MAAA;AAC3B,IAAA;AACF,EAAA;AAEuE,EAAA;AAC3C,IAAA;AACnB,IAAA;AACT,EAAA;AAEmC,EAAA;AACb,IAAA;AACb,IAAA;AACT,EAAA;AAE4E,EAAA;AAC3C,IAAA;AACxB,IAAA;AACT,EAAA;AAEwC,EAAA;AACb,IAAA;AAClB,IAAA;AACT,EAAA;AAE8D,EAAA;AAC1B,IAAA;AACpC,EAAA;AAE2E,EAAA;AACnC,IAAA;AACC,IAAA;AAChC,IAAA;AACT,EAAA;AAEuC,EAAA;AACF,IAAA;AAC5B,IAAA;AACT,EAAA;AAEqD,EAAA;AAChB,IAAA;AAEH,IAAA;AACM,MAAA;AACF,MAAA;AACnC,IAAA;AAEM,IAAA;AACT,EAAA;AAEmB,EAAA;AACM,IAAA;AACc,IAAA;AACD,MAAA;AACpC,IAAA;AAEe,IAAA;AAES,IAAA;AAEe,IAAA;AACL,IAAA;AAElB,MAAA;AAIhB,IAAA;AAC4B,IAAA;AACU,IAAA;AAE/B,IAAA;AACT,EAAA;AACF;AL8Y2C;AACA;AMzeT;AAGJ;AAA6C,EAAA;AAAA,IAAA;AAAA,EAAA;AACjE,EAAA;AACmB,iBAAA;AACnB,EAAA;AACA,EAAA;AACA,EAAA;AAEe,EAAA;AACkB,IAAA;AAC3B,IAAA;AACd,EAAA;AAEsB,EAAA;AACR,IAAA;AACd,EAAA;AAEmC,EAAA;AACrB,IAAA;AACd,EAAA;AAE+B,EAAA;AACJ,IAAA;AAC3B,EAAA;AAE4B,EAAA;AACH,IAAA;AACzB,EAAA;AAEoD,EAAA;AAC9B,IAAA;AAEY,IAAA;AACF,IAAA;AACI,IAAA;AACJ,IAAA;AACS,IAAA;AACzB,MAAA;AACF,MAAA;AACyB,MAAA;AACnC,IAAA;AACqC,IAAA;AACtB,MAAA;AACF,MAAA;AACA,MAAA;AACF,MAAA;AACA,MAAA;AACW,MAAA;AACtB,IAAA;AAEK,IAAA;AACT,EAAA;AAEgC,EAAA;AACd,IAAA;AAClB,EAAA;AACF;ANme2C;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA","file":"/home/runner/work/nextjs-jsonapi/nextjs-jsonapi/dist/chunk-4XLDBOSE.js","sourcesContent":[null,"import { ApiDataInterface } from \"../interfaces/ApiDataInterface\";\nimport { ApiRequestDataTypeInterface } from \"../interfaces/ApiRequestDataTypeInterface\";\nimport { JsonApiHydratedDataInterface } from \"../interfaces/JsonApiHydratedDataInterface\";\nimport { DataClassRegistry } from \"../registry/DataClassRegistry\";\n\n/**\n * The resources being rehydrated right now, along the current chain of relationships. A resource\n * met again inside its own chain (A's relationship leads to B, B's back to A) is a circle in the\n * `included` data: following it would recurse until the stack overflows, so it is skipped there.\n */\nconst inProgress = new Set<string>();\n\nconst keyOf = (data: JsonApiHydratedDataInterface): string | undefined => {\n const resource = data?.jsonApi;\n return resource?.type && resource?.id ? `${resource.type}:${resource.id}` : undefined;\n};\n\nfunction guarded<T>(data: JsonApiHydratedDataInterface, run: () => T): T {\n const key = keyOf(data);\n if (!key) return run();\n if (inProgress.has(key)) return undefined as T;\n inProgress.add(key);\n try {\n return run();\n } finally {\n inProgress.delete(key);\n }\n}\n\nexport class RehydrationFactory {\n public static rehydrate<T extends ApiDataInterface>(\n classKey: ApiRequestDataTypeInterface,\n data: JsonApiHydratedDataInterface,\n ): T {\n const factoryClass = DataClassRegistry.get(classKey);\n\n return guarded(data, () => new factoryClass().rehydrate(data) as T);\n }\n\n public static rehydrateList<T extends ApiDataInterface>(\n classKey: ApiRequestDataTypeInterface,\n data: JsonApiHydratedDataInterface[],\n ): T[] {\n const factoryClass = DataClassRegistry.get(classKey);\n\n return data.map((item: JsonApiHydratedDataInterface) =>\n guarded(item, () => new factoryClass().rehydrate(item) as T),\n );\n }\n}\n","import { RehydrationFactory } from \"../factories/RehydrationFactory\";\nimport { ApiDataInterface } from \"../interfaces/ApiDataInterface\";\nimport { ApiRequestDataTypeInterface } from \"../interfaces/ApiRequestDataTypeInterface\";\nimport { JsonApiHydratedDataInterface } from \"../interfaces/JsonApiHydratedDataInterface\";\n\nexport abstract class AbstractApiData implements ApiDataInterface {\n static identifierFields: string[] = [\"name\"];\n\n get identifier(): string {\n const fields = (this.constructor as typeof AbstractApiData).identifierFields;\n return fields\n .map((field) => this._jsonApi?.attributes?.[field])\n .filter((v) => v != null && v !== \"\")\n .join(\" \");\n }\n\n protected _jsonApi?: any;\n protected _included?: any[];\n\n protected _id?: string;\n protected _type?: string;\n protected _createdAt?: Date;\n protected _updatedAt?: Date;\n\n protected _self?: string;\n\n get type(): string {\n if (!this._type) throw new Error(\"Type is not set.\");\n return this._type;\n }\n\n get id(): string {\n if (!this._id) throw new Error(\"Id is not set.\");\n return this._id;\n }\n\n get self(): string | undefined {\n return this._self;\n }\n\n get createdAt(): Date {\n return this._createdAt ?? new Date();\n }\n\n get updatedAt(): Date {\n return this._updatedAt ?? new Date();\n }\n\n get included(): any[] {\n return this._included ?? [];\n }\n\n get jsonApi(): any {\n return this._jsonApi;\n }\n\n ingestJsonApi(_data: JsonApiHydratedDataInterface): void {}\n\n generateApiUrl(_params?: any): string {\n throw new Error(\"Method not implemented.\");\n }\n\n createJsonApi(_data?: any): any {\n throw new Error(\"Method not implemented.\");\n }\n\n protected _readIncluded<T extends ApiDataInterface>(\n data: JsonApiHydratedDataInterface,\n type: string,\n dataType: ApiRequestDataTypeInterface,\n ): T | T[] | undefined {\n if (\n data.included === undefined ||\n data.included.length === 0 ||\n data.jsonApi.relationships === undefined ||\n data.jsonApi.relationships[type] === undefined ||\n data.jsonApi.relationships[type].data === undefined\n ) {\n return undefined;\n }\n\n if (Array.isArray(data.jsonApi.relationships[type].data)) {\n const response: T[] = data.jsonApi.relationships[type].data.map((jsonApiData: any) => {\n const includedData = data.included.find(\n (includedData: any) => includedData.id === jsonApiData.id && includedData.type === jsonApiData.type,\n );\n\n if (includedData === undefined) return undefined;\n\n return RehydrationFactory.rehydrate(dataType, {\n jsonApi: includedData,\n included: data.included,\n }) as T;\n });\n\n return response.filter((item: T | undefined) => item !== undefined) as T[];\n }\n\n const includedData = data.included.find(\n (includedData: any) =>\n includedData.id === data.jsonApi.relationships[type].data.id &&\n includedData.type === data.jsonApi.relationships[type].data.type,\n );\n\n if (includedData === undefined && data.allData !== undefined) {\n // Try to find in allData as a fallback\n const fallbackData = data.allData.find(\n (includedData: any) =>\n includedData.id === data.jsonApi.relationships[type].data.id &&\n includedData.type === data.jsonApi.relationships[type].data.type,\n );\n if (fallbackData !== undefined) {\n return RehydrationFactory.rehydrate(dataType, {\n jsonApi: fallbackData,\n included: data.included,\n }) as T;\n }\n }\n\n if (includedData === undefined) return undefined;\n\n return RehydrationFactory.rehydrate(dataType, {\n jsonApi: includedData,\n included: data.included,\n }) as T;\n }\n\n /**\n * Read included relationships with polymorphic type resolution.\n * Determines the correct model class based on the JSON:API type in included data.\n */\n protected _readIncludedPolymorphic<T extends ApiDataInterface>(\n data: JsonApiHydratedDataInterface,\n relationshipKey: string,\n candidateModules: ApiRequestDataTypeInterface[],\n ): T | T[] | undefined {\n // Validate relationship exists\n if (!data.included?.length || !data.jsonApi.relationships?.[relationshipKey]?.data) {\n return undefined;\n }\n\n const relData = data.jsonApi.relationships[relationshipKey].data;\n\n // Build lookup map: JSON:API type -> module\n const typeToModule = new Map<string, ApiRequestDataTypeInterface>();\n for (const mod of candidateModules) {\n typeToModule.set(mod.name, mod);\n }\n\n if (Array.isArray(relData)) {\n // Many relationship\n const result: T[] = [];\n for (const item of relData) {\n const includedItem = data.included.find((inc: any) => inc.id === item.id && inc.type === item.type);\n if (!includedItem) continue;\n\n // Resolve module by JSON:API type\n const module = typeToModule.get(includedItem.type);\n if (!module) continue;\n\n result.push(\n RehydrationFactory.rehydrate(module, {\n jsonApi: includedItem,\n included: data.included,\n }) as T,\n );\n }\n return result.length > 0 ? result : undefined;\n }\n\n // Single relationship\n const includedItem = data.included.find((inc: any) => inc.id === relData.id && inc.type === relData.type);\n if (!includedItem) return undefined;\n\n const module = typeToModule.get(includedItem.type);\n if (!module) return undefined;\n\n return RehydrationFactory.rehydrate(module, {\n jsonApi: includedItem,\n included: data.included,\n }) as T;\n }\n\n /**\n * Read included relationship data and augment with relationship meta properties.\n * Handles both single relationships (one-to-one) and array relationships (one-to-many).\n *\n * For single relationships: meta is read from `relationships[type].meta`\n * For array relationships: per-item meta is read from `relationships[type].data[].meta`\n *\n * @param data - Hydrated JSON:API data\n * @param type - Relationship type key (e.g., \"guide\", \"persons\")\n * @param dataType - Module reference for rehydration\n * @returns Related object(s) augmented with meta properties, or undefined\n */\n protected _readIncludedWithMeta<T extends ApiDataInterface, M extends Record<string, any>>(\n data: JsonApiHydratedDataInterface,\n type: string,\n dataType: ApiRequestDataTypeInterface,\n ): (T & M) | (T & M)[] | undefined {\n // Check if relationship exists\n if (\n data.included === undefined ||\n data.included.length === 0 ||\n data.jsonApi.relationships === undefined ||\n data.jsonApi.relationships[type] === undefined ||\n data.jsonApi.relationships[type].data === undefined\n ) {\n return undefined;\n }\n\n const relationshipData = data.jsonApi.relationships[type].data;\n\n // Handle array relationships with per-item meta\n if (Array.isArray(relationshipData)) {\n const result: (T & M)[] = [];\n\n for (const item of relationshipData) {\n const includedData = data.included.find((inc: any) => inc.id === item.id && inc.type === item.type);\n\n if (!includedData) continue;\n\n const entity = RehydrationFactory.rehydrate(dataType, {\n jsonApi: includedData,\n included: data.included,\n }) as T;\n\n // Merge per-item meta from relationships[type].data[].meta\n if (item.meta) {\n AbstractApiData._mergeMeta(entity, item.meta);\n }\n\n result.push(entity as T & M);\n }\n\n return result;\n }\n\n // Handle single relationship\n const includedData = data.included.find(\n (inc: any) => inc.id === relationshipData.id && inc.type === relationshipData.type,\n );\n\n if (!includedData) {\n // Try to find in allData as a fallback\n if (data.allData !== undefined) {\n const fallbackData = data.allData.find(\n (inc: any) => inc.id === relationshipData.id && inc.type === relationshipData.type,\n );\n if (fallbackData) {\n const entity = RehydrationFactory.rehydrate(dataType, {\n jsonApi: fallbackData,\n included: data.included,\n }) as T;\n\n // Merge relationship-level meta for single relationships\n const relationshipMeta = data.jsonApi.relationships[type].meta;\n if (relationshipMeta) {\n AbstractApiData._mergeMeta(entity, relationshipMeta);\n }\n return entity as T & M;\n }\n }\n return undefined;\n }\n\n const entity = RehydrationFactory.rehydrate(dataType, {\n jsonApi: includedData,\n included: data.included,\n }) as T;\n\n // Merge relationship-level meta for single relationships\n const relationshipMeta = data.jsonApi.relationships[type].meta;\n if (relationshipMeta) {\n AbstractApiData._mergeMeta(entity, relationshipMeta);\n }\n\n return entity as T & M;\n }\n\n /**\n * Copies relationship meta onto a rehydrated entity as own data properties. Object.assign throws\n * when the model declares a getter-only accessor of the same name (an app's `Chunk` with\n * `get relevance()`); an own property shadows that getter, so the model reads the meta value.\n */\n private static _mergeMeta(entity: object, meta: Record<string, any>): void {\n for (const [key, value] of Object.entries(meta)) {\n Object.defineProperty(entity, key, { value, writable: true, enumerable: true, configurable: true });\n }\n }\n\n dehydrate(): JsonApiHydratedDataInterface {\n return {\n jsonApi: this._jsonApi,\n included: this._included ?? [],\n };\n }\n\n rehydrate(data: JsonApiHydratedDataInterface): this {\n this._jsonApi = data.jsonApi;\n this._included = data.included;\n\n this._type = this._jsonApi.type;\n this._id = this._jsonApi.id;\n this._createdAt = this._jsonApi.meta?.createdAt !== undefined ? new Date(this._jsonApi.meta.createdAt) : undefined;\n this._updatedAt = this._jsonApi.meta?.updatedAt !== undefined ? new Date(this._jsonApi.meta.updatedAt) : undefined;\n\n this._self = this._jsonApi.links?.self ?? undefined;\n\n return this;\n }\n}\n","import { ComponentType } from \"react\";\n\n// Types for injected hooks\nexport interface I18nRouter {\n push: (href: string) => void;\n replace: (href: string) => void;\n back: () => void;\n forward: () => void;\n refresh: () => void;\n prefetch: (href: string) => void;\n}\n\nexport type UseRouterHook = () => I18nRouter;\nexport type UseTranslationsHook = (namespace?: string) => (key: string, values?: Record<string, any>) => string;\nexport type UseLocaleHook = () => string;\nexport type GetLocaleFunction = () => Promise<string>;\n\nexport type UseDateFnsLocaleHook = () => any; // date-fns Locale type\nexport type LinkComponent = ComponentType<{ href: string; children: React.ReactNode; [key: string]: any }>;\n\nexport interface I18nConfig {\n useRouter: UseRouterHook;\n useTranslations: UseTranslationsHook;\n useLocale?: UseLocaleHook;\n useDateFnsLocale?: UseDateFnsLocaleHook;\n Link: LinkComponent;\n usePathname: () => string;\n /**\n * Server-side locale for API requests (pass next-intl's `getLocale` from `next-intl/server`).\n *\n * The library never imports next-intl itself: instrumentation loads the library, and\n * next-intl's `getLocale` pulls in the app's `i18n/request.ts`, which reads\n * `next/root-params` — a module only allowed inside the app directory.\n */\n getLocale: GetLocaleFunction;\n /**\n * Locales the app supports. The first entry is the fallback.\n * Defaults to `[\"en\"]` when omitted.\n */\n supportedLocales?: string[];\n}\n\n// Private storage\nlet _config: I18nConfig | null = null;\n\n// Configuration function (called by app at startup)\nexport function configureI18n(config: I18nConfig): void {\n _config = config;\n}\n\n// Hooks for library components to use\nexport function useI18nRouter(): I18nRouter {\n if (!_config?.useRouter) {\n throw new Error(\"i18n not configured. Call configureI18n() at app startup.\");\n }\n return _config.useRouter();\n}\n\nexport function useI18nTranslations(namespace?: string): (key: string, values?: Record<string, any>) => string {\n if (!_config?.useTranslations) {\n // Fallback: return key as-is (safe for server/client)\n return (key: string) => key;\n }\n return _config.useTranslations(namespace);\n}\n\nexport function getI18nLink(): LinkComponent {\n if (!_config?.Link) {\n throw new Error(\"i18n not configured. Call configureI18n() at app startup.\");\n }\n return _config.Link;\n}\n\nexport function useI18nLocale(): string {\n if (_config?.useLocale) {\n return _config.useLocale();\n }\n // Fallback to English (safe for server/client)\n return \"en\";\n}\n\n/** The server-side locale from the app's `getLocale`. Throws when `configureI18n` has not run. */\nexport async function getI18nServerLocale(): Promise<string> {\n if (!_config?.getLocale) {\n throw new Error(\"i18n not configured. Call configureI18n() with getLocale at app startup.\");\n }\n return _config.getLocale();\n}\n\nexport function useI18nDateFnsLocale(): any {\n if (_config?.useDateFnsLocale) {\n return _config.useDateFnsLocale();\n }\n // Fallback to undefined (Calendar will use default)\n return undefined;\n}\n\n/** The app's supported locales. Defaults to `[\"en\"]` when not configured. */\nexport function getI18nSupportedLocales(): string[] {\n if (_config?.supportedLocales && _config.supportedLocales.length > 0) {\n return _config.supportedLocales;\n }\n return [\"en\"];\n}\n\n/** The app's default locale: the first supported locale (`\"en\"` when not configured). */\nexport function getI18nDefaultLocale(): string {\n return getI18nSupportedLocales()[0];\n}\n","import { ModuleWithPermissions } from \"../../permissions/types\";\nimport { ApiRequestDataTypeInterface } from \"../interfaces/ApiRequestDataTypeInterface\";\nimport { hasBootstrapper, tryBootstrap } from \"./bootstrapStore\";\n\n// Foundation module types - defined by LIBRARY\nexport interface FoundationModuleDefinitions {\n S3: ModuleWithPermissions;\n Auth: ModuleWithPermissions;\n User: ModuleWithPermissions;\n Author: ModuleWithPermissions;\n Company: ModuleWithPermissions;\n Role: ModuleWithPermissions;\n Notification: ModuleWithPermissions;\n Push: ModuleWithPermissions;\n Feature: ModuleWithPermissions;\n Module: ModuleWithPermissions;\n Content: ModuleWithPermissions;\n HowTo: ModuleWithPermissions;\n HandbookPage: ModuleWithPermissions;\n HandbookSection: ModuleWithPermissions;\n HandbookThread: ModuleWithPermissions;\n HandbookThreadMessage: ModuleWithPermissions;\n Assistant: ModuleWithPermissions;\n AssistantMessage: ModuleWithPermissions;\n AssistantAction: ModuleWithPermissions;\n Chunk: ModuleWithPermissions;\n // Billing modules - READ: all users, UPDATE: CompanyAdministrator, ADMIN: Administrator\n Billing: ModuleWithPermissions;\n StripeCustomer: ModuleWithPermissions;\n StripePaymentMethod: ModuleWithPermissions;\n StripeSubscription: ModuleWithPermissions;\n StripeInvoice: ModuleWithPermissions;\n StripeProduct: ModuleWithPermissions;\n StripePrice: ModuleWithPermissions;\n StripeUsage: ModuleWithPermissions;\n StripePromotionCode: ModuleWithPermissions;\n StripeCoupon: ModuleWithPermissions;\n StripeCouponCode: ModuleWithPermissions;\n StripeCouponOffer: ModuleWithPermissions;\n // AI connection administration\n AiConnection: ModuleWithPermissions;\n // OAuth modules\n OAuth: ModuleWithPermissions;\n // Waitlist modules\n Waitlist: ModuleWithPermissions;\n WaitlistStats: ModuleWithPermissions;\n // Email automation modules\n EmailAutomation: ModuleWithPermissions;\n EmailAutomationStep: ModuleWithPermissions;\n EmailAutomationEnrollment: ModuleWithPermissions;\n EmailAutomationTrigger: ModuleWithPermissions;\n // Email blast modules\n EmailBlast: ModuleWithPermissions;\n EmailBlastDelivery: ModuleWithPermissions;\n EmailBlastAudience: ModuleWithPermissions;\n // Blog modules\n BlogPost: ModuleWithPermissions;\n BlogPostTranslation: ModuleWithPermissions;\n BlogCategory: ModuleWithPermissions;\n BlogCategoryTranslation: ModuleWithPermissions;\n BlogSettings: ModuleWithPermissions;\n // Referral modules\n Referral: ModuleWithPermissions;\n ReferralStats: ModuleWithPermissions;\n // Referral link visits and the administrative referral report (opt-in: registered by apps that spread referralAdminModules)\n ReferralVisit: ModuleWithPermissions;\n ReferralAdminSummary: ModuleWithPermissions;\n ReferralAdminReferrer: ModuleWithPermissions;\n ReferralAdminReferral: ModuleWithPermissions;\n // Two-factor authentication modules\n TotpAuthenticator: ModuleWithPermissions;\n TotpSetup: ModuleWithPermissions;\n TotpVerify: ModuleWithPermissions;\n TotpVerifyLogin: ModuleWithPermissions;\n Passkey: ModuleWithPermissions;\n PasskeyRegistrationOptions: ModuleWithPermissions;\n PasskeyRegistrationVerify: ModuleWithPermissions;\n PasskeyRename: ModuleWithPermissions;\n PasskeyVerifyLogin: ModuleWithPermissions;\n PasskeyAuthenticationOptions: ModuleWithPermissions;\n TwoFactorEnable: ModuleWithPermissions;\n TwoFactorChallenge: ModuleWithPermissions;\n TwoFactorStatus: ModuleWithPermissions;\n BackupCodeVerify: ModuleWithPermissions;\n // OAuth sign-up awaiting consent\n PendingRegistration: ModuleWithPermissions;\n // RBAC modules\n PermissionMapping: ModuleWithPermissions;\n ModulePaths: ModuleWithPermissions;\n RbacMatrix: ModuleWithPermissions;\n // Audit modules\n AuditLog: ModuleWithPermissions;\n // Administrative token-usage reporting modules\n TokenUsageAdminSummary: ModuleWithPermissions;\n TokenUsageAdminTimeline: ModuleWithPermissions;\n TokenUsageAdminBreakdown: ModuleWithPermissions;\n // Self-service token-usage reporting modules\n TokenUsageReportSummary: ModuleWithPermissions;\n TokenUsageReportTimeline: ModuleWithPermissions;\n TokenUsageReportBreakdown: ModuleWithPermissions;\n // First-party web analytics modules (tracker + administrative dashboard)\n AnalyticsEvent: ModuleWithPermissions;\n AnalyticsSummary: ModuleWithPermissions;\n AnalyticsTimeline: ModuleWithPermissions;\n AnalyticsBreakdown: ModuleWithPermissions;\n AnalyticsSession: ModuleWithPermissions;\n AnalyticsPageView: ModuleWithPermissions;\n // Account deletion (opt-in: registered only by apps that enable it)\n AccountDeletion: ModuleWithPermissions;\n // Offline mode (opt-in: registered by apps that spread offlineModules)\n OfflineChangeSet: ModuleWithPermissions;\n RootSync: ModuleWithPermissions;\n}\n\n// App-specific modules - apps will augment this interface ONLY\n\nexport interface AppModuleDefinitions {}\n\n// Combined type for full autocompletion\nexport type ModuleDefinitions = FoundationModuleDefinitions & AppModuleDefinitions;\n\n// Symbol key to avoid conflicts with other globals\nconst MODULES_KEY = Symbol.for(\"nextjs-jsonapi:modules\");\n\n// Use globalThis to persist module registry across HMR reloads\nconst globalStore = globalThis as unknown as {\n [MODULES_KEY]?: Map<string, ApiRequestDataTypeInterface>;\n};\n\n// Initialize global modules map if not set\nif (!globalStore[MODULES_KEY]) {\n globalStore[MODULES_KEY] = new Map();\n}\n\nclass ModuleRegistryClass {\n private get _modules(): Map<string, ApiRequestDataTypeInterface> {\n return globalStore[MODULES_KEY]!;\n }\n\n register<K extends string>(name: K, module: ApiRequestDataTypeInterface): void {\n this._modules.set(name, module);\n }\n\n get<K extends keyof ModuleDefinitions>(name: K): ModuleDefinitions[K] {\n let module = this._modules.get(name as string);\n\n // Self-healing: if module not found, try bootstrapping first\n if (!module) {\n const didBootstrap = tryBootstrap();\n if (didBootstrap) {\n // Retry after bootstrap\n module = this._modules.get(name as string);\n }\n }\n\n if (!module) {\n // Provide helpful error message based on state\n const hint = hasBootstrapper()\n ? \"Bootstrap was called but module still not found. Check module registration.\"\n : \"No bootstrapper registered. Ensure configureJsonApi({ bootstrapper }) is called before accessing modules.\";\n throw new Error(`Module \"${String(name)}\" not registered. ${hint}`);\n }\n\n return module as ModuleDefinitions[K];\n }\n\n /**\n * True when a module is registered under `name`. Never throws, so a component\n * can check for an opt-in module the app may not have registered.\n */\n has(name: string): boolean {\n // Bootstrap only an empty registry (as findByName does): an app that never\n // registers `name` must not re-run its bootstrapper on every check.\n if (this._modules.size === 0) tryBootstrap();\n return this._modules.has(name);\n }\n\n findByName(moduleName: string): ModuleWithPermissions {\n // Self-healing: try bootstrap if registry is empty\n if (this._modules.size === 0) {\n tryBootstrap();\n }\n\n // Search by module's name property (e.g., \"topics\", \"articles\")\n for (const module of this._modules.values()) {\n if ((module as ModuleWithPermissions).name === moduleName) {\n return module as ModuleWithPermissions;\n }\n }\n throw new Error(`Module not found: ${moduleName}`);\n }\n\n getAllPageUrls(): { id: string; text: string }[] {\n if (this._modules.size === 0) {\n tryBootstrap();\n }\n\n const seen = new Set<string>();\n const result: { id: string; text: string }[] = [];\n for (const [key, module] of this._modules.entries()) {\n const m = module as ModuleWithPermissions;\n if (m.pageUrl && !seen.has(m.pageUrl)) {\n seen.add(m.pageUrl);\n result.push({ id: m.pageUrl, text: key });\n result.push({ id: `${m.pageUrl}/:id`, text: `${key} (detail)` });\n }\n }\n return result.sort((a, b) => a.text.localeCompare(b.text));\n }\n\n findByModelName(modelName: string): ModuleWithPermissions {\n // Direct lookup by registry key (e.g., \"Article\", \"Document\")\n let module = this._modules.get(modelName);\n\n // Self-healing: if not found, try bootstrapping\n if (!module) {\n const didBootstrap = tryBootstrap();\n if (didBootstrap) {\n module = this._modules.get(modelName);\n }\n }\n\n if (!module) {\n throw new Error(`Module not found for model: ${modelName}`);\n }\n return module as ModuleWithPermissions;\n }\n\n findByFeature(feature: string): ModuleWithPermissions[] {\n const response: ModuleWithPermissions[] = [];\n\n for (const module of this._modules.values()) {\n const m = module as ModuleWithPermissions;\n if (m.feature === feature) {\n response.push(m);\n }\n }\n\n return response;\n }\n\n getAll(): ApiRequestDataTypeInterface[] {\n if (this._modules.size === 0) {\n tryBootstrap();\n }\n return Array.from(this._modules.values());\n }\n}\n\nexport const ModuleRegistry = new ModuleRegistryClass();\n\n// Proxy object for Modules.X syntax with autocompletion\nexport const Modules = new Proxy({} as ModuleDefinitions, {\n get(_, prop: string) {\n if (prop === \"findByName\") {\n return (name: string) => ModuleRegistry.findByName(name);\n }\n if (prop === \"findByModelName\") {\n return (name: string) => ModuleRegistry.findByModelName(name);\n }\n if (prop === \"findByFeature\") {\n return (feature: string) => ModuleRegistry.findByFeature(feature);\n }\n return ModuleRegistry.get(prop as keyof ModuleDefinitions);\n },\n}) as ModuleDefinitions & {\n findByName: (name: string) => ModuleWithPermissions;\n findByModelName: (name: string) => ModuleWithPermissions;\n findByFeature: (feature: string) => ModuleWithPermissions[];\n};\n","import { FieldSelector } from \"../fields/FieldSelector\";\nimport { ApiRequestDataTypeInterface } from \"../interfaces/ApiRequestDataTypeInterface\";\n\nexport type EndpointQuery = {\n endpoint: ApiRequestDataTypeInterface | string;\n id?: string;\n childEndpoint?: ApiRequestDataTypeInterface | string;\n childId?: string;\n additionalParams?: { key: string; value: string | string[] }[];\n};\n\nexport class EndpointCreator {\n private _endpoint: EndpointQuery;\n\n constructor(params: {\n endpoint: ApiRequestDataTypeInterface | string;\n id?: string;\n childEndpoint?: ApiRequestDataTypeInterface | string;\n childId?: string;\n additionalParams?: { key: string; value: string }[];\n }) {\n this._endpoint = {\n endpoint: params.endpoint,\n id: params.id,\n childEndpoint: params.childEndpoint,\n childId: params.childId,\n additionalParams: params.additionalParams ?? [],\n };\n }\n\n endpoint(value: ApiRequestDataTypeInterface | string): EndpointCreator {\n this._endpoint.endpoint = value;\n return this;\n }\n\n id(value: string): EndpointCreator {\n this._endpoint.id = value;\n return this;\n }\n\n childEndpoint(value: ApiRequestDataTypeInterface | string): EndpointCreator {\n this._endpoint.childEndpoint = value;\n return this;\n }\n\n childId(value: string): EndpointCreator {\n this._endpoint.childId = value;\n return this;\n }\n\n set additionalParams(value: { key: string; value: string }[]) {\n this._endpoint.additionalParams = value;\n }\n\n addAdditionalParam(key: string, value: string | string[]): EndpointCreator {\n if (!this._endpoint.additionalParams) this._endpoint.additionalParams = [];\n this._endpoint.additionalParams.push({ key, value });\n return this;\n }\n\n limitToType(selectors: string[]): this {\n this.addAdditionalParam(`include`, selectors.join(\",\"));\n return this;\n }\n\n limitToFields(selectors: FieldSelector<any>[]): this {\n if (selectors.length === 0) return this;\n\n selectors.forEach((selector) => {\n const fieldString = selector.fields.join(\",\");\n this.addAdditionalParam(`fields[${selector.type}]`, fieldString);\n });\n\n return this;\n }\n\n generate(): string {\n let additionalParams = \"\";\n if (this._endpoint.additionalParams) {\n additionalParams = this._endpoint.additionalParams.map((param) => `${param.key}=${param.value}`).join(\"&\");\n }\n\n let response = ``;\n response += `${\n typeof this._endpoint.endpoint === \"string\" ? this._endpoint.endpoint : this._endpoint.endpoint.name\n }`;\n if (this._endpoint.id) response += `/${this._endpoint.id}`;\n if (this._endpoint.childEndpoint) {\n response += `/${\n typeof this._endpoint.childEndpoint === \"string\"\n ? this._endpoint.childEndpoint\n : this._endpoint.childEndpoint.name\n }`;\n }\n if (this._endpoint.childId) response += `/${this._endpoint.childId}`;\n if (additionalParams) response += `?${additionalParams}`;\n\n return response;\n }\n}\n","import { AbstractApiData } from \"../../../core/abstracts/AbstractApiData\";\nimport { JsonApiHydratedDataInterface } from \"../../../core/interfaces/JsonApiHydratedDataInterface\";\nimport { RootSyncEntry, RootSyncInterface, RootSyncLink } from \"./RootSyncInterface\";\n\n/**\n * Child path of the sync answer under the root module record\n * (`GET /<root endpoint>/:id/sync`), the same value as the app API's sync meta endpoint\n * (in Wyrdli, `campaignSyncMeta.endpoint`).\n */\nexport const ROOT_SYNC_ENDPOINT = \"sync\";\n\n/** The sync answer for one root record (`root-syncs`, id = root record id). Read-only. */\nexport class RootSync extends AbstractApiData implements RootSyncInterface {\n private _serverTime?: Date;\n private _locked: boolean = false;\n private _lockedFrom?: Date;\n private _entries?: RootSyncEntry[];\n private _links?: RootSyncLink[];\n\n get serverTime(): Date {\n if (!this._serverTime) throw new Error(\"serverTime is not set.\");\n return this._serverTime;\n }\n\n get locked(): boolean {\n return this._locked;\n }\n\n get lockedFrom(): Date | undefined {\n return this._lockedFrom;\n }\n\n get entries(): RootSyncEntry[] {\n return this._entries ?? [];\n }\n\n get links(): RootSyncLink[] {\n return this._links ?? [];\n }\n\n rehydrate(data: JsonApiHydratedDataInterface): this {\n super.rehydrate(data);\n\n const attributes = data.jsonApi.attributes ?? {};\n this._serverTime = attributes.serverTime ? new Date(attributes.serverTime) : undefined;\n this._locked = Boolean(attributes.locked);\n this._lockedFrom = attributes.lockedFrom ? new Date(attributes.lockedFrom) : undefined;\n this._entries = (attributes.entries ?? []).map((entry: { type: string; id: string; updatedAt: string }) => ({\n type: entry.type,\n id: entry.id,\n updatedAt: new Date(entry.updatedAt),\n }));\n this._links = (attributes.links ?? []).map((link: RootSyncLink) => ({\n fromType: link.fromType,\n fromId: link.fromId,\n toType: link.toType,\n toId: link.toId,\n kind: link.kind,\n props: link.props ?? {},\n }));\n\n return this;\n }\n\n createJsonApi(_data?: any): any {\n throw new Error(\"RootSync is read-only and cannot be created\");\n }\n}\n"]}
@@ -225,6 +225,10 @@ function refreshOfflineDeviceState() {
225
225
  });
226
226
  }
227
227
  __name(refreshOfflineDeviceState, "refreshOfflineDeviceState");
228
+ function rootKinds(config) {
229
+ return [{ module: config.rootModule, listSyncRoots: config.listSyncRoots }, ...config.extraRootKinds ?? []];
230
+ }
231
+ __name(rootKinds, "rootKinds");
228
232
  function getOfflineConfig() {
229
233
  if (!_config) throw new Error("Offline mode is not configured. Call configureOffline() first.");
230
234
  return _config;
@@ -306,6 +310,7 @@ export {
306
310
  setOfflineEnabledOnDevice,
307
311
  writeOfflineLastSync,
308
312
  refreshOfflineDeviceState,
313
+ rootKinds,
309
314
  getOfflineConfig,
310
315
  setDefaultDeviceStoreOpener,
311
316
  getSqliteModuleUrl,
@@ -314,4 +319,4 @@ export {
314
319
  getOfflineStore,
315
320
  forgetOfflineStore
316
321
  };
317
- //# sourceMappingURL=chunk-27LQDGNP.mjs.map
322
+ //# sourceMappingURL=chunk-4ZJIUTIV.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/offline/state.ts","../src/offline/types.ts","../src/offline/config.ts"],"sourcesContent":["// Kept free of React: `directFetch` (every entry, server ones included) imports this module.\n// The hooks live in state-hooks.ts, exported only from the `./offline` entry.\n\nexport type OfflineState = {\n online: boolean;\n pending: number;\n conflicts: number;\n draining: boolean;\n lockedRootIds: string[];\n /**\n * False once this browser was found unable to keep the device copy (no secure context, no\n * private file storage, or the worker reports the OPFS APIs missing). Offline mode is then off\n * for the rest of the page: `isOfflineConfigured()` answers false and nothing offline runs.\n */\n available: boolean;\n /**\n * Offline mode is on on this device for the signed-in user. Always true once configured\n * without `OfflineConfig.requireOptIn`; otherwise the GM's per-device switch.\n */\n enabled: boolean;\n /** The running full sync: root records done out of the total, null when no sync runs. */\n syncProgress: { done: number; total: number } | null;\n /** When the last full sync on this device finished (epoch ms), null when never. */\n lastSyncedAt: number | null;\n /** How many root records the last full sync kept on this device, null when unknown. */\n rootCount: number | null;\n};\n\nexport const SERVER_SNAPSHOT: OfflineState = {\n online: true,\n pending: 0,\n conflicts: 0,\n draining: false,\n lockedRootIds: [],\n available: true,\n enabled: false,\n syncProgress: null,\n lastSyncedAt: null,\n rootCount: null,\n};\n\nlet _state: OfflineState = { ...SERVER_SNAPSHOT };\nconst _listeners = new Set<(s: OfflineState) => void>();\nlet _detachBrowserEvents: (() => void) | null = null;\n\nexport function getOfflineState(): OfflineState {\n return _state;\n}\n\nexport function subscribeOfflineState(listener: (s: OfflineState) => void): () => void {\n _listeners.add(listener);\n return () => {\n _listeners.delete(listener);\n };\n}\n\nfunction sameValue(a: unknown, b: unknown): boolean {\n if (Array.isArray(a) && Array.isArray(b)) {\n return a.length === b.length && a.every((value, index) => value === b[index]);\n }\n return a === b;\n}\n\n// A reconnect attempt: a probe reached the API while the session is offline. The session stays\n// offline (spec § 4: offline \"until a sync succeeds\") while the drain and the sync run; their\n// reads and the change-set request go to the network meanwhile (`reachesNetworkWhileOffline`).\n// Any network failure (`online: false` set again) ends the attempt.\nlet _reconnecting = false;\nconst _passThroughUrls = new Set<string>();\n\n/** Whether a reconnect attempt (drain then sync, after a probe reached the API) is running. */\nexport function isReconnecting(): boolean {\n return _reconnecting;\n}\n\n/** Starts or ends a reconnect attempt (the offline runtime). */\nexport function setReconnecting(value: boolean): void {\n _reconnecting = value;\n if (!value) _passThroughUrls.clear();\n}\n\n/** Lets one write (the drain's change-set request) reach the network during a reconnect attempt. */\nexport function allowWhileReconnecting(url: string): () => void {\n _passThroughUrls.add(url);\n return () => {\n _passThroughUrls.delete(url);\n };\n}\n\n/**\n * While the session is offline, whether a request still goes to the network: only during a\n * reconnect attempt, for a GET or a write the attempt let through. Any other write stays local\n * (queued), so it is sent after the waiting changes, in order.\n */\nexport function reachesNetworkWhileOffline(method: string, url: string): boolean {\n if (!_reconnecting) return false;\n return method.toUpperCase() === \"GET\" || _passThroughUrls.has(url);\n}\n\n/** The sync and the drain may talk to the API: online, or during a reconnect attempt. */\nexport function canReachApi(): boolean {\n return _state.online || _reconnecting;\n}\n\n/** Applies a partial change. Listeners run once, and only when a value actually changed. */\nexport function setOfflineState(patch: Partial<OfflineState>): void {\n if (patch.online === false) setReconnecting(false);\n const changed = (Object.keys(patch) as (keyof OfflineState)[]).some(\n (key) => patch[key] !== undefined && !sameValue(patch[key], _state[key]),\n );\n if (!changed) return;\n\n _state = { ..._state, ...patch };\n for (const listener of [..._listeners]) listener(_state);\n}\n\n/**\n * Follows the browser's offline event. Called by `configureOffline`, never at import, so an app\n * that does not opt in gets no listener. The browser's online event alone never brings the\n * session back online (spec § 4: offline \"until a sync succeeds\"): the runtime probes the API on\n * that event and goes online only when the probe reaches it.\n */\nexport function attachBrowserOnlineEvents(): void {\n if (_detachBrowserEvents || typeof window === \"undefined\") return;\n\n if (typeof navigator !== \"undefined\" && typeof navigator.onLine === \"boolean\") {\n setOfflineState({ online: navigator.onLine });\n }\n\n const onOffline = () => setOfflineState({ online: false });\n window.addEventListener(\"offline\", onOffline);\n _detachBrowserEvents = () => {\n window.removeEventListener(\"offline\", onOffline);\n };\n}\n\n/** Test helper: back to the initial state, browser events detached, listeners kept. */\nexport function resetOfflineState(): void {\n _detachBrowserEvents?.();\n _detachBrowserEvents = null;\n setReconnecting(false);\n _state = { ...SERVER_SNAPSHOT };\n}\n","import type { ApiRequestDataTypeInterface } from \"../core/interfaces/ApiRequestDataTypeInterface\";\nimport type { DeviceStore, StoredRecord } from \"./store/DeviceStore\";\n\n/** Header of a request the server runs as an offline replay. Never answered locally. */\nexport const OFFLINE_REPLAY_HEADER = \"x-offline-replay\";\n\nexport type OfflineMethod = \"GET\" | \"POST\" | \"PUT\" | \"PATCH\" | \"DELETE\";\n\n/** A Module (matched by its endpoint), a \":param\" capture, or a literal segment (\"playing\", \"merge\"). */\nexport type PatternSegment = ApiRequestDataTypeInterface | string;\n\n/** `url` (beyond the contract, optional): the absolute URL the request was made to, for the `links` of a list. */\nexport type OfflineRequest = { method: OfflineMethod; path: string; query: URLSearchParams; body?: any; url?: string };\n\n/** `body` is a JSON:API document, `undefined` for a 204. */\nexport type OfflineAnswer = { status: number; body: any };\n\nexport type LocalAnswerContext = { request: OfflineRequest; params: Record<string, string>; store: DeviceStore };\n\nexport type LocalAnswer = (ctx: LocalAnswerContext) => Promise<OfflineAnswer>;\n\nexport type OfflineRoute = { method: OfflineMethod; pattern: PatternSegment[]; answer: LocalAnswer; queue: boolean };\n\n/**\n * A type the API reads only as a list per target record: each changed record's target is the\n * other end of its sync link of `linkKind` (from the record to the target), and `endpoint`\n * builds that target's list path with `EndpointCreator`.\n */\nexport type OfflineLinkedListFetch = {\n linkKind: string;\n endpoint: (rootId: string, target: { type: string; id: string }) => string;\n};\n\n/** One more kind of root record beside `rootModule` (e.g. a notebook). Optional. */\nexport type OfflineRootKind = {\n /** The module of the root records of this kind. Sync reads `{module}/:rootId/sync`. */\n module: ApiRequestDataTypeInterface;\n /** The ids of the roots of this kind to keep on the device. Throw to keep the device copy unchanged. */\n listSyncRoots: () => Promise<string[]>;\n /**\n * Per record type, the full list endpoint (query string included) that downloads every record of\n * that type under one root of this kind, built from the stored root record. Replaces the type's\n * `fetch` mode under this kind only. Never given `updatedSince`.\n */\n typeEndpoints?: {\n module: ApiRequestDataTypeInterface;\n endpoint: (root: { id: string; resource: StoredRecord[\"resource\"] }) => string;\n }[];\n /** The module whose model reads this kind's sync answer. Default: the library's `RootSync` module (`root-syncs`). */\n syncModule?: ApiRequestDataTypeInterface;\n};\n\ntype LocalWriteBase = { store: DeviceStore; module: ApiRequestDataTypeInterface; id: string }; // store = the write's transaction\n\n/** What a generic local write (`afterLocalWrite`) did, inside its transaction. */\nexport type OfflineLocalWriteContext =\n | (LocalWriteBase & { method: \"POST\"; resource: StoredRecord[\"resource\"]; previous: null })\n | (LocalWriteBase & {\n method: \"PUT\" | \"PATCH\";\n resource: StoredRecord[\"resource\"];\n previous: StoredRecord[\"resource\"];\n })\n | (LocalWriteBase & { method: \"DELETE\"; resource: null; previous: StoredRecord[\"resource\"] });\n\nexport type OfflineTypeConfig = {\n module: ApiRequestDataTypeInterface;\n /**\n * How the sync fetches the type's changed records: the root record's list (`root-list`), one\n * GET per record (`by-id`), or (`linked-list`) the list of each record's target, found through\n * the sync answer's links of `linkedList.linkKind` (e.g. player notes, read per target only).\n */\n fetch: \"root-list\" | \"by-id\" | \"linked-list\";\n /** Required with `fetch: \"linked-list\"`. */\n linkedList?: OfflineLinkedListFetch;\n readOnly: boolean;\n serverOwnedFields: string[];\n /**\n * Relationship name → Neo4j relationship type (`faction` → `MEMBER_OF`). A link the device\n * writes from a request's relationships carries the mapped type, the kind synced links carry;\n * an unmapped name is stored as the name itself.\n */\n relationshipKinds?: Record<string, string>;\n /** The string attributes the server's fulltext index covers (default: every string attribute). */\n searchFields?: string[];\n /** The server's order with no `orderBy` (default `updatedAt DESC`). */\n defaultOrderBy?: string;\n /**\n * Called by the generic POST/PUT/PATCH/DELETE local answers inside the same transaction as the\n * write and the enqueue (a throw rolls both back). Never called by sync or write-through.\n */\n afterLocalWrite?: (ctx: OfflineLocalWriteContext) => Promise<void>;\n};\n\nexport type OfflineConfig = {\n getUserId: () => string | undefined;\n /**\n * Offline mode is off on each device until the user turns it on (`turnOnOffline`), stored per\n * user per device. Default (undefined/false): always on, every device keeps the copy.\n */\n requireOptIn?: boolean;\n /** The module whose records own every other record (in Wyrdli, Modules.Campaign). */\n rootModule: ApiRequestDataTypeInterface;\n types: OfflineTypeConfig[];\n routes: OfflineRoute[];\n /** Ids of the root records to keep on the device. */\n listSyncRoots: () => Promise<string[]>;\n /** More kinds of root records beside `rootModule`, each synced and kept on its own (optional). */\n extraRootKinds?: OfflineRootKind[];\n shellPath: (locale: string) => string;\n syncIntervalMs: number;\n /**\n * Where the device worker loads SQLite from at run time (default `/offline-sqlite/index.mjs`).\n * SQLite is never bundled: its own helper worker uses a computed URL that app bundlers refuse.\n * The app serves the files of `dist/offline/sqlite/` at this URL's folder.\n */\n sqliteModuleUrl?: string;\n /**\n * Where the device-copy worker is started from (default `/offline-sqlite/device-worker.mjs`).\n * It is a standalone file in `dist/offline/sqlite/`, never bundled by the app.\n */\n deviceWorkerUrl?: string;\n};\n\nexport const DEFAULT_SQLITE_MODULE_URL = \"/offline-sqlite/index.mjs\";\nexport const DEVICE_WORKER_FILE = \"device-worker.mjs\";\nexport const DEFAULT_DEVICE_WORKER_URL = `/offline-sqlite/${DEVICE_WORKER_FILE}`;\n\n/**\n * The files of `dist/offline/sqlite/` the app serves: the device worker and the SQLite files\n * copied from @sqlite.org/sqlite-wasm.\n */\nexport const OFFLINE_SQLITE_FILES = [\n DEVICE_WORKER_FILE,\n \"index.mjs\",\n \"sqlite3.wasm\",\n \"sqlite3-opfs-async-proxy.js\",\n] as const;\n\n/** Thrown by a local answer for something that only the server can do. Answered as a 503 \"needs-connection\". */\nexport class NeedsConnectionError extends Error {\n readonly status = 503;\n readonly code = \"needs-connection\";\n\n constructor(message: string = \"Needs a connection\") {\n super(message);\n this.name = \"NeedsConnectionError\";\n }\n}\n\n/** Segments joined with \"/\", modules by their endpoint. */\nexport function patternToString(pattern: PatternSegment[]): string {\n return pattern.map((segment) => (typeof segment === \"string\" ? segment : segment.name)).join(\"/\");\n}\n","import { attachBrowserOnlineEvents, getOfflineState, setOfflineState } from \"./state\";\nimport type { DeviceStore } from \"./store/DeviceStore\";\nimport {\n DEFAULT_DEVICE_WORKER_URL,\n DEFAULT_SQLITE_MODULE_URL,\n NeedsConnectionError,\n type OfflineConfig,\n type OfflineRootKind,\n} from \"./types\";\n\n// Kept free of store, worker and React imports: `directFetch` reads `isOfflineConfigured()` on\n// every request, so this module is the only offline code an app that never opts in loads.\n\nlet _config: OfflineConfig | null = null;\nlet _opener: ((userId: string) => Promise<DeviceStore>) | null = null;\n// Registered by the `./offline` entry (configure.ts), so the store code is reachable only from it.\nlet _defaultOpener: ((userId: string) => Promise<DeviceStore>) | null = null;\nconst _stores = new Map<string, Promise<DeviceStore>>();\n// Users whose device store must not be opened again (logged out) until they sign in again.\nconst _blockedUsers = new Set<string>();\n// Per user: whether offline mode is on on this device (`requireOptIn`). Read from localStorage\n// once, since `isOfflineConfigured()` runs on every request.\nconst _enabledCache = new Map<string, boolean>();\n\nconst ENABLED_KEY_PREFIX = \"nja-offline-enabled:\";\nconst LAST_SYNC_KEY_PREFIX = \"nja-offline-last-sync:\";\n\nfunction readStorage(key: string): string | null {\n try {\n return typeof localStorage === \"undefined\" ? null : localStorage.getItem(key);\n } catch {\n return null;\n }\n}\n\nfunction writeStorage(key: string, value: string | null): void {\n try {\n if (typeof localStorage === \"undefined\") return;\n if (value === null) localStorage.removeItem(key);\n else localStorage.setItem(key, value);\n } catch {\n // Storage can be blocked or full: the switch then lasts for this page only.\n }\n}\n\n/**\n * The signed-in user's device store cannot be used: it could not be opened (opfs-sahpool holds\n * one connection per origin, so a second tab cannot open it) or the user logged out. A request\n * answered from the device copy then needs a connection (503 \"needs-connection\").\n */\nexport class DeviceStoreUnavailableError extends NeedsConnectionError {\n constructor(message: string = \"The device copy is not available in this tab\") {\n super(message);\n this.name = \"DeviceStoreUnavailableError\";\n }\n}\n\n/**\n * This browser cannot keep the device copy at all: not a secure context (https or `localhost`),\n * no private file storage (`navigator.storage.getDirectory`), or the worker reports the OPFS\n * APIs missing. Offline mode switches off for the page (`markOfflineUnavailable`). A failure on\n * a browser that can keep the copy (the file held by another tab) is a `DeviceStoreUnavailableError`.\n */\nexport class OfflineUnavailableError extends DeviceStoreUnavailableError {\n constructor(reason: string) {\n super(`Offline mode isn't available in this browser: ${reason}`);\n this.name = \"OfflineUnavailableError\";\n }\n}\n\n/**\n * Switches offline mode off for this page, once: one console warning, `available: false` in the\n * offline state. From then on `isOfflineConfigured()` answers false, so no request, sync, drain,\n * write-through or lock check touches the device copy again.\n */\nexport function markOfflineUnavailable(error: OfflineUnavailableError): void {\n if (!getOfflineState().available) return;\n console.warn(`[offline] ${error.message}. Offline mode is off in this browser.`);\n setOfflineState({ available: false });\n}\n\n/** Whether this browser can keep the device copy (true until found otherwise). */\nexport function isOfflineAvailable(): boolean {\n return getOfflineState().available;\n}\n\n/** Logout: the user's store is never opened again in this page until `unblockOfflineStore`. */\nexport function blockOfflineStore(userId: string): void {\n _blockedUsers.add(userId);\n _stores.delete(userId);\n}\n\n/** A sign-in (`onUserSignedIn`): the user's store may be opened again. */\nexport function unblockOfflineStore(userId: string): void {\n _blockedUsers.delete(userId);\n}\n\nexport function isOfflineStoreBlocked(userId: string): boolean {\n return _blockedUsers.has(userId);\n}\n\n/** Opts the app into offline mode. Without this call nothing offline runs. */\nexport function configureOffline(config: OfflineConfig): void {\n _config = config;\n attachBrowserOnlineEvents();\n refreshOfflineDeviceState();\n}\n\n/**\n * Configured, the browser can keep the device copy (see `markOfflineUnavailable`), and offline\n * mode is on on this device for the signed-in user (see `requireOptIn`).\n */\nexport function isOfflineConfigured(): boolean {\n return _config !== null && isOfflineAvailable() && isOfflineEnabledOnDevice(_config.getUserId());\n}\n\n/**\n * Whether offline mode is on on this device for `userId`. Always true without\n * `OfflineConfig.requireOptIn`; otherwise the stored switch, false with no user.\n */\nexport function isOfflineEnabledOnDevice(userId?: string | null): boolean {\n if (!_config?.requireOptIn) return true;\n if (!userId) return false;\n let enabled = _enabledCache.get(userId);\n if (enabled === undefined) {\n enabled = readStorage(ENABLED_KEY_PREFIX + userId) === \"1\";\n _enabledCache.set(userId, enabled);\n }\n return enabled;\n}\n\n/** Stores the device switch for `userId` (`turnOnOffline` / `turnOffOffline`). */\nexport function setOfflineEnabledOnDevice(userId: string, enabled: boolean): void {\n writeStorage(ENABLED_KEY_PREFIX + userId, enabled ? \"1\" : null);\n _enabledCache.set(userId, enabled);\n}\n\n/** When `userId`'s last full sync on this device finished (epoch ms), or null. */\nexport function readOfflineLastSync(userId: string): number | null {\n const value = Number(readStorage(LAST_SYNC_KEY_PREFIX + userId));\n return Number.isFinite(value) && value > 0 ? value : null;\n}\n\n/** Stores, or with null removes, when `userId`'s last full sync finished. */\nexport function writeOfflineLastSync(userId: string, at: number | null): void {\n writeStorage(LAST_SYNC_KEY_PREFIX + userId, at === null ? null : String(at));\n}\n\n/**\n * Reads the device switch and the last sync time of the signed-in user into the offline state\n * (`enabled`, `lastSyncedAt`). Does nothing before `configureOffline`.\n */\nexport function refreshOfflineDeviceState(): void {\n if (!_config) return;\n const userId = _config.getUserId();\n if (userId) _enabledCache.delete(userId);\n setOfflineState({\n enabled: isOfflineEnabledOnDevice(userId),\n lastSyncedAt: userId ? readOfflineLastSync(userId) : null,\n });\n}\n\n/**\n * Every kind of root record: the primary one (`rootModule` + `listSyncRoots`) first, then\n * `extraRootKinds`. Library-internal (not exported from the entry).\n */\nexport function rootKinds(config: OfflineConfig): OfflineRootKind[] {\n return [{ module: config.rootModule, listSyncRoots: config.listSyncRoots }, ...(config.extraRootKinds ?? [])];\n}\n\nexport function getOfflineConfig(): OfflineConfig {\n if (!_config) throw new Error(\"Offline mode is not configured. Call configureOffline() first.\");\n return _config;\n}\n\n/** The browser opener, set by the `./offline` entry's `configureOffline`. */\nexport function setDefaultDeviceStoreOpener(opener: (userId: string) => Promise<DeviceStore>): void {\n _defaultOpener = opener;\n}\n\n/** The URL the device worker loads SQLite from (`OfflineConfig.sqliteModuleUrl`). */\nexport function getSqliteModuleUrl(): string {\n return _config?.sqliteModuleUrl ?? DEFAULT_SQLITE_MODULE_URL;\n}\n\n/** The URL the device worker is started from (`OfflineConfig.deviceWorkerUrl`). */\nexport function getDeviceWorkerUrl(): string {\n return _config?.deviceWorkerUrl ?? DEFAULT_DEVICE_WORKER_URL;\n}\n\n/** Replaces how a user's device store is opened (tests pass `openMemoryDeviceStore`). */\nexport function setDeviceStoreOpener(opener: ((userId: string) => Promise<DeviceStore>) | null): void {\n _opener = opener;\n _stores.clear();\n}\n\n/**\n * The signed-in user's device store, opened once per user id. Only the signed-in user's file is\n * ever opened; with no signed-in user the request needs a connection.\n */\nexport async function getOfflineStore(): Promise<DeviceStore> {\n const userId = getOfflineConfig().getUserId();\n if (!userId) throw new NeedsConnectionError(\"No signed-in user\");\n if (!isOfflineEnabledOnDevice(userId)) throw new DeviceStoreUnavailableError(\"Offline mode is off on this device\");\n if (_blockedUsers.has(userId)) throw new DeviceStoreUnavailableError(\"The device copy was deleted at logout\");\n if (!isOfflineAvailable()) throw new OfflineUnavailableError(\"it was found unable to keep the device copy\");\n\n let store = _stores.get(userId);\n if (!store) {\n const opener = _opener ?? _defaultOpener;\n if (!opener) throw new Error(\"No device store opener: configure offline mode through the ./offline entry.\");\n store = opener(userId).catch((error) => {\n if (error instanceof OfflineUnavailableError) markOfflineUnavailable(error);\n if (error instanceof NeedsConnectionError) throw error;\n console.warn(\"[offline] the device copy could not be opened\", error);\n throw new DeviceStoreUnavailableError(\n `The device copy could not be opened: ${String((error as Error)?.message ?? error)}`,\n );\n });\n _stores.set(userId, store);\n store.catch(() => _stores.delete(userId));\n }\n return store;\n}\n\n/** Forgets the opened store of a user (logout, deleted file). */\nexport function forgetOfflineStore(userId: string): void {\n _stores.delete(userId);\n}\n\n/** Test helper: back to \"not configured\". */\nexport function resetOfflineConfig(): void {\n _config = null;\n _opener = null;\n _stores.clear();\n _blockedUsers.clear();\n _enabledCache.clear();\n}\n"],"mappings":"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","names":[]}
@@ -9,7 +9,7 @@
9
9
 
10
10
 
11
11
 
12
- var _chunkMHB36MYEjs = require('./chunk-MHB36MYE.js');
12
+ var _chunkWUNSG3INjs = require('./chunk-WUNSG3IN.js');
13
13
 
14
14
 
15
15
  var _chunk7QVYU63Ejs = require('./chunk-7QVYU63E.js');
@@ -826,7 +826,7 @@ var missingDeviceStorage = /* @__PURE__ */ _chunk7QVYU63Ejs.__name.call(void 0,
826
826
  }, "missingDeviceStorage");
827
827
  var assertDeviceStorage = /* @__PURE__ */ _chunk7QVYU63Ejs.__name.call(void 0, () => {
828
828
  const reason = missingDeviceStorage();
829
- if (reason) throw new (0, _chunkMHB36MYEjs.OfflineUnavailableError)(reason);
829
+ if (reason) throw new (0, _chunkWUNSG3INjs.OfflineUnavailableError)(reason);
830
830
  }, "assertDeviceStorage");
831
831
  var OPFS_MISSING = /Missing required OPFS APIs/i;
832
832
  var defaultBackend = {
@@ -836,7 +836,7 @@ var defaultBackend = {
836
836
  return await navigator.storage.getDirectory();
837
837
  } catch (error) {
838
838
  if (_optionalChain([error, 'optionalAccess', _24 => _24.name]) === "SecurityError") {
839
- throw new (0, _chunkMHB36MYEjs.OfflineUnavailableError)("the browser refused its private file storage");
839
+ throw new (0, _chunkWUNSG3INjs.OfflineUnavailableError)("the browser refused its private file storage");
840
840
  }
841
841
  throw error;
842
842
  }
@@ -844,15 +844,15 @@ var defaultBackend = {
844
844
  openDatabase: /* @__PURE__ */ _chunk7QVYU63Ejs.__name.call(void 0, async (userId, fileName) => {
845
845
  assertDeviceStorage();
846
846
  const openLocal = /* @__PURE__ */ _chunk7QVYU63Ejs.__name.call(void 0, () => openWorkerDatabase(userId, fileName, {
847
- workerUrl: _chunkMHB36MYEjs.getDeviceWorkerUrl.call(void 0, ),
848
- sqliteModuleUrl: _chunkMHB36MYEjs.getSqliteModuleUrl.call(void 0, )
847
+ workerUrl: _chunkWUNSG3INjs.getDeviceWorkerUrl.call(void 0, ),
848
+ sqliteModuleUrl: _chunkWUNSG3INjs.getSqliteModuleUrl.call(void 0, )
849
849
  }), "openLocal");
850
850
  try {
851
851
  if (!canShareDatabase()) return await openLocal();
852
852
  return await openSharedDatabase(userId, openLocal, () => forgetClosedStore(userId));
853
853
  } catch (error) {
854
854
  if (OPFS_MISSING.test(String(_nullishCoalesce(_optionalChain([error, 'optionalAccess', _25 => _25.message]), () => ( error))))) {
855
- throw new (0, _chunkMHB36MYEjs.OfflineUnavailableError)("the browser lacks the file access the device copy needs (OPFS)");
855
+ throw new (0, _chunkWUNSG3INjs.OfflineUnavailableError)("the browser lacks the file access the device copy needs (OPFS)");
856
856
  }
857
857
  throw error;
858
858
  }
@@ -885,12 +885,12 @@ var entriesOf = /* @__PURE__ */ _chunk7QVYU63Ejs.__name.call(void 0, async (dire
885
885
  return names;
886
886
  }, "entriesOf");
887
887
  var deviceDirectory = /* @__PURE__ */ _chunk7QVYU63Ejs.__name.call(void 0, async () => {
888
- if (!_chunkMHB36MYEjs.isOfflineAvailable.call(void 0, )) return void 0;
888
+ if (!_chunkWUNSG3INjs.isOfflineAvailable.call(void 0, )) return void 0;
889
889
  try {
890
890
  return await backend.getDirectory();
891
891
  } catch (error) {
892
- if (!(error instanceof _chunkMHB36MYEjs.OfflineUnavailableError)) throw error;
893
- _chunkMHB36MYEjs.markOfflineUnavailable.call(void 0, error);
892
+ if (!(error instanceof _chunkWUNSG3INjs.OfflineUnavailableError)) throw error;
893
+ _chunkWUNSG3INjs.markOfflineUnavailable.call(void 0, error);
894
894
  return void 0;
895
895
  }
896
896
  }, "deviceDirectory");
@@ -906,16 +906,16 @@ var closeCurrent = /* @__PURE__ */ _chunk7QVYU63Ejs.__name.call(void 0, async ()
906
906
  }, "closeCurrent");
907
907
  function openDeviceStore(userId) {
908
908
  if (!userId) return Promise.reject(new Error("openDeviceStore needs the signed-in user id."));
909
- if (_chunkMHB36MYEjs.isOfflineStoreBlocked.call(void 0, userId)) {
910
- return Promise.reject(new (0, _chunkMHB36MYEjs.DeviceStoreUnavailableError)("The device copy was deleted at logout"));
909
+ if (_chunkWUNSG3INjs.isOfflineStoreBlocked.call(void 0, userId)) {
910
+ return Promise.reject(new (0, _chunkWUNSG3INjs.DeviceStoreUnavailableError)("The device copy was deleted at logout"));
911
911
  }
912
- if (!_chunkMHB36MYEjs.isOfflineAvailable.call(void 0, )) {
913
- return Promise.reject(new (0, _chunkMHB36MYEjs.OfflineUnavailableError)("it was found unable to keep the device copy"));
912
+ if (!_chunkWUNSG3INjs.isOfflineAvailable.call(void 0, )) {
913
+ return Promise.reject(new (0, _chunkWUNSG3INjs.OfflineUnavailableError)("it was found unable to keep the device copy"));
914
914
  }
915
915
  if (_optionalChain([current, 'optionalAccess', _35 => _35.userId]) === userId) return current.store;
916
916
  const previous = closeCurrent();
917
917
  const database = previous.then(() => backend.openDatabase(userId, deviceFileName(userId))).catch((error) => {
918
- if (error instanceof _chunkMHB36MYEjs.OfflineUnavailableError) _chunkMHB36MYEjs.markOfflineUnavailable.call(void 0, error);
918
+ if (error instanceof _chunkWUNSG3INjs.OfflineUnavailableError) _chunkWUNSG3INjs.markOfflineUnavailable.call(void 0, error);
919
919
  throw error;
920
920
  });
921
921
  const store = database.then(async (opened) => {
@@ -972,8 +972,8 @@ async function openMemoryDeviceStore() {
972
972
  _chunk7QVYU63Ejs.__name.call(void 0, openMemoryDeviceStore, "openMemoryDeviceStore");
973
973
  function forgetClosedStore(userId) {
974
974
  if (_optionalChain([current, 'optionalAccess', _36 => _36.userId]) === userId) current = void 0;
975
- _chunkMHB36MYEjs.forgetOfflineStore.call(void 0, userId);
976
- _chunkMHB36MYEjs.refreshOfflineDeviceState.call(void 0, );
975
+ _chunkWUNSG3INjs.forgetOfflineStore.call(void 0, userId);
976
+ _chunkWUNSG3INjs.refreshOfflineDeviceState.call(void 0, );
977
977
  }
978
978
  _chunk7QVYU63Ejs.__name.call(void 0, forgetClosedStore, "forgetClosedStore");
979
979
  async function deleteDeviceStore(userId) {
@@ -1001,7 +1001,7 @@ async function hasUnsentChanges(userId) {
1001
1001
  }
1002
1002
  _chunk7QVYU63Ejs.__name.call(void 0, hasUnsentChanges, "hasUnsentChanges");
1003
1003
  async function onUserSignedIn(userId) {
1004
- _chunkMHB36MYEjs.unblockOfflineStore.call(void 0, userId);
1004
+ _chunkWUNSG3INjs.unblockOfflineStore.call(void 0, userId);
1005
1005
  if (current && current.userId !== userId) await closeCurrent();
1006
1006
  const directory = await deviceDirectory();
1007
1007
  if (!directory) return;
@@ -1046,4 +1046,4 @@ _chunk7QVYU63Ejs.__name.call(void 0, isRootLocked, "isRootLocked");
1046
1046
 
1047
1047
 
1048
1048
  exports.imageUrlOf = imageUrlOf; exports.cacheArtworkImage = cacheArtworkImage; exports.removeArtworkImage = removeArtworkImage; exports.deleteImagesCaches = deleteImagesCaches; exports.setDeviceStoreBackend = setDeviceStoreBackend; exports.openDeviceStore = openDeviceStore; exports.openMemoryDatabase = openMemoryDatabase; exports.openMemoryDeviceStore = openMemoryDeviceStore; exports.deleteDeviceStore = deleteDeviceStore; exports.hasUnsentChanges = hasUnsentChanges; exports.onUserSignedIn = onUserSignedIn; exports.isRootLocked = isRootLocked;
1049
- //# sourceMappingURL=chunk-PXDUJ47N.js.map
1049
+ //# sourceMappingURL=chunk-6RCZ64BQ.js.map