kaafil-js 0.1.0 → 0.2.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.
@@ -2964,7 +2964,35 @@ var SYNC_PULL_SECTIONS = [
2964
2964
  "itinerary",
2965
2965
  "closeout"
2966
2966
  ];
2967
- function extractSectionRows(data) {
2967
+ var SECTION_ROW_KEY = {
2968
+ // Delta-shaped `rooms[]`; `windows[]`/`unassigned[]` are derived
2969
+ // projections — the long note above is still exactly right about this one.
2970
+ rooming: "rooms",
2971
+ // The same decision in the same shape: `vehicles[]` is the feed,
2972
+ // `unassignedPool[]` the projection that must never be cached as rows.
2973
+ seating: "vehicles",
2974
+ expenses: "items",
2975
+ float: "data",
2976
+ // The one that was silently dead. `sections[]` is a grouping projection and
2977
+ // `availableTemplates[]` is agency-level catalogue; `items[]` is the trip's
2978
+ // own entity list and the only one of the three carrying tombstones.
2979
+ checklist: "items",
2980
+ // `days[]` is the day-by-day projection the engine recomputes per read;
2981
+ // `items[]` is the entity list.
2982
+ itinerary: "items",
2983
+ closeout: null
2984
+ // `stayWindows`, `pickups`, `bookings` and `collections` send a top-level
2985
+ // array and never reach this table.
2986
+ };
2987
+ function extractSectionRows(data, section) {
2988
+ if (section !== void 0 && section in SECTION_ROW_KEY) {
2989
+ const key = SECTION_ROW_KEY[section];
2990
+ if (key === null || key === void 0 || typeof data !== "object" || data === null) {
2991
+ return void 0;
2992
+ }
2993
+ const value = data[key];
2994
+ return Array.isArray(value) && isRowArray(value) ? value : void 0;
2995
+ }
2968
2996
  if (Array.isArray(data)) {
2969
2997
  return isRowArray(data) ? data : void 0;
2970
2998
  }
@@ -3034,7 +3062,7 @@ function createPullCoordinator(options) {
3034
3062
  absent.push(name);
3035
3063
  continue;
3036
3064
  }
3037
- const rows = extractSectionRows(section.data);
3065
+ const rows = extractSectionRows(section.data, name);
3038
3066
  if (rows === void 0) {
3039
3067
  unmapped.push(name);
3040
3068
  continue;
@@ -3071,6 +3099,49 @@ function createPullCoordinator(options) {
3071
3099
  };
3072
3100
  }
3073
3101
 
3102
+ // src/offline/reads.ts
3103
+ function createReadCacheStore(options) {
3104
+ const key = `${options.keyPrefix}:reads`;
3105
+ let reads = /* @__PURE__ */ new Map();
3106
+ async function persist() {
3107
+ const shape = { reads: Object.fromEntries(reads) };
3108
+ await options.storage.set(key, JSON.stringify(shape));
3109
+ }
3110
+ return {
3111
+ get(readKey) {
3112
+ return reads.get(readKey);
3113
+ },
3114
+ async set(readKey, value, serverTime) {
3115
+ reads.set(readKey, { value, syncedAt: serverTime });
3116
+ await persist();
3117
+ },
3118
+ async purge(readKey) {
3119
+ if (!reads.delete(readKey)) {
3120
+ return;
3121
+ }
3122
+ await persist();
3123
+ },
3124
+ async load() {
3125
+ reads = /* @__PURE__ */ new Map();
3126
+ const raw = await options.storage.get(key);
3127
+ if (raw === void 0) {
3128
+ return;
3129
+ }
3130
+ let parsed;
3131
+ try {
3132
+ parsed = JSON.parse(raw);
3133
+ } catch {
3134
+ return;
3135
+ }
3136
+ for (const [readKey, entry] of Object.entries(parsed.reads ?? {})) {
3137
+ if (entry !== null && typeof entry === "object" && typeof entry.syncedAt === "string") {
3138
+ reads.set(readKey, entry);
3139
+ }
3140
+ }
3141
+ }
3142
+ };
3143
+ }
3144
+
3074
3145
  // src/offline/share.ts
3075
3146
  var SHARE_WRITE_GRACE_MS = 7 * 24 * 60 * 60 * 1e3;
3076
3147
  var KaafilShareLinkExpiredError = class _KaafilShareLinkExpiredError extends Error {
@@ -3445,6 +3516,7 @@ function createOfflineEngine(options) {
3445
3516
  ...options.onEventHandlerError !== void 0 ? { onHandlerError: (error) => options.onEventHandlerError?.(error) } : {}
3446
3517
  });
3447
3518
  const snapshot = createSnapshotStore({ storage: options.storage, keyPrefix });
3519
+ const reads = createReadCacheStore({ storage: options.storage, keyPrefix });
3448
3520
  const outbox = createOutbox({
3449
3521
  storage: options.storage,
3450
3522
  keyPrefix,
@@ -3517,13 +3589,19 @@ function createOfflineEngine(options) {
3517
3589
  return {
3518
3590
  events,
3519
3591
  snapshot,
3592
+ reads,
3520
3593
  outbox,
3521
3594
  drainer,
3522
3595
  pull,
3523
3596
  blobs,
3524
3597
  share,
3525
3598
  async open() {
3526
- await Promise.all([snapshot.load(), outbox.load(), blobs?.load() ?? Promise.resolve()]);
3599
+ await Promise.all([
3600
+ snapshot.load(),
3601
+ reads.load(),
3602
+ outbox.load(),
3603
+ blobs?.load() ?? Promise.resolve()
3604
+ ]);
3527
3605
  unbind = drainer.bindOpportunisticTriggers();
3528
3606
  drainer.kick();
3529
3607
  },
@@ -7511,6 +7589,7 @@ exports.createOfflineEngine = createOfflineEngine;
7511
7589
  exports.createOfflineEvents = createOfflineEvents;
7512
7590
  exports.createOutbox = createOutbox;
7513
7591
  exports.createPullCoordinator = createPullCoordinator;
7592
+ exports.createReadCacheStore = createReadCacheStore;
7514
7593
  exports.createShareGuard = createShareGuard;
7515
7594
  exports.createSnapshotStore = createSnapshotStore;
7516
7595
  exports.createSyncResource = createSyncResource;