@nebulr-group/bridge-auth-core 0.1.2 → 0.4.0-beta.1

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 (132) hide show
  1. package/dist/billing/bridge-subscription.d.ts +71 -0
  2. package/dist/billing/bridge-subscription.d.ts.map +1 -0
  3. package/dist/billing/bridge-subscription.js +209 -0
  4. package/dist/billing/bridge-subscription.js.map +1 -0
  5. package/dist/billing/entitlements-store.d.ts +61 -0
  6. package/dist/billing/entitlements-store.d.ts.map +1 -0
  7. package/dist/billing/entitlements-store.js +127 -0
  8. package/dist/billing/entitlements-store.js.map +1 -0
  9. package/dist/billing/fetch-billing-state.d.ts +9 -0
  10. package/dist/billing/fetch-billing-state.d.ts.map +1 -0
  11. package/dist/billing/fetch-billing-state.js +22 -0
  12. package/dist/billing/fetch-billing-state.js.map +1 -0
  13. package/dist/billing/lock-signal.d.ts +6 -0
  14. package/dist/billing/lock-signal.d.ts.map +1 -0
  15. package/dist/billing/lock-signal.js +8 -0
  16. package/dist/billing/lock-signal.js.map +1 -0
  17. package/dist/billing/quota-store.d.ts +86 -0
  18. package/dist/billing/quota-store.d.ts.map +1 -0
  19. package/dist/billing/quota-store.js +180 -0
  20. package/dist/billing/quota-store.js.map +1 -0
  21. package/dist/billing/types.d.ts +64 -0
  22. package/dist/billing/types.d.ts.map +1 -0
  23. package/dist/billing/types.js +49 -0
  24. package/dist/billing/types.js.map +1 -0
  25. package/dist/billing/use-bridge.d.ts +131 -0
  26. package/dist/billing/use-bridge.d.ts.map +1 -0
  27. package/dist/billing/use-bridge.js +181 -0
  28. package/dist/billing/use-bridge.js.map +1 -0
  29. package/dist/bridge-auth.d.ts +39 -1
  30. package/dist/bridge-auth.d.ts.map +1 -1
  31. package/dist/bridge-auth.js +89 -6
  32. package/dist/bridge-auth.js.map +1 -1
  33. package/dist/direct-auth.d.ts +1 -0
  34. package/dist/direct-auth.d.ts.map +1 -1
  35. package/dist/direct-auth.js +7 -0
  36. package/dist/direct-auth.js.map +1 -1
  37. package/dist/errors.d.ts +11 -0
  38. package/dist/errors.d.ts.map +1 -1
  39. package/dist/errors.js +14 -0
  40. package/dist/errors.js.map +1 -1
  41. package/dist/flags/attribute-providers.d.ts +229 -0
  42. package/dist/flags/attribute-providers.d.ts.map +1 -0
  43. package/dist/flags/attribute-providers.js +375 -0
  44. package/dist/flags/attribute-providers.js.map +1 -0
  45. package/dist/flags/dev-attribute-provider.d.ts +67 -0
  46. package/dist/flags/dev-attribute-provider.d.ts.map +1 -0
  47. package/dist/flags/dev-attribute-provider.js +200 -0
  48. package/dist/flags/dev-attribute-provider.js.map +1 -0
  49. package/dist/flags/evaluator.d.ts +58 -0
  50. package/dist/flags/evaluator.d.ts.map +1 -0
  51. package/dist/flags/evaluator.js +160 -0
  52. package/dist/flags/evaluator.js.map +1 -0
  53. package/dist/flags/flag.d.ts +199 -0
  54. package/dist/flags/flag.d.ts.map +1 -0
  55. package/dist/flags/flag.js +337 -0
  56. package/dist/flags/flag.js.map +1 -0
  57. package/dist/flags/identity.d.ts +77 -0
  58. package/dist/flags/identity.d.ts.map +1 -0
  59. package/dist/flags/identity.js +134 -0
  60. package/dist/flags/identity.js.map +1 -0
  61. package/dist/flags/index.d.ts +20 -0
  62. package/dist/flags/index.d.ts.map +1 -0
  63. package/dist/flags/index.js +21 -0
  64. package/dist/flags/index.js.map +1 -0
  65. package/dist/flags/operators.d.ts +63 -0
  66. package/dist/flags/operators.d.ts.map +1 -0
  67. package/dist/flags/operators.js +299 -0
  68. package/dist/flags/operators.js.map +1 -0
  69. package/dist/flags/propagation.d.ts +16 -0
  70. package/dist/flags/propagation.d.ts.map +1 -0
  71. package/dist/flags/propagation.js +107 -0
  72. package/dist/flags/propagation.js.map +1 -0
  73. package/dist/flags/realtime.d.ts +353 -0
  74. package/dist/flags/realtime.d.ts.map +1 -0
  75. package/dist/flags/realtime.js +779 -0
  76. package/dist/flags/realtime.js.map +1 -0
  77. package/dist/flags/runtime-mode.d.ts +32 -0
  78. package/dist/flags/runtime-mode.d.ts.map +1 -0
  79. package/dist/flags/runtime-mode.js +84 -0
  80. package/dist/flags/runtime-mode.js.map +1 -0
  81. package/dist/flags/telemetry.d.ts +79 -0
  82. package/dist/flags/telemetry.d.ts.map +1 -0
  83. package/dist/flags/telemetry.js +286 -0
  84. package/dist/flags/telemetry.js.map +1 -0
  85. package/dist/http.d.ts +4 -0
  86. package/dist/http.d.ts.map +1 -1
  87. package/dist/http.js +44 -12
  88. package/dist/http.js.map +1 -1
  89. package/dist/index.d.ts +14 -2
  90. package/dist/index.d.ts.map +1 -1
  91. package/dist/index.js +16 -1
  92. package/dist/index.js.map +1 -1
  93. package/dist/management-types.d.ts +38 -0
  94. package/dist/management-types.d.ts.map +1 -1
  95. package/dist/route-guard.d.ts.map +1 -1
  96. package/dist/route-guard.js +15 -5
  97. package/dist/route-guard.js.map +1 -1
  98. package/dist/token-manager.d.ts +3 -1
  99. package/dist/token-manager.d.ts.map +1 -1
  100. package/dist/token-manager.js +10 -6
  101. package/dist/token-manager.js.map +1 -1
  102. package/dist/types.d.ts +10 -2
  103. package/dist/types.d.ts.map +1 -1
  104. package/dist/usage/index.d.ts +3 -0
  105. package/dist/usage/index.d.ts.map +1 -0
  106. package/dist/usage/index.js +4 -0
  107. package/dist/usage/index.js.map +1 -0
  108. package/dist/usage/storage/durable-storage.d.ts +47 -0
  109. package/dist/usage/storage/durable-storage.d.ts.map +1 -0
  110. package/dist/usage/storage/durable-storage.js +27 -0
  111. package/dist/usage/storage/durable-storage.js.map +1 -0
  112. package/dist/usage/storage/index.d.ts +7 -0
  113. package/dist/usage/storage/index.d.ts.map +1 -0
  114. package/dist/usage/storage/index.js +28 -0
  115. package/dist/usage/storage/index.js.map +1 -0
  116. package/dist/usage/storage/indexeddb-storage.d.ts +18 -0
  117. package/dist/usage/storage/indexeddb-storage.d.ts.map +1 -0
  118. package/dist/usage/storage/indexeddb-storage.js +159 -0
  119. package/dist/usage/storage/indexeddb-storage.js.map +1 -0
  120. package/dist/usage/storage/node-fs-storage.d.ts +29 -0
  121. package/dist/usage/storage/node-fs-storage.d.ts.map +1 -0
  122. package/dist/usage/storage/node-fs-storage.js +180 -0
  123. package/dist/usage/storage/node-fs-storage.js.map +1 -0
  124. package/dist/usage/storage/noop-storage.d.ts +17 -0
  125. package/dist/usage/storage/noop-storage.d.ts.map +1 -0
  126. package/dist/usage/storage/noop-storage.js +67 -0
  127. package/dist/usage/storage/noop-storage.js.map +1 -0
  128. package/dist/usage/usage-reporter.d.ts +64 -0
  129. package/dist/usage/usage-reporter.d.ts.map +1 -0
  130. package/dist/usage/usage-reporter.js +234 -0
  131. package/dist/usage/usage-reporter.js.map +1 -0
  132. package/package.json +2 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/usage/storage/index.ts"],"names":[],"mappings":"AAAA,yDAAyD;AACzD,EAAE;AACF,4DAA4D;AAC5D,iCAAiC;AACjC,8BAA8B;AAC9B,sDAAsD;AACtD,EAAE;AACF,2EAA2E;AAC3E,4EAA4E;AAC5E,2EAA2E;AAC3E,wEAAwE;AACxE,WAAW;AAEX,OAAO,EACL,YAAY,EACZ,SAAS,GAGV,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAEpD,OAAO,EAIL,gBAAgB,EAChB,YAAY,EACZ,SAAS,GACV,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAEpD,MAAM,UAAU,oBAAoB,CAAC,OAA8B,EAAE;IACnE,IAAI,YAAY,EAAE;QAAE,OAAO,IAAI,gBAAgB,CAAC,IAAI,CAAC,CAAC;IACtD,IAAI,SAAS,EAAE;QAAE,OAAO,IAAI,aAAa,CAAC,IAAI,CAAC,CAAC;IAChD,OAAO,IAAI,eAAe,CAAC,IAAI,CAAC,CAAC;AACnC,CAAC"}
