@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.
- package/CHANGELOG.md +25 -0
- package/dist/ai.d.cts +1 -1
- package/dist/ai.d.ts +1 -1
- package/dist/auth.cjs +179 -2
- package/dist/auth.cjs.map +1 -1
- package/dist/auth.d.cts +1 -1
- package/dist/auth.d.ts +1 -1
- package/dist/auth.mjs +179 -2
- package/dist/auth.mjs.map +1 -1
- package/dist/catalog.d.cts +1 -1
- package/dist/catalog.d.ts +1 -1
- package/dist/checkout.d.cts +1 -1
- package/dist/checkout.d.ts +1 -1
- package/dist/db-react.d.cts +1 -1
- package/dist/db-react.d.ts +1 -1
- package/dist/db.cjs +17 -0
- package/dist/db.cjs.map +1 -1
- package/dist/db.d.cts +1 -1
- package/dist/db.d.ts +1 -1
- package/dist/db.mjs +17 -1
- package/dist/db.mjs.map +1 -1
- package/dist/entitlements.d.cts +1 -1
- package/dist/entitlements.d.ts +1 -1
- package/dist/firestore-compat.d.cts +1 -1
- package/dist/firestore-compat.d.ts +1 -1
- package/dist/index.cjs +180 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.mjs +180 -3
- package/dist/index.mjs.map +1 -1
- package/dist/mocks.cjs +68 -1
- package/dist/mocks.cjs.map +1 -1
- package/dist/mocks.d.cts +17 -1
- package/dist/mocks.d.ts +17 -1
- package/dist/mocks.mjs +68 -1
- package/dist/mocks.mjs.map +1 -1
- package/dist/notifications.d.cts +1 -1
- package/dist/notifications.d.ts +1 -1
- package/dist/react.d.cts +1 -1
- package/dist/react.d.ts +1 -1
- package/dist/support.cjs +98 -1
- package/dist/support.cjs.map +1 -1
- package/dist/support.d.cts +1 -1
- package/dist/support.d.ts +1 -1
- package/dist/support.mjs +98 -1
- package/dist/support.mjs.map +1 -1
- package/dist/telemetry.d.cts +1 -1
- package/dist/telemetry.d.ts +1 -1
- package/dist/{types-DQplLXIk.d.cts → types-BoFSCHF_.d.cts} +117 -2
- package/dist/{types-DslphKIM.d.ts → types-DdJyqBy-.d.ts} +117 -2
- package/dist/usage.d.cts +1 -1
- package/dist/usage.d.ts +1 -1
- package/dist/webhooks.d.cts +1 -1
- package/dist/webhooks.d.ts +1 -1
- package/package.json +1 -1
package/dist/entitlements.d.cts
CHANGED
package/dist/entitlements.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Y as NeetruDb, E as DbCollectionRef, P as FieldSentinel, K as DbQuery } from './types-
|
|
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-
|
|
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.
|
|
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;
|