bff-store 0.1.0 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. package/.claude/settings.local.json +14 -1
  2. package/README.md +196 -63
  3. package/dist/cli.js +11 -9
  4. package/dist/index.d.mts +48 -1
  5. package/dist/index.d.ts +48 -1
  6. package/dist/index.mjs +88 -10
  7. package/dist/package.json +3 -6
  8. package/dist/server/entry.d.mts +1 -1
  9. package/dist/server/entry.d.ts +1 -1
  10. package/dist/server/entry.js +31992 -23
  11. package/dist/server/entry.mjs +32016 -13
  12. package/dist/{server-V7WCW4ZB.mjs → server-2WMLXQ23.mjs} +11 -9
  13. package/dist/storage/jsonl-entry.js +1 -1
  14. package/dist/storage/jsonl-entry.mjs +1 -1
  15. package/dist/storage/mongodb-entry.js +31986 -10
  16. package/dist/storage/mongodb-entry.mjs +32008 -8
  17. package/docs/BUG_FIX_MONGODB_CHILD_PROCESS.md +129 -0
  18. package/docs/FRONTEND_BACKEND_ISOLATION.md +150 -0
  19. package/docs/IMPLEMENTATION_OVERVIEW.md +231 -0
  20. package/docs/LOCAL_LINK_STRATEGIES.md +117 -0
  21. package/docs/bugs/01-server-async-startup.high.md +34 -0
  22. package/docs/bugs/03-storage-cache-eviction.md +40 -0
  23. package/docs/bugs/04-http-error-body-loss.md +38 -0
  24. package/docs/bugs/05-debouncer-ms-ignored.md +41 -0
  25. package/docs/bugs/07-jsonl-key-collision.high.md +31 -0
  26. package/docs/bugs/08-dead-code-getStorageForRequest.md +18 -0
  27. package/docs/bugs/09-waitForLoad-infinite.md +37 -0
  28. package/docs/bugs/10-parseBody-silent-failure.md +32 -0
  29. package/docs/bugs/11-mongodb-storage-leak.high.md +35 -0
  30. package/docs/bugs/12-setEntityId-stale-closure.high.md +35 -0
  31. package/docs/bugs/14-dead-code-isServerRunning.md +18 -0
  32. package/docs/bugs/15-unmount-data-loss.md +37 -0
  33. package/docs/bugs/17-unused-parameter.md +26 -0
  34. package/docs/bugs/18-storage-get-silent-error.md +28 -0
  35. package/docs/bugs/README.md +35 -0
  36. package/package.json +3 -6
  37. package/src/atomCreator.ts +10 -2
  38. package/src/createStore.ts +19 -1
  39. package/src/debouncer.ts +5 -2
  40. package/src/environment.ts +11 -0
  41. package/src/index.ts +8 -1
  42. package/src/nodeStore.ts +86 -0
  43. package/src/server/handlers.ts +7 -24
  44. package/src/server/index.ts +0 -4
  45. package/src/storage/adapters/remoteStorage.ts +2 -1
  46. package/src/storage/jsonl.ts +3 -1
  47. package/src/storage/mongodb.ts +6 -6
  48. package/src/storage/transport.ts +24 -3
  49. package/tests/storage/jsonl.test.ts +18 -2
  50. package/tsconfig.json +1 -0
  51. package/docs/BUG_DIAGNOSIS_REMOTE_STORAGE_OPTIONS.md +0 -104
  52. package/docs/BUG_FIX_REMOTE_STORAGE_OPTIONS.md +0 -63
  53. package/docs/BUG_FIX_SESSION_2026-06-03.md +0 -171
  54. /package/docs/{SIDECAR_SERVER.md → BFF_SIDECAR_SERVER.md} +0 -0
@@ -29,12 +29,11 @@ async function mongodbStorage(options) {
29
29
  },
30
30
  async set(key, value) {
31
31
  const collection = getCollection(currentEntityId);
32
- await collection.insertOne({
33
- key,
34
- value,
35
- timestamp: Date.now(),
36
- entityId: currentEntityId
37
- });
32
+ await collection.updateOne(
33
+ { key, entityId: currentEntityId },
34
+ { $set: { value, timestamp: Date.now() } },
35
+ { upsert: true }
36
+ );
38
37
  },
39
38
  async remove(key) {
40
39
  const collection = getCollection(currentEntityId);
@@ -137,7 +136,7 @@ function jsonlStorage(options) {
137
136
  const baseDir = options?.dir ?? "./sessions";
138
137
  let entityId = "default";
139
138
  function getFilePath(eId, key) {
140
- const safeKey = key.replace(/[^a-zA-Z0-9_]/g, "_");
139
+ const safeKey = encodeURIComponent(key);
141
140
  return path.join(baseDir, eId, `${safeKey}.jsonl`);
142
141
  }
143
142
  const storage = {
@@ -285,7 +284,7 @@ async function getCachedStorage(config, entityId) {
285
284
  }
286
285
  return entry.adapter.storage;
287
286
  }
288
- if (storageCache.size >= MAX_CACHE_SIZE) {
287
+ while (storageCache.size >= MAX_CACHE_SIZE && storageCache.size > 0) {
289
288
  let oldestKey = null;
290
289
  let oldestTime = Infinity;
291
290
  for (const [k, entry] of storageCache.entries()) {
@@ -296,6 +295,8 @@ async function getCachedStorage(config, entityId) {
296
295
  }
297
296
  if (oldestKey) {
298
297
  storageCache.delete(oldestKey);
298
+ } else {
299
+ break;
299
300
  }
300
301
  }
301
302
  let adapter;
@@ -328,6 +329,7 @@ function createStorageHandlers(options) {
328
329
  try {
329
330
  body = await parseBody(req);
330
331
  } catch {
332
+ console.warn("[bff-store] Failed to parse request body, using URL config only");
331
333
  }
332
334
  }
333
335
  const config = body ? {
@@ -403,7 +405,7 @@ function createStorageHandlers(options) {
403
405
  res.writeHead(200);
404
406
  res.end(JSON.stringify({ success: true }));
405
407
  }
406
- async function handleHealth(req, res) {
408
+ async function handleHealth(_req, res) {
407
409
  res.setHeader("Content-Type", "application/json");
408
410
  res.writeHead(200);
409
411
  res.end(JSON.stringify({ status: "ok" }));
@@ -42,7 +42,7 @@ function jsonlStorage(options) {
42
42
  const baseDir = options?.dir ?? "./sessions";
43
43
  let entityId = "default";
44
44
  function getFilePath(eId, key) {
45
- const safeKey = key.replace(/[^a-zA-Z0-9_]/g, "_");
45
+ const safeKey = encodeURIComponent(key);
46
46
  return path.join(baseDir, eId, `${safeKey}.jsonl`);
47
47
  }
48
48
  const storage = {
@@ -5,7 +5,7 @@ function jsonlStorage(options) {
5
5
  const baseDir = options?.dir ?? "./sessions";
6
6
  let entityId = "default";
7
7
  function getFilePath(eId, key) {
8
- const safeKey = key.replace(/[^a-zA-Z0-9_]/g, "_");
8
+ const safeKey = encodeURIComponent(key);
9
9
  return path.join(baseDir, eId, `${safeKey}.jsonl`);
10
10
  }
11
11
  const storage = {