@@ -0,0 +1,18 @@
1
+ import { type DurableStorage, type DurableStorageOptions, type QueuedEvent } from './durable-storage.js';
2
+ export declare class IndexedDBStorage implements DurableStorage {
3
+ private _dbPromise?;
4
+ private maxSize;
5
+ constructor(opts?: DurableStorageOptions);
6
+ enqueue(event: QueuedEvent): Promise<void>;
7
+ peek(limit: number): Promise<QueuedEvent[]>;
8
+ remove(keys: string[]): Promise<void>;
9
+ markRetry(key: string, error: string): Promise<void>;
10
+ size(): Promise<number>;
11
+ configure(opts: {
12
+ maxSize?: number;
13
+ }): void;
14
+ close(): Promise<void>;
15
+ private _db;
16
+ private _enforceMaxSize;
17
+ }
18
+ //# sourceMappingURL=indexeddb-storage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"indexeddb-storage.d.ts","sourceRoot":"","sources":["../../../src/usage/storage/indexeddb-storage.ts"],"names":[],"mappings":"AAkBA,OAAO,EAGL,KAAK,cAAc,EACnB,KAAK,qBAAqB,EAC1B,KAAK,WAAW,EACjB,MAAM,sBAAsB,CAAC;AAM9B,qBAAa,gBAAiB,YAAW,cAAc;IACrD,OAAO,CAAC,UAAU,CAAC,CAAuB;IAC1C,OAAO,CAAC,OAAO,CAAS;gBAEZ,IAAI,GAAE,qBAA0B;IAStC,OAAO,CAAC,KAAK,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC;IAc1C,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC;IAa3C,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAarC,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAuBpD,IAAI,IAAI,OAAO,CAAC,MAAM,CAAC;IAW7B,SAAS,CAAC,IAAI,EAAE;QAAE,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI;IAMrC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAO5B,OAAO,CAAC,GAAG;YAmBG,eAAe;CA0B9B"}
@@ -0,0 +1,159 @@
1
+ // Billing 2.0 US-19 (TBP-270) — IndexedDB-backed `DurableStorage` (browser).
2
+ //
3
+ // Single object store `usage_queue` keyed on `idempotencyKey`. Uses the raw
4
+ // IndexedDB API directly to avoid pulling `idb` (or any other dep) into
5
+ // auth-core's tree.
6
+ //
7
+ // Schema versioning: v1 — single store, key-path `idempotencyKey`. If we
8
+ // ever change shape we bump the DB version and add an `onupgradeneeded`
9
+ // migration. v1 is intentionally minimal.
10
+ //
11
+ // Concurrency: each call opens a fresh transaction. The DB handle is cached
12
+ // across calls (`_dbPromise`). IndexedDB itself serializes transactions.
13
+ //
14
+ // Tree-shake isolation: this file references `indexedDB` / `IDBDatabase`
15
+ // directly — bundlers MUST NOT include this in Node-only builds. The
16
+ // factory in `./index.ts` is the only consumer; `node-fs-storage.ts` lives
17
+ // in a sibling file so the two never share a module graph.
18
+ import { DEFAULT_MAX_SIZE, isBrowserEnv, } from './durable-storage.js';
19
+ const DB_NAME = 'bridge-usage-queue';
20
+ const DB_VERSION = 1;
21
+ const STORE_NAME = 'usage_queue';
22
+ export class IndexedDBStorage {
23
+ _dbPromise;
24
+ maxSize;
25
+ constructor(opts = {}) {
26
+ if (!isBrowserEnv()) {
27
+ throw new Error('[bridge-usage] IndexedDBStorage requires a browser environment (window + indexedDB).');
28
+ }
29
+ this.maxSize = opts.maxSize ?? DEFAULT_MAX_SIZE;
30
+ }
31
+ async enqueue(event) {
32
+ const db = await this._db();
33
+ await new Promise((resolve, reject) => {
34
+ const tx = db.transaction(STORE_NAME, 'readwrite');
35
+ const store = tx.objectStore(STORE_NAME);
36
+ // `put` upserts on the idempotencyKey — same key = same logical event.
37
+ store.put(event);
38
+ tx.oncomplete = () => resolve();
39
+ tx.onerror = () => reject(tx.error ?? new Error('enqueue tx failed'));
40
+ tx.onabort = () => reject(tx.error ?? new Error('enqueue tx aborted'));
41
+ });
42
+ await this._enforceMaxSize();
43
+ }
44
+ async peek(limit) {
45
+ if (limit <= 0)
46
+ return [];
47
+ const db = await this._db();
48
+ const events = await new Promise((resolve, reject) => {
49
+ const tx = db.transaction(STORE_NAME, 'readonly');
50
+ const store = tx.objectStore(STORE_NAME);
51
+ const req = store.getAll();
52
+ req.onsuccess = () => resolve((req.result ?? []));
53
+ req.onerror = () => reject(req.error ?? new Error('peek failed'));
54
+ });
55
+ return events.sort((a, b) => a.enqueuedAt - b.enqueuedAt).slice(0, limit);
56
+ }
57
+ async remove(keys) {
58
+ if (keys.length === 0)
59
+ return;
60
+ const db = await this._db();
61
+ await new Promise((resolve, reject) => {
62
+ const tx = db.transaction(STORE_NAME, 'readwrite');
63
+ const store = tx.objectStore(STORE_NAME);
64
+ for (const k of keys)
65
+ store.delete(k);
66
+ tx.oncomplete = () => resolve();
67
+ tx.onerror = () => reject(tx.error ?? new Error('remove tx failed'));
68
+ tx.onabort = () => reject(tx.error ?? new Error('remove tx aborted'));
69
+ });
70
+ }
71
+ async markRetry(key, error) {
72
+ const db = await this._db();
73
+ await new Promise((resolve, reject) => {
74
+ const tx = db.transaction(STORE_NAME, 'readwrite');
75
+ const store = tx.objectStore(STORE_NAME);
76
+ const getReq = store.get(key);
77
+ getReq.onsuccess = () => {
78
+ const existing = getReq.result;
79
+ if (!existing) {
80
+ resolve();
81
+ return;
82
+ }
83
+ existing.retryCount = (existing.retryCount ?? 0) + 1;
84
+ existing.lastError = error;
85
+ store.put(existing);
86
+ };
87
+ getReq.onerror = () => reject(getReq.error ?? new Error('markRetry get failed'));
88
+ tx.oncomplete = () => resolve();
89
+ tx.onerror = () => reject(tx.error ?? new Error('markRetry tx failed'));
90
+ tx.onabort = () => reject(tx.error ?? new Error('markRetry tx aborted'));
91
+ });
92
+ }
93
+ async size() {
94
+ const db = await this._db();
95
+ return new Promise((resolve, reject) => {
96
+ const tx = db.transaction(STORE_NAME, 'readonly');
97
+ const store = tx.objectStore(STORE_NAME);
98
+ const req = store.count();
99
+ req.onsuccess = () => resolve(req.result ?? 0);
100
+ req.onerror = () => reject(req.error ?? new Error('size failed'));
101
+ });
102
+ }
103
+ configure(opts) {
104
+ if (typeof opts.maxSize === 'number' && opts.maxSize > 0) {
105
+ this.maxSize = opts.maxSize;
106
+ }
107
+ }
108
+ async close() {
109
+ if (!this._dbPromise)
110
+ return;
111
+ const db = await this._dbPromise;
112
+ db.close();
113
+ this._dbPromise = undefined;
114
+ }
115
+ _db() {
116
+ if (!this._dbPromise) {
117
+ this._dbPromise = new Promise((resolve, reject) => {
118
+ const req = indexedDB.open(DB_NAME, DB_VERSION);
119
+ req.onupgradeneeded = () => {
120
+ const db = req.result;
121
+ if (!db.objectStoreNames.contains(STORE_NAME)) {
122
+ db.createObjectStore(STORE_NAME, { keyPath: 'idempotencyKey' });
123
+ }
124
+ };
125
+ req.onsuccess = () => resolve(req.result);
126
+ req.onerror = () => reject(req.error ?? new Error('IndexedDB open failed'));
127
+ req.onblocked = () => reject(new Error('IndexedDB open blocked (another tab holds an older version)'));
128
+ });
129
+ }
130
+ return this._dbPromise;
131
+ }
132
+ async _enforceMaxSize() {
133
+ const currentSize = await this.size();
134
+ if (currentSize <= this.maxSize)
135
+ return;
136
+ const overflow = currentSize - this.maxSize;
137
+ // Read all, sort by enqueuedAt, drop the oldest N.
138
+ const db = await this._db();
139
+ const oldestKeys = await new Promise((resolve, reject) => {
140
+ const tx = db.transaction(STORE_NAME, 'readonly');
141
+ const store = tx.objectStore(STORE_NAME);
142
+ const req = store.getAll();
143
+ req.onsuccess = () => {
144
+ const all = (req.result ?? [])
145
+ .sort((a, b) => a.enqueuedAt - b.enqueuedAt)
146
+ .slice(0, overflow)
147
+ .map((e) => e.idempotencyKey);
148
+ resolve(all);
149
+ };
150
+ req.onerror = () => reject(req.error ?? new Error('enforceMaxSize getAll failed'));
151
+ });
152
+ if (oldestKeys.length === 0)
153
+ return;
154
+ await this.remove(oldestKeys);
155
+ // eslint-disable-next-line no-console
156
+ console.warn(`[bridge-usage] queue at max-size (${this.maxSize}); dropping oldest event`);
157
+ }
158
+ }
159
+ //# sourceMappingURL=indexeddb-storage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"indexeddb-storage.js","sourceRoot":"","sources":["../../../src/usage/storage/indexeddb-storage.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,29 @@
1
+ import { type DurableStorage, type DurableStorageOptions, type QueuedEvent } from './durable-storage.js';
2
+ export declare class NodeFsStorage implements DurableStorage {
3
+ private maxSize;
4
+ private dirPromise?;
5
+ private writeChain;
6
+ private fsP?;
7
+ private pathP?;
8
+ private osP?;
9
+ private readonly explicitDir?;
10
+ constructor(opts?: DurableStorageOptions);
11
+ enqueue(event: QueuedEvent): Promise<void>;
12
+ peek(limit: number): Promise<QueuedEvent[]>;
13
+ remove(keys: string[]): Promise<void>;
14
+ markRetry(key: string, error: string): Promise<void>;
15
+ size(): Promise<number>;
16
+ configure(opts: {
17
+ maxSize?: number;
18
+ }): void;
19
+ close(): Promise<void>;
20
+ private _serialize;
21
+ private _readAll;
22
+ private _enforceMaxSizeLocked;
23
+ private _files;
24
+ private _fs;
25
+ private _path;
26
+ private _os;
27
+ private _dir;
28
+ }
29
+ //# sourceMappingURL=node-fs-storage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"node-fs-storage.d.ts","sourceRoot":"","sources":["../../../src/usage/storage/node-fs-storage.ts"],"names":[],"mappings":"AAqBA,OAAO,EAGL,KAAK,cAAc,EACnB,KAAK,qBAAqB,EAC1B,KAAK,WAAW,EACjB,MAAM,sBAAsB,CAAC;AAM9B,qBAAa,aAAc,YAAW,cAAc;IAClD,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,UAAU,CAAC,CAAkB;IACrC,OAAO,CAAC,UAAU,CAAuC;IACzD,OAAO,CAAC,GAAG,CAAC,CAAoB;IAChC,OAAO,CAAC,KAAK,CAAC,CAAsB;IACpC,OAAO,CAAC,GAAG,CAAC,CAAoB;IAChC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAS;gBAE1B,IAAI,GAAE,qBAA0B;IAUtC,OAAO,CAAC,KAAK,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC;IAS1C,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC;IAM3C,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAYrC,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAkBpD,IAAI,IAAI,OAAO,CAAC,MAAM,CAAC;IAK7B,SAAS,CAAC,IAAI,EAAE;QAAE,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI;IAMrC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAO5B,OAAO,CAAC,UAAU;YAOJ,QAAQ;YA8BR,qBAAqB;YAcrB,MAAM;IAOpB,OAAO,CAAC,GAAG;IAKX,OAAO,CAAC,KAAK;IAKb,OAAO,CAAC,GAAG;IAKX,OAAO,CAAC,IAAI;CAab"}
@@ -0,0 +1,180 @@
1
+ // Billing 2.0 US-19 (TBP-270) — Filesystem-backed `DurableStorage` (Node).
2
+ //
3
+ // Stores the queue as JSON Lines (`.jsonl`) under a configurable directory
4
+ // (default `~/.bridge/usage-queue/queue.jsonl`).
5
+ //
6
+ // Design choices (v1):
7
+ // - Append-only writes for `enqueue` (cheap, durable).
8
+ // - `remove` rewrites the whole file without the removed keys. Acceptable
9
+ // for v1 — the queue rarely exceeds a few KB in practice. If it ever
10
+ // gets large enough that rewrites hurt, we can switch to SQLite (better-
11
+ // sqlite3) or a tombstone scheme.
12
+ // - `peek` reads + parses the file each call. Same v1 trade-off.
13
+ // - Concurrency safety inside a single process: an in-memory promise chain
14
+ // serializes all writes. We do NOT attempt multi-process locking — bridge
15
+ // SDK consumers run a single process per app instance.
16
+ //
17
+ // Tree-shake isolation: this file uses `node:fs/promises` and `node:path` via
18
+ // `await import()` so bundlers that target the browser can statically prove
19
+ // the module never executes the imports. The IndexedDB sibling never reaches
20
+ // into this file's graph.
21
+ import { DEFAULT_MAX_SIZE, isNodeEnv, } from './durable-storage.js';
22
+ export class NodeFsStorage {
23
+ maxSize;
24
+ dirPromise;
25
+ writeChain = Promise.resolve();
26
+ fsP;
27
+ pathP;
28
+ osP;
29
+ explicitDir;
30
+ constructor(opts = {}) {
31
+ if (!isNodeEnv()) {
32
+ throw new Error('[bridge-usage] NodeFsStorage requires a Node environment (process.versions.node).');
33
+ }
34
+ this.maxSize = opts.maxSize ?? DEFAULT_MAX_SIZE;
35
+ this.explicitDir = opts.nodeDir;
36
+ }
37
+ async enqueue(event) {
38
+ await this._serialize(async () => {
39
+ const { fs, file } = await this._files();
40
+ const line = JSON.stringify(event) + '\n';
41
+ await fs.appendFile(file, line, 'utf8');
42
+ await this._enforceMaxSizeLocked();
43
+ });
44
+ }
45
+ async peek(limit) {
46
+ if (limit <= 0)
47
+ return [];
48
+ const events = await this._readAll();
49
+ return events.sort((a, b) => a.enqueuedAt - b.enqueuedAt).slice(0, limit);
50
+ }
51
+ async remove(keys) {
52
+ if (keys.length === 0)
53
+ return;
54
+ const dropSet = new Set(keys);
55
+ await this._serialize(async () => {
56
+ const { fs, file } = await this._files();
57
+ const events = await this._readAll();
58
+ const kept = events.filter((e) => !dropSet.has(e.idempotencyKey));
59
+ const body = kept.map((e) => JSON.stringify(e)).join('\n');
60
+ await fs.writeFile(file, body.length > 0 ? body + '\n' : '', 'utf8');
61
+ });
62
+ }
63
+ async markRetry(key, error) {
64
+ await this._serialize(async () => {
65
+ const { fs, file } = await this._files();
66
+ const events = await this._readAll();
67
+ let touched = false;
68
+ for (const e of events) {
69
+ if (e.idempotencyKey === key) {
70
+ e.retryCount = (e.retryCount ?? 0) + 1;
71
+ e.lastError = error;
72
+ touched = true;
73
+ }
74
+ }
75
+ if (!touched)
76
+ return;
77
+ const body = events.map((e) => JSON.stringify(e)).join('\n');
78
+ await fs.writeFile(file, body.length > 0 ? body + '\n' : '', 'utf8');
79
+ });
80
+ }
81
+ async size() {
82
+ const events = await this._readAll();
83
+ return events.length;
84
+ }
85
+ configure(opts) {
86
+ if (typeof opts.maxSize === 'number' && opts.maxSize > 0) {
87
+ this.maxSize = opts.maxSize;
88
+ }
89
+ }
90
+ async close() {
91
+ // No persistent handles to close — we open/close on each call.
92
+ await this.writeChain.catch(() => undefined);
93
+ }
94
+ // --- internals ---
95
+ _serialize(fn) {
96
+ const next = this.writeChain.then(fn, fn);
97
+ // Keep the chain rejection-tolerant so one failure doesn't poison the queue.
98
+ this.writeChain = next.catch(() => undefined);
99
+ return next;
100
+ }
101
+ async _readAll() {
102
+ const { fs, file } = await this._files();
103
+ let raw;
104
+ try {
105
+ raw = await fs.readFile(file, 'utf8');
106
+ }
107
+ catch (err) {
108
+ if (err.code === 'ENOENT')
109
+ return [];
110
+ throw err;
111
+ }
112
+ if (!raw)
113
+ return [];
114
+ const out = [];
115
+ for (const line of raw.split('\n')) {
116
+ const trimmed = line.trim();
117
+ if (!trimmed)
118
+ continue;
119
+ try {
120
+ const parsed = JSON.parse(trimmed);
121
+ if (parsed &&
122
+ typeof parsed.idempotencyKey === 'string' &&
123
+ typeof parsed.metric === 'string') {
124
+ out.push(parsed);
125
+ }
126
+ }
127
+ catch {
128
+ // Skip malformed lines — better to lose one event than block the queue.
129
+ }
130
+ }
131
+ return out;
132
+ }
133
+ async _enforceMaxSizeLocked() {
134
+ const events = await this._readAll();
135
+ if (events.length <= this.maxSize)
136
+ return;
137
+ const sorted = events.sort((a, b) => a.enqueuedAt - b.enqueuedAt);
138
+ const kept = sorted.slice(sorted.length - this.maxSize);
139
+ const { fs, file } = await this._files();
140
+ const body = kept.map((e) => JSON.stringify(e)).join('\n');
141
+ await fs.writeFile(file, body.length > 0 ? body + '\n' : '', 'utf8');
142
+ // eslint-disable-next-line no-console
143
+ console.warn(`[bridge-usage] queue at max-size (${this.maxSize}); dropping oldest event`);
144
+ }
145
+ async _files() {
146
+ const fs = await this._fs();
147
+ const dir = await this._dir();
148
+ const path = await this._path();
149
+ return { fs, file: path.join(dir, 'queue.jsonl') };
150
+ }
151
+ _fs() {
152
+ if (!this.fsP)
153
+ this.fsP = import('node:fs/promises');
154
+ return this.fsP;
155
+ }
156
+ _path() {
157
+ if (!this.pathP)
158
+ this.pathP = import('node:path');
159
+ return this.pathP;
160
+ }
161
+ _os() {
162
+ if (!this.osP)
163
+ this.osP = import('node:os');
164
+ return this.osP;
165
+ }
166
+ _dir() {
167
+ if (!this.dirPromise) {
168
+ this.dirPromise = (async () => {
169
+ const fs = await this._fs();
170
+ const path = await this._path();
171
+ const os = await this._os();
172
+ const dir = this.explicitDir ?? path.join(os.homedir(), '.bridge', 'usage-queue');
173
+ await fs.mkdir(dir, { recursive: true });
174
+ return dir;
175
+ })();
176
+ }
177
+ return this.dirPromise;
178
+ }
179
+ }
180
+ //# sourceMappingURL=node-fs-storage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"node-fs-storage.js","sourceRoot":"","sources":["../../../src/usage/storage/node-fs-storage.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ import { type DurableStorage, type DurableStorageOptions, type QueuedEvent } from './durable-storage.js';
2
+ export declare class InMemoryStorage implements DurableStorage {
3
+ private readonly map;
4
+ private maxSize;
5
+ constructor(opts?: DurableStorageOptions);
6
+ enqueue(event: QueuedEvent): Promise<void>;
7
+ peek(limit: number): Promise<QueuedEvent[]>;
8
+ remove(keys: string[]): Promise<void>;
9
+ markRetry(key: string, error: string): Promise<void>;
10
+ size(): Promise<number>;
11
+ configure(opts: {
12
+ maxSize?: number;
13
+ }): void;
14
+ close(): Promise<void>;
15
+ private _enforceMaxSize;
16
+ }
17
+ //# sourceMappingURL=noop-storage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"noop-storage.d.ts","sourceRoot":"","sources":["../../../src/usage/storage/noop-storage.ts"],"names":[],"mappings":"AAOA,OAAO,EAEL,KAAK,cAAc,EACnB,KAAK,qBAAqB,EAC1B,KAAK,WAAW,EACjB,MAAM,sBAAsB,CAAC;AAE9B,qBAAa,eAAgB,YAAW,cAAc;IACpD,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAkC;IACtD,OAAO,CAAC,OAAO,CAAS;gBAEZ,IAAI,GAAE,qBAA0B;IAItC,OAAO,CAAC,KAAK,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC;IAK1C,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC;IAQ3C,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAIrC,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAOpD,IAAI,IAAI,OAAO,CAAC,MAAM,CAAC;IAI7B,SAAS,CAAC,IAAI,EAAE;QAAE,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI;IAOrC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAI5B,OAAO,CAAC,eAAe;CAmBxB"}
@@ -0,0 +1,67 @@
1
+ // Billing 2.0 US-19 (TBP-270) — In-memory `DurableStorage` impl.
2
+ //
3
+ // Used as a fallback when neither browser nor Node env is detected (SSR
4
+ // edge runtimes, sandboxed iframes with IndexedDB disabled, etc.). NOT
5
+ // durable across process crashes — but matches the API surface so the
6
+ // UsageReporter doesn't need to branch.
7
+ import { DEFAULT_MAX_SIZE, } from './durable-storage.js';
8
+ export class InMemoryStorage {
9
+ map = new Map();
10
+ maxSize;
11
+ constructor(opts = {}) {
12
+ this.maxSize = opts.maxSize ?? DEFAULT_MAX_SIZE;
13
+ }
14
+ async enqueue(event) {
15
+ this.map.set(event.idempotencyKey, event);
16
+ this._enforceMaxSize();
17
+ }
18
+ async peek(limit) {
19
+ // Iteration order on Map is insertion order, which matches enqueuedAt for
20
+ // typical use. We still sort defensively in case `enqueue` was called with
21
+ // historical timestamps (e.g. hydrated-from-elsewhere).
22
+ const all = Array.from(this.map.values()).sort((a, b) => a.enqueuedAt - b.enqueuedAt);
23
+ return all.slice(0, Math.max(0, limit));
24
+ }
25
+ async remove(keys) {
26
+ for (const k of keys)
27
+ this.map.delete(k);
28
+ }
29
+ async markRetry(key, error) {
30
+ const existing = this.map.get(key);
31
+ if (!existing)
32
+ return;
33
+ existing.retryCount += 1;
34
+ existing.lastError = error;
35
+ }
36
+ async size() {
37
+ return this.map.size;
38
+ }
39
+ configure(opts) {
40
+ if (typeof opts.maxSize === 'number' && opts.maxSize > 0) {
41
+ this.maxSize = opts.maxSize;
42
+ this._enforceMaxSize();
43
+ }
44
+ }
45
+ async close() {
46
+ // no-op
47
+ }
48
+ _enforceMaxSize() {
49
+ while (this.map.size > this.maxSize) {
50
+ // Drop oldest by enqueuedAt
51
+ let oldestKey;
52
+ let oldestTs = Number.POSITIVE_INFINITY;
53
+ for (const ev of this.map.values()) {
54
+ if (ev.enqueuedAt < oldestTs) {
55
+ oldestTs = ev.enqueuedAt;
56
+ oldestKey = ev.idempotencyKey;
57
+ }
58
+ }
59
+ if (oldestKey === undefined)
60
+ break;
61
+ this.map.delete(oldestKey);
62
+ // eslint-disable-next-line no-console
63
+ console.warn(`[bridge-usage] queue at max-size (${this.maxSize}); dropping oldest event`);
64
+ }
65
+ }
66
+ }
67
+ //# sourceMappingURL=noop-storage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"noop-storage.js","sourceRoot":"","sources":["../../../src/usage/storage/noop-storage.ts"],"names":[],"mappings":"AAAA,iEAAiE;AACjE,EAAE;AACF,wEAAwE;AACxE,uEAAuE;AACvE,sEAAsE;AACtE,wCAAwC;AAExC,OAAO,EACL,gBAAgB,GAIjB,MAAM,sBAAsB,CAAC;AAE9B,MAAM,OAAO,eAAe;IACT,GAAG,GAAG,IAAI,GAAG,EAAuB,CAAC;IAC9C,OAAO,CAAS;IAExB,YAAY,OAA8B,EAAE;QAC1C,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,OAAO,IAAI,gBAAgB,CAAC;IAClD,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,KAAkB;QAC9B,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,cAAc,EAAE,KAAK,CAAC,CAAC;QAC1C,IAAI,CAAC,eAAe,EAAE,CAAC;IACzB,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,KAAa;QACtB,0EAA0E;QAC1E,2EAA2E;QAC3E,wDAAwD;QACxD,MAAM,GAAG,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,GAAG,CAAC,CAAC,UAAU,CAAC,CAAC;QACtF,OAAO,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC;IAC1C,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,IAAc;QACzB,KAAK,MAAM,CAAC,IAAI,IAAI;YAAE,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;IAC3C,CAAC;IAED,KAAK,CAAC,SAAS,CAAC,GAAW,EAAE,KAAa;QACxC,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACnC,IAAI,CAAC,QAAQ;YAAE,OAAO;QACtB,QAAQ,CAAC,UAAU,IAAI,CAAC,CAAC;QACzB,QAAQ,CAAC,SAAS,GAAG,KAAK,CAAC;IAC7B,CAAC;IAED,KAAK,CAAC,IAAI;QACR,OAAO,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC;IACvB,CAAC;IAED,SAAS,CAAC,IAA0B;QAClC,IAAI,OAAO,IAAI,CAAC,OAAO,KAAK,QAAQ,IAAI,IAAI,CAAC,OAAO,GAAG,CAAC,EAAE,CAAC;YACzD,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC;YAC5B,IAAI,CAAC,eAAe,EAAE,CAAC;QACzB,CAAC;IACH,CAAC;IAED,KAAK,CAAC,KAAK;QACT,QAAQ;IACV,CAAC;IAEO,eAAe;QACrB,OAAO,IAAI,CAAC,GAAG,CAAC,IAAI,GAAG,IAAI,CAAC,OAAO,EAAE,CAAC;YACpC,4BAA4B;YAC5B,IAAI,SAA6B,CAAC;YAClC,IAAI,QAAQ,GAAG,MAAM,CAAC,iBAAiB,CAAC;YACxC,KAAK,MAAM,EAAE,IAAI,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,EAAE,CAAC;gBACnC,IAAI,EAAE,CAAC,UAAU,GAAG,QAAQ,EAAE,CAAC;oBAC7B,QAAQ,GAAG,EAAE,CAAC,UAAU,CAAC;oBACzB,SAAS,GAAG,EAAE,CAAC,cAAc,CAAC;gBAChC,CAAC;YACH,CAAC;YACD,IAAI,SAAS,KAAK,SAAS;gBAAE,MAAM;YACnC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;YAC3B,sCAAsC;YACtC,OAAO,CAAC,IAAI,CACV,qCAAqC,IAAI,CAAC,OAAO,0BAA0B,CAC5E,CAAC;QACJ,CAAC;IACH,CAAC;CACF"}
@@ -0,0 +1,64 @@
1
+ import { type DurableStorage } from './storage/index.js';
2
+ export interface UsageReporterOptions {
3
+ /** Bridge API base URL (e.g. https://api.thebridge.dev or http://localhost:3500). */
4
+ apiBaseUrl: string;
5
+ /** Accessor for the current user's access token. Returns null when unauthenticated. */
6
+ getAccessToken: () => string | null;
7
+ /** Optional logger. Defaults to a `console`-shaped stub that warns on failures. */
8
+ logger?: {
9
+ warn(...args: unknown[]): void;
10
+ };
11
+ /** Maximum events drained per flush. Default 10. */
12
+ batchSize?: number;
13
+ /** Debounce window before flushing the queue. Default 1000ms. */
14
+ flushIntervalMs?: number;
15
+ /** Optional fetch override — primarily for tests. */
16
+ fetchFn?: typeof fetch;
17
+ /**
18
+ * Durable storage backend. Defaults to `createDurableStorage()` which
19
+ * auto-detects browser / Node / fallback. Tests can inject `InMemoryStorage`.
20
+ */
21
+ storage?: DurableStorage;
22
+ }
23
+ export interface QueueStatus {
24
+ /** Current queue depth (events awaiting flush). */
25
+ queueDepth: number;
26
+ /** Sum of retryCount across all queued events. */
27
+ retryCount: number;
28
+ /** Unix ms of the last flush attempt (success or failure). Null if never flushed. */
29
+ lastFlushTimestamp: number | null;
30
+ /** Last error message recorded during a flush, or null if last flush was clean. */
31
+ lastFlushError: string | null;
32
+ }
33
+ export declare class UsageReporter {
34
+ private readonly apiBaseUrl;
35
+ private readonly getAccessToken;
36
+ private readonly logger;
37
+ private readonly batchSize;
38
+ private readonly flushIntervalMs;
39
+ private readonly fetchFn;
40
+ private readonly storage;
41
+ private timer;
42
+ private stopped;
43
+ private flushing;
44
+ private _lastFlushTimestamp;
45
+ private _lastFlushError;
46
+ constructor(opts: UsageReporterOptions);
47
+ /**
48
+ * Enqueue a usage event. Non-blocking — schedules a debounced flush.
49
+ * `idempotencyKey` is auto-generated via `crypto.randomUUID()` when omitted
50
+ * and persisted with the event so crash/restart replays use the SAME key.
51
+ */
52
+ report(metric: string, value?: number, idempotencyKey?: string): void;
53
+ /** Force an immediate drain of the queue. Resolves once all in-flight POSTs settle. */
54
+ flushNow(): Promise<void>;
55
+ /** Read-only queue observability — for dev-facing monitoring. */
56
+ getQueueStatus(): Promise<QueueStatus>;
57
+ /** Cancel pending timer and drain. Idempotent — safe to call multiple times. */
58
+ shutdown(): void;
59
+ private _maybeHydrate;
60
+ private _scheduleFlush;
61
+ private _flush;
62
+ private _flushInner;
63
+ }
64
+ //# sourceMappingURL=usage-reporter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"usage-reporter.d.ts","sourceRoot":"","sources":["../../src/usage/usage-reporter.ts"],"names":[],"mappings":"AAuBA,OAAO,EAEL,KAAK,cAAc,EAEpB,MAAM,oBAAoB,CAAC;AAE5B,MAAM,WAAW,oBAAoB;IACnC,qFAAqF;IACrF,UAAU,EAAE,MAAM,CAAC;IACnB,uFAAuF;IACvF,cAAc,EAAE,MAAM,MAAM,GAAG,IAAI,CAAC;IACpC,mFAAmF;IACnF,MAAM,CAAC,EAAE;QAAE,IAAI,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,CAAA;KAAE,CAAC;IAC5C,oDAAoD;IACpD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,iEAAiE;IACjE,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,qDAAqD;IACrD,OAAO,CAAC,EAAE,OAAO,KAAK,CAAC;IACvB;;;OAGG;IACH,OAAO,CAAC,EAAE,cAAc,CAAC;CAC1B;AAED,MAAM,WAAW,WAAW;IAC1B,mDAAmD;IACnD,UAAU,EAAE,MAAM,CAAC;IACnB,kDAAkD;IAClD,UAAU,EAAE,MAAM,CAAC;IACnB,qFAAqF;IACrF,kBAAkB,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,mFAAmF;IACnF,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;CAC/B;AAID,qBAAa,aAAa;IACxB,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAsB;IACrD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAqC;IAC5D,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAS;IACzC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAe;IACvC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAiB;IAEzC,OAAO,CAAC,KAAK,CAA4C;IACzD,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,QAAQ,CAA4B;IAG5C,OAAO,CAAC,mBAAmB,CAAuB;IAClD,OAAO,CAAC,eAAe,CAAuB;gBAElC,IAAI,EAAE,oBAAoB;IActC;;;;OAIG;IACI,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,GAAE,MAAU,EAAE,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI;IAkB/E,uFAAuF;IAC1E,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;IAQtC,iEAAiE;IACpD,cAAc,IAAI,OAAO,CAAC,WAAW,CAAC;IAYnD,gFAAgF;IACzE,QAAQ,IAAI,IAAI;YAeT,aAAa;IAY3B,OAAO,CAAC,cAAc;YASR,MAAM;YASN,WAAW;CAgF1B"}