@xtr-dev/rondevu-server 0.5.22 → 0.5.25

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.
@@ -43,6 +43,7 @@ jobs:
43
43
  type=ref,event=pr
44
44
  type=semver,pattern={{version}}
45
45
  type=semver,pattern={{major}}.{{minor}}
46
+ type=raw,value=latest,enable=${{ startsWith(github.ref, 'refs/tags/v') }}
46
47
  type=sha,prefix=
47
48
 
48
49
  - name: Build and push Docker image
package/dist/index.js CHANGED
@@ -354,6 +354,38 @@ var init_memory = __esm({
354
354
  const candidates = this.iceCandidates.get(offerId);
355
355
  return candidates ? candidates.length : 0;
356
356
  }
357
+ async countOffersByTags(tags, unique = false) {
358
+ const result = /* @__PURE__ */ new Map();
359
+ if (tags.length === 0) return result;
360
+ const now = Date.now();
361
+ for (const tag of tags) {
362
+ const offerIds = this.offersByTag.get(tag);
363
+ if (!offerIds) {
364
+ result.set(tag, 0);
365
+ continue;
366
+ }
367
+ if (unique) {
368
+ const uniquePublicKeys = /* @__PURE__ */ new Set();
369
+ for (const offerId of offerIds) {
370
+ const offer = this.offers.get(offerId);
371
+ if (offer && offer.expiresAt > now && !offer.answererPublicKey) {
372
+ uniquePublicKeys.add(offer.publicKey);
373
+ }
374
+ }
375
+ result.set(tag, uniquePublicKeys.size);
376
+ } else {
377
+ let count = 0;
378
+ for (const offerId of offerIds) {
379
+ const offer = this.offers.get(offerId);
380
+ if (offer && offer.expiresAt > now && !offer.answererPublicKey) {
381
+ count++;
382
+ }
383
+ }
384
+ result.set(tag, count);
385
+ }
386
+ }
387
+ return result;
388
+ }
357
389
  // ===== Helper Methods =====
358
390
  removeOfferFromIndexes(offer) {
359
391
  const publicKeyOffers = this.offersByPublicKey.get(offer.publicKey);
@@ -793,6 +825,24 @@ var init_sqlite = __esm({
793
825
  const result = this.db.prepare("SELECT COUNT(*) as count FROM ice_candidates WHERE offer_id = ?").get(offerId);
794
826
  return result.count;
795
827
  }
828
+ async countOffersByTags(tags, unique = false) {
829
+ const result = /* @__PURE__ */ new Map();
830
+ if (tags.length === 0) return result;
831
+ const now = Date.now();
832
+ const countColumn = unique ? "COUNT(DISTINCT o.public_key)" : "COUNT(DISTINCT o.id)";
833
+ const stmt = this.db.prepare(`
834
+ SELECT ${countColumn} as count
835
+ FROM offers o, json_each(o.tags) as t
836
+ WHERE t.value = ?
837
+ AND o.expires_at > ?
838
+ AND o.answerer_public_key IS NULL
839
+ `);
840
+ for (const tag of tags) {
841
+ const row = stmt.get(tag, now);
842
+ result.set(tag, row.count);
843
+ }
844
+ return result;
845
+ }
796
846
  // ===== Helper Methods =====
797
847
  /**
798
848
  * Helper method to convert database row to Offer object
@@ -1181,6 +1231,24 @@ var init_mysql = __esm({
1181
1231
  );
1182
1232
  return Number(rows[0].count);
1183
1233
  }
1234
+ async countOffersByTags(tags, unique = false) {
1235
+ const result = /* @__PURE__ */ new Map();
1236
+ if (tags.length === 0) return result;
1237
+ const now = Date.now();
1238
+ for (const tag of tags) {
1239
+ const countColumn = unique ? "COUNT(DISTINCT public_key)" : "COUNT(DISTINCT id)";
1240
+ const [rows] = await this.pool.query(
1241
+ `SELECT ${countColumn} as count
1242
+ FROM offers
1243
+ WHERE JSON_CONTAINS(tags, ?)
1244
+ AND expires_at > ?
1245
+ AND answerer_public_key IS NULL`,
1246
+ [JSON.stringify(tag), now]
1247
+ );
1248
+ result.set(tag, Number(rows[0].count));
1249
+ }
1250
+ return result;
1251
+ }
1184
1252
  // ===== Helper Methods =====
1185
1253
  rowToOffer(row) {
1186
1254
  return {
@@ -1581,6 +1649,24 @@ var init_postgres = __esm({
1581
1649
  );
1582
1650
  return Number(result.rows[0].count);
1583
1651
  }
1652
+ async countOffersByTags(tags, unique = false) {
1653
+ const result = /* @__PURE__ */ new Map();
1654
+ if (tags.length === 0) return result;
1655
+ const now = Date.now();
1656
+ for (const tag of tags) {
1657
+ const countColumn = unique ? "COUNT(DISTINCT public_key)" : "COUNT(DISTINCT id)";
1658
+ const queryResult = await this.pool.query(
1659
+ `SELECT ${countColumn} as count
1660
+ FROM offers
1661
+ WHERE tags ? $1
1662
+ AND expires_at > $2
1663
+ AND answerer_public_key IS NULL`,
1664
+ [tag, now]
1665
+ );
1666
+ result.set(tag, Number(queryResult.rows[0].count));
1667
+ }
1668
+ return result;
1669
+ }
1584
1670
  // ===== Helper Methods =====
1585
1671
  rowToOffer(row) {
1586
1672
  return {
@@ -2365,6 +2451,22 @@ var handlers = {
2365
2451
  expiresAt: offer.expiresAt
2366
2452
  };
2367
2453
  },
2454
+ /**
2455
+ * Count available offers by tags
2456
+ */
2457
+ async countOffersByTags(params, publicKey, timestamp, signature, storage, config, request) {
2458
+ const { tags, unique } = params;
2459
+ const tagsValidation = validateTags(tags);
2460
+ if (!tagsValidation.valid) {
2461
+ throw new RpcError(ErrorCodes.INVALID_TAG, tagsValidation.error || "Invalid tags");
2462
+ }
2463
+ const counts = await storage.countOffersByTags(tags, unique === true);
2464
+ const result = {};
2465
+ for (const [tag, count] of counts) {
2466
+ result[tag] = count;
2467
+ }
2468
+ return { counts: result };
2469
+ },
2368
2470
  /**
2369
2471
  * Publish offers with tags
2370
2472
  */
@@ -2661,7 +2763,7 @@ var handlers = {
2661
2763
  };
2662
2764
  }
2663
2765
  };
2664
- var UNAUTHENTICATED_METHODS = /* @__PURE__ */ new Set(["discover"]);
2766
+ var UNAUTHENTICATED_METHODS = /* @__PURE__ */ new Set(["discover", "countOffersByTags"]);
2665
2767
  async function handleRpc(requests, ctx, storage, config) {
2666
2768
  const responses = [];
2667
2769
  const clientIp = ctx.req.header("cf-connecting-ip") || ctx.req.header("x-real-ip") || ctx.req.header("x-forwarded-for")?.split(",")[0].trim() || void 0;
@@ -2898,7 +3000,7 @@ function createApp(storage, config) {
2898
3000
  }
2899
3001
 
2900
3002
  // src/config.ts
2901
- var BUILD_VERSION = true ? "aa71918" : "unknown";
3003
+ var BUILD_VERSION = true ? "33a7f9c" : "unknown";
2902
3004
  function loadConfig() {
2903
3005
  function parsePositiveInt(value, defaultValue, name, min = 1) {
2904
3006
  const parsed = parseInt(value || defaultValue, 10);
@@ -2948,8 +3050,8 @@ var CONFIG_DEFAULTS = {
2948
3050
  offerDefaultTtl: 6e4,
2949
3051
  offerMaxTtl: 864e5,
2950
3052
  offerMinTtl: 6e4,
2951
- answeredOfferTtl: 3e4,
2952
- // 30 seconds TTL after offer is answered
3053
+ answeredOfferTtl: 6e4,
3054
+ // 60 seconds TTL after offer is answered
2953
3055
  cleanupInterval: 6e4,
2954
3056
  maxOffersPerRequest: 100,
2955
3057
  maxBatchSize: 100,