@neetru/sdk 3.3.0 → 3.4.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.
Files changed (56) hide show
  1. package/CHANGELOG.md +25 -0
  2. package/dist/ai.d.cts +1 -1
  3. package/dist/ai.d.ts +1 -1
  4. package/dist/auth.cjs +179 -2
  5. package/dist/auth.cjs.map +1 -1
  6. package/dist/auth.d.cts +1 -1
  7. package/dist/auth.d.ts +1 -1
  8. package/dist/auth.mjs +179 -2
  9. package/dist/auth.mjs.map +1 -1
  10. package/dist/catalog.d.cts +1 -1
  11. package/dist/catalog.d.ts +1 -1
  12. package/dist/checkout.d.cts +1 -1
  13. package/dist/checkout.d.ts +1 -1
  14. package/dist/db-react.d.cts +1 -1
  15. package/dist/db-react.d.ts +1 -1
  16. package/dist/db.cjs +17 -0
  17. package/dist/db.cjs.map +1 -1
  18. package/dist/db.d.cts +1 -1
  19. package/dist/db.d.ts +1 -1
  20. package/dist/db.mjs +17 -1
  21. package/dist/db.mjs.map +1 -1
  22. package/dist/entitlements.d.cts +1 -1
  23. package/dist/entitlements.d.ts +1 -1
  24. package/dist/firestore-compat.d.cts +1 -1
  25. package/dist/firestore-compat.d.ts +1 -1
  26. package/dist/index.cjs +180 -3
  27. package/dist/index.cjs.map +1 -1
  28. package/dist/index.d.cts +2 -2
  29. package/dist/index.d.ts +2 -2
  30. package/dist/index.mjs +180 -3
  31. package/dist/index.mjs.map +1 -1
  32. package/dist/mocks.cjs +68 -1
  33. package/dist/mocks.cjs.map +1 -1
  34. package/dist/mocks.d.cts +17 -1
  35. package/dist/mocks.d.ts +17 -1
  36. package/dist/mocks.mjs +68 -1
  37. package/dist/mocks.mjs.map +1 -1
  38. package/dist/notifications.d.cts +1 -1
  39. package/dist/notifications.d.ts +1 -1
  40. package/dist/react.d.cts +1 -1
  41. package/dist/react.d.ts +1 -1
  42. package/dist/support.cjs +98 -1
  43. package/dist/support.cjs.map +1 -1
  44. package/dist/support.d.cts +1 -1
  45. package/dist/support.d.ts +1 -1
  46. package/dist/support.mjs +98 -1
  47. package/dist/support.mjs.map +1 -1
  48. package/dist/telemetry.d.cts +1 -1
  49. package/dist/telemetry.d.ts +1 -1
  50. package/dist/{types-DQplLXIk.d.cts → types-BoFSCHF_.d.cts} +117 -2
  51. package/dist/{types-DslphKIM.d.ts → types-DdJyqBy-.d.ts} +117 -2
  52. package/dist/usage.d.cts +1 -1
  53. package/dist/usage.d.ts +1 -1
  54. package/dist/webhooks.d.cts +1 -1
  55. package/dist/webhooks.d.ts +1 -1
  56. package/package.json +1 -1
@@ -1,4 +1,4 @@
1
- import { ag as ResolvedConfig, O as EntitlementCheck } from './types-DQplLXIk.cjs';
1
+ import { ag as ResolvedConfig, O as EntitlementCheck } from './types-BoFSCHF_.cjs';
2
2
  import 'drizzle-orm/node-postgres';
3
3
  import './errors.cjs';
4
4
 
@@ -1,4 +1,4 @@
1
- import { ag as ResolvedConfig, O as EntitlementCheck } from './types-DslphKIM.js';
1
+ import { ag as ResolvedConfig, O as EntitlementCheck } from './types-DdJyqBy-.js';
2
2
  import 'drizzle-orm/node-postgres';
3
3
  import './errors.js';
4
4
 
@@ -1,4 +1,4 @@
1
- import { Y as NeetruDb, E as DbCollectionRef, P as FieldSentinel, K as DbQuery } from './types-DQplLXIk.cjs';
1
+ import { Y as NeetruDb, E as DbCollectionRef, P as FieldSentinel, K as DbQuery } from './types-BoFSCHF_.cjs';
2
2
  import 'drizzle-orm/node-postgres';
3
3
  import './errors.cjs';
4
4
 
@@ -1,4 +1,4 @@
1
- import { Y as NeetruDb, E as DbCollectionRef, P as FieldSentinel, K as DbQuery } from './types-DslphKIM.js';
1
+ import { Y as NeetruDb, E as DbCollectionRef, P as FieldSentinel, K as DbQuery } from './types-DdJyqBy-.js';
2
2
  import 'drizzle-orm/node-postgres';
