fauxbase 0.5.2 → 0.5.4

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.
package/README.md CHANGED
@@ -714,6 +714,32 @@ const fb = createClient({
714
714
  });
715
715
  ```
716
716
 
717
+ ### Authentication
718
+
719
+ When `auth` is configured, STOMP automatically injects `Authorization: Bearer <token>` into connection headers. Both SSE and STOMP reconnect on login/logout so the connection always uses the current token.
720
+
721
+ ```ts
722
+ const fb = createClient({
723
+ driver: { type: 'http', baseUrl: '/api' },
724
+ services: { todo: TodoService },
725
+ auth: UserAuth,
726
+ events: {
727
+ source: {
728
+ type: 'stomp',
729
+ brokerUrl: 'wss://api.example.com/ws',
730
+ subscriptions: { '/topic/todos': 'todo' },
731
+ // No need to set connectHeaders — token is injected automatically
732
+ },
733
+ },
734
+ });
735
+
736
+ // After login, STOMP reconnects with the new token
737
+ await fb.auth.login({ email: 'alice@test.com', password: 'secret' });
738
+
739
+ // After logout, STOMP reconnects without token
740
+ fb.auth.logout();
741
+ ```
742
+
717
743
  ### Custom handlers
718
744
 
719
745
  ```ts
package/dist/index.cjs CHANGED
@@ -243,6 +243,9 @@ var Service = class {
243
243
  }
244
244
  };
245
245
  }
246
+ async request(path, options) {
247
+ return this.driver.request(this.resourceName, path, options);
248
+ }
246
249
  emitEvent(action, extra) {
247
250
  if (!this._eventBus) return;
248
251
  this._eventBus.emit({
@@ -887,6 +890,11 @@ var LocalDriver = class {
887
890
  }
888
891
  return { data: { count } };
889
892
  }
893
+ async request(_resource, _path, _options) {
894
+ throw new Error(
895
+ "service.request() is only available with the HTTP driver. Local driver does not support custom endpoints."
896
+ );
897
+ }
890
898
  // --- Seed management (synchronous) ---
891
899
  seed(resource, data, entityClass) {
892
900
  for (let i = 0; i < data.length; i++) {
@@ -1261,7 +1269,7 @@ var HttpDriver = class {
1261
1269
  }
1262
1270
  return headers;
1263
1271
  }
1264
- async request(url, options = {}, retryCount = 0) {
1272
+ async _fetch(url, options = {}, retryCount = 0) {
1265
1273
  const controller = new AbortController();
1266
1274
  const timer = setTimeout(() => controller.abort(), this.timeout);
1267
1275
  try {
@@ -1275,7 +1283,7 @@ var HttpDriver = class {
1275
1283
  if (response.status >= 500 && retryCount < this.maxRetries) {
1276
1284
  const delay = this.baseDelay * Math.pow(2, retryCount);
1277
1285
  await new Promise((r) => setTimeout(r, delay));
1278
- return this.request(url, options, retryCount + 1);
1286
+ return this._fetch(url, options, retryCount + 1);
1279
1287
  }
1280
1288
  const body = await response.json().catch(() => ({}));
1281
1289
  this.throwMappedError(response.status, body);
@@ -1313,7 +1321,7 @@ var HttpDriver = class {
1313
1321
  const params = serializeQuery(query, this.preset.query);
1314
1322
  const queryString = params.toString();
1315
1323
  const fullUrl = queryString ? `${url}?${queryString}` : url;
1316
- const raw = await this.request(fullUrl);
1324
+ const raw = await this._fetch(fullUrl);
1317
1325
  const parsed = this.preset.response.list(raw);
1318
1326
  return {
1319
1327
  items: parsed.items,
@@ -1327,12 +1335,12 @@ var HttpDriver = class {
1327
1335
  }
1328
1336
  async get(resource, id) {
1329
1337
  const url = this.buildUrl(resource, id);
1330
- const raw = await this.request(url);
1338
+ const raw = await this._fetch(url);
1331
1339
  return this.preset.response.single(raw);
1332
1340
  }
1333
1341
  async create(resource, data) {
1334
1342
  const url = this.buildUrl(resource);
1335
- const raw = await this.request(url, {
1343
+ const raw = await this._fetch(url, {
1336
1344
  method: "POST",
1337
1345
  body: JSON.stringify(data)
1338
1346
  });
@@ -1340,7 +1348,7 @@ var HttpDriver = class {
1340
1348
  }
1341
1349
  async update(resource, id, data) {
1342
1350
  const url = this.buildUrl(resource, id);
1343
- const raw = await this.request(url, {
1351
+ const raw = await this._fetch(url, {
1344
1352
  method: "PATCH",
1345
1353
  body: JSON.stringify(data)
1346
1354
  });
@@ -1348,7 +1356,7 @@ var HttpDriver = class {
1348
1356
  }
1349
1357
  async delete(resource, id) {
1350
1358
  const url = this.buildUrl(resource, id);
1351
- const raw = await this.request(url, {
1359
+ const raw = await this._fetch(url, {
1352
1360
  method: "DELETE"
1353
1361
  });
1354
1362
  return this.preset.response.single(raw);
@@ -1358,12 +1366,12 @@ var HttpDriver = class {
1358
1366
  const params = filter ? serializeQuery({ filter }, this.preset.query) : new URLSearchParams();
1359
1367
  const queryString = params.toString();
1360
1368
  const fullUrl = queryString ? `${url}?${queryString}` : url;
1361
- const raw = await this.request(fullUrl);
1369
+ const raw = await this._fetch(fullUrl);
1362
1370
  return raw.count ?? raw.data?.count ?? 0;
1363
1371
  }
1364
1372
  async bulkCreate(resource, data) {
1365
1373
  const url = `${this.buildUrl(resource)}/bulk`;
1366
- const raw = await this.request(url, {
1374
+ const raw = await this._fetch(url, {
1367
1375
  method: "POST",
1368
1376
  body: JSON.stringify(data)
1369
1377
  });
@@ -1372,7 +1380,7 @@ var HttpDriver = class {
1372
1380
  }
1373
1381
  async bulkUpdate(resource, updates) {
1374
1382
  const url = `${this.buildUrl(resource)}/bulk`;
1375
- const raw = await this.request(url, {
1383
+ const raw = await this._fetch(url, {
1376
1384
  method: "PATCH",
1377
1385
  body: JSON.stringify(updates)
1378
1386
  });
@@ -1381,12 +1389,24 @@ var HttpDriver = class {
1381
1389
  }
1382
1390
  async bulkDelete(resource, ids) {
1383
1391
  const url = `${this.buildUrl(resource)}/bulk`;
1384
- const raw = await this.request(url, {
1392
+ const raw = await this._fetch(url, {
1385
1393
  method: "DELETE",
1386
1394
  body: JSON.stringify({ ids })
1387
1395
  });
1388
1396
  return { data: { count: raw.count ?? raw.data?.count ?? ids.length } };
1389
1397
  }
1398
+ async request(resource, path, options) {
1399
+ const endpoint = this.getEndpoint(resource);
1400
+ let url = `${this.baseUrl}${endpoint}${path}`;
1401
+ if (options?.query) {
1402
+ const params = new URLSearchParams(options.query);
1403
+ url += `?${params.toString()}`;
1404
+ }
1405
+ return this._fetch(url, {
1406
+ method: options?.method ?? "POST",
1407
+ body: options?.body !== void 0 ? JSON.stringify(options.body) : void 0
1408
+ });
1409
+ }
1390
1410
  // Seed methods are no-ops for HTTP — backend owns data
1391
1411
  seed() {
1392
1412
  }