3
3
  import './errors.js';
4
4
 
package/dist/index.cjs CHANGED
@@ -1584,6 +1584,7 @@ function toTicket(raw) {
1584
1584
  if (typeof r.id !== "string") {
1585
1585
  throw new exports.NeetruError("invalid_response", "Ticket missing id");
1586
1586
  }
1587
+ const firstAttachment = Array.isArray(r.attachments) && typeof r.attachments[0] === "string" ? r.attachments[0] : void 0;
1587
1588
  return {
1588
1589
  id: r.id,
1589
1590
  subject: typeof r.subject === "string" ? r.subject : "",
@@ -1592,9 +1593,28 @@ function toTicket(raw) {
1592
1593
  status: VALID_STATUSES.includes(r.status) ? r.status : "open",
1593
1594
  createdAt: typeof r.createdAt === "string" ? r.createdAt : (/* @__PURE__ */ new Date()).toISOString(),
1594
1595
  updatedAt: typeof r.updatedAt === "string" ? r.updatedAt : void 0,
1595
- productSlug: typeof r.productId === "string" ? r.productId : typeof r.productSlug === "string" ? r.productSlug : void 0
1596
+ productSlug: typeof r.productId === "string" ? r.productId : typeof r.productSlug === "string" ? r.productSlug : void 0,
1597
+ pageUrl: typeof r.pageUrl === "string" ? r.pageUrl : null,
1598
+ screenshotUrl: typeof r.screenshotUrl === "string" ? r.screenshotUrl : firstAttachment ?? null,
1599
+ resolvedAt: typeof r.resolvedAt === "string" ? r.resolvedAt : null,
1600
+ resolvedNotifiedAt: typeof r.resolvedNotifiedAt === "string" ? r.resolvedNotifiedAt : null,
1601
+ satisfactionAttempts: typeof r.satisfactionAttempts === "number" && Number.isFinite(r.satisfactionAttempts) ? r.satisfactionAttempts : 0,
1602
+ lastSatisfactionAttemptAt: typeof r.lastSatisfactionAttemptAt === "string" ? r.lastSatisfactionAttemptAt : null,
1603
+ satisfiedAt: typeof r.satisfiedAt === "string" ? r.satisfiedAt : null,
1604
+ rating: typeof r.rating === "number" && Number.isFinite(r.rating) ? r.rating : null,
1605
+ satisfactionComment: typeof r.satisfactionComment === "string" ? r.satisfactionComment : null
1596
1606
  };
1597
1607
  }
1608
+ function assertTicketId(ticketId) {
1609
+ if (!ticketId || typeof ticketId !== "string") {
1610
+ throw new exports.NeetruError("validation_failed", "ticketId is required");
1611
+ }
1612
+ }
1613
+ function assertValidComment(comment) {
1614
+ if (typeof comment === "string" && comment.length > 2e3) {
1615
+ throw new exports.NeetruError("validation_failed", "comment max 2000 chars");
1616
+ }
1617
+ }
1598
1618
  function resolveProductId(config, ...candidates) {
1599
1619
  for (const c of candidates) {
1600
1620
  if (typeof c === "string" && c.length > 0) {
@@ -1651,6 +1671,15 @@ function createSupportNamespace(config) {
1651
1671
  if (input.metadata && typeof input.metadata === "object") {
1652
1672
  body.metadata = input.metadata;
1653
1673
  }
1674
+ if (typeof input.pageUrl === "string") {
1675
+ body.pageUrl = input.pageUrl;
1676
+ }
1677
+ if (typeof input.screenshotBase64 === "string") {
1678
+ body.screenshotBase64 = input.screenshotBase64;
1679
+ }
1680
+ if (typeof input.consoleLogs === "string") {
1681
+ body.consoleLogs = input.consoleLogs;
1682
+ }
1654
1683
  const raw = await httpRequest(config, {
1655
1684
  method: "POST",
1656
1685
  path: "/api/sdk/v1/support/tickets",
@@ -1676,6 +1705,74 @@ function createSupportNamespace(config) {
1676
1705
  });
1677
1706
  const list = Array.isArray(raw) ? raw : raw && typeof raw === "object" && "tickets" in raw ? raw.tickets ?? [] : [];
1678
1707
  return list.map(toTicket);
1708
+ },
1709
+ /**
1710
+ * 3.4: marca a notificação de resolução como vista (`resolvedNotifiedAt`,
1711
+ * idempotente no Core). Endpoint canonical:
1712
+ * `POST /api/sdk/v1/support/tickets/{id}/resolved-seen`.
1713
+ */
1714
+ async markResolvedSeen(ticketId) {
1715
+ assertTicketId(ticketId);
1716
+ await httpRequest(config, {
1717
+ method: "POST",
1718
+ path: `/api/sdk/v1/support/tickets/${encodeURIComponent(ticketId)}/resolved-seen`,
1719
+ requireAuth: true
1720
+ });
1721
+ },
1722
+ /**
1723
+ * 3.4: registra uma tentativa de exibição do modal de satisfação
1724
+ * (`satisfactionAttempts += 1`). Chamar no SHOW do modal, não na
1725
+ * resposta. Endpoint canonical:
1726
+ * `POST /api/sdk/v1/support/tickets/{id}/satisfaction-attempt`.
1727
+ */
1728
+ async recordSatisfactionAttempt(ticketId) {
1729
+ assertTicketId(ticketId);
1730
+ await httpRequest(config, {
1731
+ method: "POST",
1732
+ path: `/api/sdk/v1/support/tickets/${encodeURIComponent(ticketId)}/satisfaction-attempt`,
1733
+ requireAuth: true
1734
+ });
1735
+ },
1736
+ /**
1737
+ * 3.4: envia (ou pula) a avaliação de satisfação (CSAT 1-5). Endpoint
1738
+ * canonical: `POST /api/sdk/v1/support/tickets/{id}/satisfaction`.
1739
+ */
1740
+ async submitSatisfaction(input) {
1741
+ if (!input || typeof input !== "object") {
1742
+ throw new exports.NeetruError("validation_failed", "input is required");
1743
+ }
1744
+ assertTicketId(input.ticketId);
1745
+ if (input.rating !== null && input.rating !== void 0) {
1746
+ if (!Number.isInteger(input.rating) || input.rating < 1 || input.rating > 5) {
1747
+ throw new exports.NeetruError("validation_failed", "rating must be an integer 1-5 or null");
1748
+ }
1749
+ }
1750
+ assertValidComment(input.comment);
1751
+ await httpRequest(config, {
1752
+ method: "POST",
1753
+ path: `/api/sdk/v1/support/tickets/${encodeURIComponent(input.ticketId)}/satisfaction`,
1754
+ body: {
1755
+ rating: input.rating ?? null,
1756
+ comment: input.comment ?? null,
1757
+ skipped: input.skipped
1758
+ },
1759
+ requireAuth: true
1760
+ });
1761
+ },
1762
+ /**
1763
+ * 3.4: contesta um ticket resolvido — reabre e zera o ciclo de
1764
+ * satisfação/notificação. Endpoint canonical:
1765
+ * `POST /api/sdk/v1/support/tickets/{id}/contest`.
1766
+ */
1767
+ async contestTicket(ticketId, opts) {
1768
+ assertTicketId(ticketId);
1769
+ assertValidComment(opts?.comment);
1770
+ await httpRequest(config, {
1771
+ method: "POST",
1772
+ path: `/api/sdk/v1/support/tickets/${encodeURIComponent(ticketId)}/contest`,
1773
+ body: { comment: opts?.comment ?? void 0 },
1774
+ requireAuth: true
1775
+ });
1679
1776
  }
1680
1777
  };
1681
1778
  }
@@ -5107,7 +5204,20 @@ function buildTicketProvider(config, opts) {
5107
5204
  return ticket;
5108
5205
  };
5109
5206
  }
5207
+ var _hasWarnedMissingDbId = false;
5208
+ function warnMissingDbIdOnce(config, dbOpts) {
5209
+ if (_hasWarnedMissingDbId) return;
5210
+ if (dbOpts.dbId) return;
5211
+ if (config.env === "prod") return;
5212
+ if (typeof window === "undefined") return;
5213
+ if (typeof console === "undefined" || typeof console.warn !== "function") return;
5214
+ _hasWarnedMissingDbId = true;
5215
+ console.warn(
5216
+ "[neetru/sdk] client.db sem `dbId` expl\xEDcito: escritas client-side (add/set/update/remove/list) caem no datastore gen\xE9rico do Core, escopado por tenant/produto (header x-neetru-tenant) \u2014 `dbId` s\xF3 nomeia o cache offline LOCAL (IndexedDB), n\xE3o roteia nem escopa nada no servidor. Veja o JSDoc de NeetruDbOptions.dbId."
5217
+ );
5218
+ }
5110
5219
  function createNeetruDb(config, dbOpts = {}) {
5220
+ warnMissingDbIdOnce(config, dbOpts);
5111
5221
  let resolvedTransport;
5112
5222
  if (dbOpts.transport !== void 0) {
5113
5223
  resolvedTransport = dbOpts.transport;
@@ -6617,7 +6727,18 @@ var MockSupport = class {
6617
6727
  severity: input.severity ?? "normal",
6618
6728
  status: "open",
6619
6729
  createdAt: (/* @__PURE__ */ new Date()).toISOString(),
6620
- productSlug: input.productSlug
6730
+ productSlug: input.productSlug,
6731
+ // 3.4 (product-feedback): espelha o contrato — campos novos nullable,
6732
+ // populados a partir do input quando fornecidos.
6733
+ pageUrl: typeof input.pageUrl === "string" ? input.pageUrl : null,
6734
+ screenshotUrl: typeof input.screenshotBase64 === "string" ? input.screenshotBase64 : null,
6735
+ resolvedAt: null,
6736
+ resolvedNotifiedAt: null,
6737
+ satisfactionAttempts: 0,
6738
+ lastSatisfactionAttemptAt: null,
6739
+ satisfiedAt: null,
6740
+ rating: null,
6741
+ satisfactionComment: null
6621
6742
  };
6622
6743
  this._tickets.push(ticket);
6623
6744
  return ticket;
@@ -6628,6 +6749,62 @@ var MockSupport = class {
6628
6749
  }
6629
6750
  return [...this._tickets];
6630
6751
  }
6752
+ _find(ticketId) {
6753
+ if (!ticketId || typeof ticketId !== "string") {
6754
+ throw new exports.NeetruError("validation_failed", "ticketId is required");
6755
+ }
6756
+ const ticket = this._tickets.find((t) => t.id === ticketId);
6757
+ if (!ticket) {
6758
+ throw new exports.NeetruError("not_found", `ticket ${ticketId} not found`);
6759
+ }
6760
+ return ticket;
6761
+ }
6762
+ /** 3.4: espelha `markResolvedSeen` — idempotente (só seta se ainda null). */
6763
+ async markResolvedSeen(ticketId) {
6764
+ const ticket = this._find(ticketId);
6765
+ if (ticket.resolvedNotifiedAt === null) {
6766
+ ticket.resolvedNotifiedAt = (/* @__PURE__ */ new Date()).toISOString();
6767
+ }
6768
+ }
6769
+ /** 3.4: espelha `recordSatisfactionAttempt` — incrementa contador. */
6770
+ async recordSatisfactionAttempt(ticketId) {
6771
+ const ticket = this._find(ticketId);
6772
+ ticket.satisfactionAttempts += 1;
6773
+ ticket.lastSatisfactionAttemptAt = (/* @__PURE__ */ new Date()).toISOString();
6774
+ }
6775
+ /** 3.4: espelha `submitSatisfaction` — terminal, seta `satisfiedAt`. */
6776
+ async submitSatisfaction(input) {
6777
+ if (!input || typeof input !== "object") {
6778
+ throw new exports.NeetruError("validation_failed", "input is required");
6779
+ }
6780
+ if (input.rating !== null && input.rating !== void 0) {
6781
+ if (!Number.isInteger(input.rating) || input.rating < 1 || input.rating > 5) {
6782
+ throw new exports.NeetruError("validation_failed", "rating must be an integer 1-5 or null");
6783
+ }
6784
+ }
6785
+ if (typeof input.comment === "string" && input.comment.length > 2e3) {
6786
+ throw new exports.NeetruError("validation_failed", "comment max 2000 chars");
6787
+ }
6788
+ const ticket = this._find(input.ticketId);
6789
+ ticket.satisfiedAt = (/* @__PURE__ */ new Date()).toISOString();
6790
+ ticket.rating = input.rating ?? null;
6791
+ ticket.satisfactionComment = input.comment ?? null;
6792
+ }
6793
+ /** 3.4: espelha `contestTicket` — reabre e zera o ciclo de satisfação. */
6794
+ async contestTicket(ticketId, opts) {
6795
+ if (typeof opts?.comment === "string" && opts.comment.length > 2e3) {
6796
+ throw new exports.NeetruError("validation_failed", "comment max 2000 chars");
6797
+ }
6798
+ const ticket = this._find(ticketId);
6799
+ ticket.status = "open";
6800
+ ticket.resolvedAt = null;
6801
+ ticket.resolvedNotifiedAt = null;
6802
+ ticket.satisfactionAttempts = 0;
6803
+ ticket.lastSatisfactionAttemptAt = null;
6804
+ ticket.satisfiedAt = null;
6805
+ ticket.rating = null;
6806
+ ticket.satisfactionComment = null;
6807
+ }
6631
6808
  /** Test helper. */
6632
6809
  __reset() {
6633
6810
  this._tickets = [];
@@ -7664,7 +7841,7 @@ function createNeetruClient(config = {}) {
7664
7841
  init_errors();
7665
7842
  init_db_errors();
7666
7843
  init_http();
7667
- var VERSION = "3.3.0";
7844
+ var VERSION = "3.4.0";
7668
7845
 
7669
7846
  exports.DEFAULT_BASE_URL = DEFAULT_BASE_URL;
7670
7847
  exports.DEV_FIXTURE_USER = DEV_FIXTURE_USER;