@neetru/sdk 3.6.0 → 3.8.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 +104 -0
- package/README.md +66 -1
- package/dist/ai.cjs +298 -391
- package/dist/ai.d.cts +1 -1
- package/dist/ai.d.ts +1 -1
- package/dist/ai.mjs +298 -391
- package/dist/auth.cjs +3717 -5005
- package/dist/auth.d.cts +1 -1
- package/dist/auth.d.ts +1 -1
- package/dist/auth.mjs +3714 -5002
- package/dist/build-guard.cjs +101 -119
- package/dist/build-guard.mjs +91 -109
- package/dist/catalog.cjs +220 -225
- package/dist/catalog.d.cts +1 -1
- package/dist/catalog.d.ts +1 -1
- package/dist/catalog.mjs +220 -225
- package/dist/checkout.cjs +307 -323
- package/dist/checkout.d.cts +1 -1
- package/dist/checkout.d.ts +1 -1
- package/dist/checkout.mjs +306 -322
- package/dist/db-react.cjs +59 -87
- package/dist/db-react.d.cts +1 -1
- package/dist/db-react.d.ts +1 -1
- package/dist/db-react.mjs +56 -84
- package/dist/db.cjs +2128 -3014
- package/dist/db.d.cts +1 -1
- package/dist/db.d.ts +1 -1
- package/dist/db.mjs +2141 -3027
- package/dist/entitlements.cjs +19 -20
- package/dist/entitlements.d.cts +1 -1
- package/dist/entitlements.d.ts +1 -1
- package/dist/entitlements.mjs +19 -20
- package/dist/errors.cjs +16 -12
- package/dist/errors.d.cts +59 -3
- package/dist/errors.d.ts +59 -3
- package/dist/errors.mjs +15 -12
- package/dist/firestore-compat.cjs +241 -297
- package/dist/firestore-compat.d.cts +1 -1
- package/dist/firestore-compat.d.ts +1 -1
- package/dist/firestore-compat.mjs +215 -271
- package/dist/index.cjs +3942 -5134
- package/dist/index.d.cts +181 -5
- package/dist/index.d.ts +181 -5
- package/dist/index.mjs +4040 -5239
- package/dist/mobile.cjs +459 -344
- package/dist/mobile.d.cts +59 -4
- package/dist/mobile.d.ts +59 -4
- package/dist/mobile.mjs +459 -344
- package/dist/mocks.cjs +319 -447
- package/dist/mocks.d.cts +1 -1
- package/dist/mocks.d.ts +1 -1
- package/dist/mocks.mjs +313 -441
- package/dist/notifications.cjs +296 -317
- package/dist/notifications.d.cts +1 -1
- package/dist/notifications.d.ts +1 -1
- package/dist/notifications.mjs +295 -316
- package/dist/react.cjs +557 -707
- package/dist/react.d.cts +1 -1
- package/dist/react.d.ts +1 -1
- package/dist/react.mjs +547 -697
- package/dist/support.cjs +402 -328
- package/dist/support.d.cts +29 -3
- package/dist/support.d.ts +29 -3
- package/dist/support.mjs +401 -328
- package/dist/telemetry.cjs +267 -304
- package/dist/telemetry.d.cts +1 -1
- package/dist/telemetry.d.ts +1 -1
- package/dist/telemetry.mjs +267 -304
- package/dist/{types-Du_iioJ7.d.cts → types-D-9bjlM0.d.cts} +74 -1
- package/dist/{types-BPATkXYu.d.ts → types-bVztFQTI.d.ts} +74 -1
- package/dist/usage.cjs +233 -230
- package/dist/usage.d.cts +1 -1
- package/dist/usage.d.ts +1 -1
- package/dist/usage.mjs +233 -230
- package/dist/webhooks.cjs +328 -362
- package/dist/webhooks.d.cts +1 -1
- package/dist/webhooks.d.ts +1 -1
- package/dist/webhooks.mjs +325 -359
- package/package.json +5 -3
- package/dist/ai.cjs.map +0 -1
- package/dist/ai.mjs.map +0 -1
- package/dist/auth.cjs.map +0 -1
- package/dist/auth.mjs.map +0 -1
- package/dist/build-guard.cjs.map +0 -1
- package/dist/build-guard.mjs.map +0 -1
- package/dist/catalog.cjs.map +0 -1
- package/dist/catalog.mjs.map +0 -1
- package/dist/checkout.cjs.map +0 -1
- package/dist/checkout.mjs.map +0 -1
- package/dist/db-react.cjs.map +0 -1
- package/dist/db-react.mjs.map +0 -1
- package/dist/db.cjs.map +0 -1
- package/dist/db.mjs.map +0 -1
- package/dist/entitlements.cjs.map +0 -1
- package/dist/entitlements.mjs.map +0 -1
- package/dist/errors.cjs.map +0 -1
- package/dist/errors.mjs.map +0 -1
- package/dist/firestore-compat.cjs.map +0 -1
- package/dist/firestore-compat.mjs.map +0 -1
- package/dist/index.cjs.map +0 -1
- package/dist/index.mjs.map +0 -1
- package/dist/mobile.cjs.map +0 -1
- package/dist/mobile.mjs.map +0 -1
- package/dist/mocks.cjs.map +0 -1
- package/dist/mocks.mjs.map +0 -1
- package/dist/notifications.cjs.map +0 -1
- package/dist/notifications.mjs.map +0 -1
- package/dist/react.cjs.map +0 -1
- package/dist/react.mjs.map +0 -1
- package/dist/support.cjs.map +0 -1
- package/dist/support.mjs.map +0 -1
- package/dist/telemetry.cjs.map +0 -1
- package/dist/telemetry.mjs.map +0 -1
- package/dist/usage.cjs.map +0 -1
- package/dist/usage.mjs.map +0 -1
- package/dist/webhooks.cjs.map +0 -1
- package/dist/webhooks.mjs.map +0 -1
package/dist/mocks.cjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
// src/errors.ts
|
|
4
|
-
var
|
|
4
|
+
var l = class m extends Error {
|
|
5
5
|
code;
|
|
6
6
|
status;
|
|
7
7
|
requestId;
|
|
@@ -14,24 +14,24 @@ var NeetruError = class _NeetruError extends Error {
|
|
|
14
14
|
* para um `NeetruDbErrorCode` mais específico (recuperável vs não).
|
|
15
15
|
*/
|
|
16
16
|
reason;
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
17
|
+
/**
|
|
18
|
+
* 3.8.0: `x-correlation-id` da requisição que falhou. O SDK gera um UUID por
|
|
19
|
+
* chamada (ou usa o que o chamador passou) e manda no header; o Core grava o
|
|
20
|
+
* mesmo id nos logs/auditoria — cite-o ao abrir um ticket de suporte.
|
|
21
|
+
* `undefined` em erros que acontecem antes de qualquer requisição.
|
|
22
|
+
*/
|
|
23
|
+
correlationId;
|
|
24
|
+
constructor(e, r, i, o, a, c) {
|
|
25
|
+
super(r), this.name = "NeetruError", this.code = e, this.status = i, this.requestId = o, this.reason = a, this.correlationId = c, Object.setPrototypeOf(this, m.prototype);
|
|
25
26
|
}
|
|
26
27
|
};
|
|
27
28
|
|
|
28
29
|
// src/db-errors.ts
|
|
29
|
-
var
|
|
30
|
+
var U = /* @__PURE__ */ new Set([
|
|
30
31
|
"db_unavailable",
|
|
31
32
|
"db_conflict",
|
|
32
33
|
"db_timeout"
|
|
33
|
-
])
|
|
34
|
-
var NeetruDbError = class _NeetruDbError extends NeetruError {
|
|
34
|
+
]), _ = class m extends l {
|
|
35
35
|
/** Código de erro fechado — específico de DB. */
|
|
36
36
|
code;
|
|
37
37
|
/**
|
|
@@ -44,79 +44,60 @@ var NeetruDbError = class _NeetruDbError extends NeetruError {
|
|
|
44
44
|
* Nunca deve ser exibido ao usuário final.
|
|
45
45
|
*/
|
|
46
46
|
dbId;
|
|
47
|
-
constructor(
|
|
48
|
-
super(code,
|
|
49
|
-
this.name = "NeetruDbError";
|
|
50
|
-
this.code = code;
|
|
51
|
-
this.retryable = RETRYABLE_CODES.has(code);
|
|
52
|
-
this.dbId = dbId;
|
|
53
|
-
Object.setPrototypeOf(this, _NeetruDbError.prototype);
|
|
47
|
+
constructor(e, r, i) {
|
|
48
|
+
super(e, r), this.name = "NeetruDbError", this.code = e, this.retryable = U.has(e), this.dbId = i, Object.setPrototypeOf(this, m.prototype);
|
|
54
49
|
}
|
|
55
50
|
};
|
|
56
51
|
|
|
57
52
|
// src/runtime-env.ts
|
|
58
|
-
function
|
|
53
|
+
function R() {
|
|
59
54
|
try {
|
|
60
|
-
if (typeof process
|
|
55
|
+
if (typeof process < "u" && process.env)
|
|
61
56
|
return process.env.NODE_ENV === "production";
|
|
62
|
-
}
|
|
63
57
|
} catch {
|
|
64
58
|
}
|
|
65
59
|
return false;
|
|
66
60
|
}
|
|
67
61
|
|
|
68
62
|
// src/mocks.ts
|
|
69
|
-
var
|
|
63
|
+
var x = Object.freeze({
|
|
70
64
|
uid: "dev-fixture-uid-0001",
|
|
71
65
|
email: "dev@neetru.local",
|
|
72
66
|
emailVerified: true,
|
|
73
67
|
displayName: "Dev Fixture",
|
|
74
68
|
isCustomer: true,
|
|
75
69
|
isStaff: false
|
|
76
|
-
})
|
|
77
|
-
var MockAuth = class {
|
|
70
|
+
}), A = class {
|
|
78
71
|
_user;
|
|
79
72
|
_listeners;
|
|
80
73
|
_allowUnsignedDecode;
|
|
81
|
-
constructor(
|
|
82
|
-
this._user =
|
|
83
|
-
|
|
84
|
-
this._allowUnsignedDecode = options?.allowUnsignedDecode ?? false;
|
|
85
|
-
if (this._allowUnsignedDecode && isProductionRuntime()) {
|
|
86
|
-
throw new NeetruError(
|
|
74
|
+
constructor(e = null, r) {
|
|
75
|
+
if (this._user = e, this._listeners = /* @__PURE__ */ new Set(), this._allowUnsignedDecode = r?.allowUnsignedDecode ?? false, this._allowUnsignedDecode && R())
|
|
76
|
+
throw new l(
|
|
87
77
|
"invalid_config",
|
|
88
78
|
"MockAuth com allowUnsignedDecode=true \xE9 PROIBIDO em produ\xE7\xE3o (NODE_ENV=production): decodificar JWT sem verificar assinatura \xE9 bypass de autentica\xE7\xE3o. Este modo existe exclusivamente para testes."
|
|
89
79
|
);
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
if (!isTestEnv && typeof console !== "undefined") {
|
|
94
|
-
console.warn(
|
|
95
|
-
"[neetru-sdk] MockAuth.verifyToken est\xE1 em modo allowUnsignedDecode=true: tokens N\xC3O t\xEAm assinatura verificada. Este modo \xE9 exclusivo para testes \u2014 NUNCA use como security boundary em c\xF3digo deployado."
|
|
96
|
-
);
|
|
97
|
-
}
|
|
98
|
-
}
|
|
80
|
+
this._allowUnsignedDecode && !(typeof process < "u" && (process.env?.NODE_ENV === "test" || process.env?.VITEST === "true" || process.env?.VITEST != null)) && typeof console < "u" && console.warn(
|
|
81
|
+
"[neetru-sdk] MockAuth.verifyToken est\xE1 em modo allowUnsignedDecode=true: tokens N\xC3O t\xEAm assinatura verificada. Este modo \xE9 exclusivo para testes \u2014 NUNCA use como security boundary em c\xF3digo deployado."
|
|
82
|
+
);
|
|
99
83
|
}
|
|
100
|
-
async signIn(
|
|
101
|
-
|
|
102
|
-
this._notify();
|
|
103
|
-
return this._user;
|
|
84
|
+
async signIn(e) {
|
|
85
|
+
return this._user || (this._user = { ...x }), this._notify(), this._user;
|
|
104
86
|
}
|
|
105
87
|
async signOut() {
|
|
106
|
-
this._user = null;
|
|
107
|
-
this._notify();
|
|
88
|
+
this._user = null, this._notify();
|
|
108
89
|
}
|
|
109
90
|
getUser() {
|
|
110
91
|
return this._user;
|
|
111
92
|
}
|
|
112
|
-
onAuthStateChanged(
|
|
113
|
-
this._listeners.add(
|
|
93
|
+
onAuthStateChanged(e) {
|
|
94
|
+
this._listeners.add(e);
|
|
114
95
|
try {
|
|
115
|
-
|
|
96
|
+
e(this._user);
|
|
116
97
|
} catch {
|
|
117
98
|
}
|
|
118
99
|
return () => {
|
|
119
|
-
this._listeners.delete(
|
|
100
|
+
this._listeners.delete(e);
|
|
120
101
|
};
|
|
121
102
|
}
|
|
122
103
|
/**
|
|
@@ -129,52 +110,46 @@ var MockAuth = class {
|
|
|
129
110
|
*
|
|
130
111
|
* Para simular falhas ou resultados customizados, use `__mockVerifyToken(fn)`.
|
|
131
112
|
*/
|
|
132
|
-
async verifyToken(
|
|
133
|
-
if (this._verifyTokenOverride)
|
|
134
|
-
return this._verifyTokenOverride(
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
if (!this._allowUnsignedDecode) {
|
|
140
|
-
throw new NeetruError(
|
|
113
|
+
async verifyToken(e) {
|
|
114
|
+
if (this._verifyTokenOverride)
|
|
115
|
+
return this._verifyTokenOverride(e);
|
|
116
|
+
if (!e)
|
|
117
|
+
throw new l("token_invalid_signature", "Token inv\xE1lido: string vazia");
|
|
118
|
+
if (!this._allowUnsignedDecode)
|
|
119
|
+
throw new l(
|
|
141
120
|
"unauthorized",
|
|
142
121
|
"MockAuth.verifyToken n\xE3o verifica assinaturas JWT e N\xC3O deve ser usado como security boundary em c\xF3digo deployado. Em testes, use new MockAuth(user, { allowUnsignedDecode: true }) para habilitar decodifica\xE7\xE3o sem assinatura, ou __mockVerifyToken(fn) para injetar resultado customizado."
|
|
143
122
|
);
|
|
144
|
-
}
|
|
145
123
|
try {
|
|
146
|
-
|
|
147
|
-
if (
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
const decoded = JSON.parse(
|
|
151
|
-
typeof atob === "function" ? atob(b64 + pad) : Buffer.from(b64 + pad, "base64").toString("utf-8")
|
|
124
|
+
let r = e.split(".");
|
|
125
|
+
if (r.length === 3) {
|
|
126
|
+
let i = r[1].replace(/-/g, "+").replace(/_/g, "/"), o = "=".repeat((4 - i.length % 4) % 4), a = JSON.parse(
|
|
127
|
+
typeof atob == "function" ? atob(i + o) : Buffer.from(i + o, "base64").toString("utf-8")
|
|
152
128
|
);
|
|
153
|
-
if (typeof
|
|
129
|
+
if (typeof a.sub == "string")
|
|
154
130
|
return {
|
|
155
|
-
uid:
|
|
156
|
-
email: typeof
|
|
157
|
-
emailVerified: typeof
|
|
158
|
-
displayName: typeof
|
|
159
|
-
photoURL: typeof
|
|
160
|
-
isStaff:
|
|
161
|
-
isCustomer:
|
|
162
|
-
tenantId: typeof
|
|
163
|
-
...
|
|
131
|
+
uid: a.sub,
|
|
132
|
+
email: typeof a.email == "string" ? a.email : "",
|
|
133
|
+
emailVerified: typeof a.email_verified == "boolean" ? a.email_verified : void 0,
|
|
134
|
+
displayName: typeof a.name == "string" ? a.name : void 0,
|
|
135
|
+
photoURL: typeof a.picture == "string" ? a.picture : void 0,
|
|
136
|
+
isStaff: a.is_staff === !0,
|
|
137
|
+
isCustomer: a.is_customer === !0,
|
|
138
|
+
tenantId: typeof a.tenant_id == "string" ? a.tenant_id : void 0,
|
|
139
|
+
...a
|
|
164
140
|
};
|
|
165
|
-
}
|
|
166
141
|
}
|
|
167
142
|
} catch {
|
|
168
143
|
}
|
|
169
144
|
if (this._user) return this._user;
|
|
170
|
-
throw new
|
|
145
|
+
throw new l("token_invalid_signature", "Nenhum user mock dispon\xEDvel e JWT sem sub v\xE1lido");
|
|
171
146
|
}
|
|
172
147
|
/**
|
|
173
148
|
* Mock de `handleRedirectCallback` (Bug 2 / 3.1.3) — não há redirect real no
|
|
174
149
|
* mock, então retorna `null` por default. Use `__setPendingCallback(result)`
|
|
175
150
|
* em testes pra simular um retorno do IdP.
|
|
176
151
|
*/
|
|
177
|
-
async handleRedirectCallback(
|
|
152
|
+
async handleRedirectCallback(e) {
|
|
178
153
|
return this._pendingCallback;
|
|
179
154
|
}
|
|
180
155
|
/**
|
|
@@ -183,7 +158,7 @@ var MockAuth = class {
|
|
|
183
158
|
* contrato "no-op seguro em todo page load" da implementação real). O login
|
|
184
159
|
* mock acontece direto via `signIn()`.
|
|
185
160
|
*/
|
|
186
|
-
async completeSignIn(
|
|
161
|
+
async completeSignIn(e) {
|
|
187
162
|
return null;
|
|
188
163
|
}
|
|
189
164
|
/**
|
|
@@ -196,12 +171,12 @@ var MockAuth = class {
|
|
|
196
171
|
_pendingCallback = null;
|
|
197
172
|
_idToken = null;
|
|
198
173
|
/** Test helper — simula o material devolvido por um callback OIDC. */
|
|
199
|
-
__setPendingCallback(
|
|
200
|
-
this._pendingCallback =
|
|
174
|
+
__setPendingCallback(e) {
|
|
175
|
+
this._pendingCallback = e;
|
|
201
176
|
}
|
|
202
177
|
/** Test helper — injeta o id_token cru retornado por `getIdToken`. */
|
|
203
|
-
__setIdToken(
|
|
204
|
-
this._idToken =
|
|
178
|
+
__setIdToken(e) {
|
|
179
|
+
this._idToken = e;
|
|
205
180
|
}
|
|
206
181
|
_verifyTokenOverride = null;
|
|
207
182
|
/**
|
|
@@ -214,75 +189,63 @@ var MockAuth = class {
|
|
|
214
189
|
* mock.__mockVerifyToken(async () => { throw new NeetruError('token_expired', '...'); });
|
|
215
190
|
* ```
|
|
216
191
|
*/
|
|
217
|
-
__mockVerifyToken(
|
|
218
|
-
this._verifyTokenOverride =
|
|
192
|
+
__mockVerifyToken(e) {
|
|
193
|
+
this._verifyTokenOverride = e;
|
|
219
194
|
}
|
|
220
195
|
/** Helper de tests — força um user state arbitrário. */
|
|
221
|
-
__setUser(
|
|
222
|
-
this._user =
|
|
223
|
-
this._notify();
|
|
196
|
+
__setUser(e) {
|
|
197
|
+
this._user = e, this._notify();
|
|
224
198
|
}
|
|
225
199
|
_notify() {
|
|
226
|
-
for (
|
|
200
|
+
for (let e of this._listeners)
|
|
227
201
|
try {
|
|
228
|
-
|
|
202
|
+
e(this._user);
|
|
229
203
|
} catch {
|
|
230
204
|
}
|
|
231
|
-
}
|
|
232
205
|
}
|
|
233
|
-
}
|
|
234
|
-
var MockUsage = class {
|
|
206
|
+
}, T = class {
|
|
235
207
|
_reports = [];
|
|
236
208
|
_quotas;
|
|
237
209
|
_counters = /* @__PURE__ */ new Map();
|
|
238
|
-
constructor(
|
|
239
|
-
this._quotas = new Map(Object.entries(
|
|
240
|
-
}
|
|
241
|
-
async report(
|
|
242
|
-
if (!
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
qty: safeQty,
|
|
250
|
-
productId: options?.productId,
|
|
251
|
-
tenantId: options?.tenantId,
|
|
210
|
+
constructor(e = {}) {
|
|
211
|
+
this._quotas = new Map(Object.entries(e));
|
|
212
|
+
}
|
|
213
|
+
async report(e, r = 1, i) {
|
|
214
|
+
if (!e) throw new Error("resource required");
|
|
215
|
+
let o = Number.isFinite(r) && r > 0 ? Math.floor(r) : 1, c = (this._counters.get(e) ?? 0) + o;
|
|
216
|
+
this._counters.set(e, c), this._reports.push({
|
|
217
|
+
resource: e,
|
|
218
|
+
qty: o,
|
|
219
|
+
productId: i?.productId,
|
|
220
|
+
tenantId: i?.tenantId,
|
|
252
221
|
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
253
222
|
});
|
|
254
|
-
|
|
255
|
-
const limit = limitFixture?.limit ?? -1;
|
|
223
|
+
let d = this._quotas.get(e)?.limit ?? -1;
|
|
256
224
|
return {
|
|
257
225
|
ok: true,
|
|
258
|
-
counterId: `mock_${
|
|
259
|
-
value:
|
|
260
|
-
limit,
|
|
261
|
-
remaining:
|
|
262
|
-
status:
|
|
226
|
+
counterId: `mock_${e}`,
|
|
227
|
+
value: c,
|
|
228
|
+
limit: d,
|
|
229
|
+
remaining: d < 0 ? -1 : Math.max(0, d - c),
|
|
230
|
+
status: d > 0 && c >= d ? "read_only_overlimit" : "ok"
|
|
263
231
|
};
|
|
264
232
|
}
|
|
265
|
-
async check(
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
if (!quota) {
|
|
233
|
+
async check(e, r) {
|
|
234
|
+
let i = this._quotas.get(e), o = this._counters.get(e) ?? 0;
|
|
235
|
+
if (!i)
|
|
269
236
|
return { allowed: true, reason: "granted", limit: -1, remaining: -1, behavior: null };
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
behavior: "readonly"
|
|
279
|
-
};
|
|
280
|
-
}
|
|
281
|
-
return {
|
|
237
|
+
let a = i.limit < 0 ? -1 : Math.max(0, i.limit - o);
|
|
238
|
+
return a === 0 ? {
|
|
239
|
+
allowed: false,
|
|
240
|
+
reason: "limit_exceeded",
|
|
241
|
+
limit: i.limit,
|
|
242
|
+
remaining: 0,
|
|
243
|
+
behavior: "readonly"
|
|
244
|
+
} : {
|
|
282
245
|
allowed: true,
|
|
283
246
|
reason: "granted",
|
|
284
|
-
limit:
|
|
285
|
-
remaining,
|
|
247
|
+
limit: i.limit,
|
|
248
|
+
remaining: a,
|
|
286
249
|
behavior: null
|
|
287
250
|
};
|
|
288
251
|
}
|
|
@@ -295,40 +258,37 @@ var MockUsage = class {
|
|
|
295
258
|
return this.__getReports();
|
|
296
259
|
}
|
|
297
260
|
/** Test helper — substitui quota fixture. */
|
|
298
|
-
__setQuota(
|
|
299
|
-
this._quotas.set(
|
|
261
|
+
__setQuota(e, r) {
|
|
262
|
+
this._quotas.set(e, r);
|
|
300
263
|
}
|
|
301
264
|
/** Test helper — limpa estado. */
|
|
302
265
|
__reset() {
|
|
303
|
-
this._reports = [];
|
|
304
|
-
this._quotas.clear();
|
|
305
|
-
this._counters.clear();
|
|
266
|
+
this._reports = [], this._quotas.clear(), this._counters.clear();
|
|
306
267
|
}
|
|
307
|
-
}
|
|
308
|
-
var MockSupport = class {
|
|
268
|
+
}, P = class {
|
|
309
269
|
_tickets = [];
|
|
310
270
|
_ticketSeq = 0;
|
|
311
|
-
async createTicket(
|
|
312
|
-
if (!
|
|
313
|
-
if (!
|
|
314
|
-
if (!
|
|
315
|
-
throw new
|
|
271
|
+
async createTicket(e) {
|
|
272
|
+
if (!e?.subject) throw new l("validation_failed", "subject required");
|
|
273
|
+
if (!e?.message) throw new l("validation_failed", "message required");
|
|
274
|
+
if (!e?.productSlug)
|
|
275
|
+
throw new l(
|
|
316
276
|
"validation_failed",
|
|
317
277
|
"productSlug required (3.0 breaking \u2014 pass to input or set on createNeetruClient)"
|
|
318
278
|
);
|
|
319
|
-
|
|
320
|
-
const ticket = {
|
|
279
|
+
let r = {
|
|
321
280
|
id: `mock-ticket-${++this._ticketSeq}`,
|
|
322
|
-
subject:
|
|
323
|
-
message:
|
|
324
|
-
severity:
|
|
281
|
+
subject: e.subject,
|
|
282
|
+
message: e.message,
|
|
283
|
+
severity: e.severity ?? "normal",
|
|
325
284
|
status: "open",
|
|
326
285
|
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
327
|
-
productSlug:
|
|
286
|
+
productSlug: e.productSlug,
|
|
328
287
|
// 3.4 (product-feedback): espelha o contrato — campos novos nullable,
|
|
329
288
|
// populados a partir do input quando fornecidos.
|
|
330
|
-
pageUrl: typeof
|
|
331
|
-
screenshotUrl: typeof
|
|
289
|
+
pageUrl: typeof e.pageUrl == "string" ? e.pageUrl : null,
|
|
290
|
+
screenshotUrl: typeof e.screenshotBase64 == "string" ? e.screenshotBase64 : null,
|
|
291
|
+
screenshotAttached: typeof e.screenshotBase64 == "string",
|
|
332
292
|
resolvedAt: null,
|
|
333
293
|
resolvedNotifiedAt: null,
|
|
334
294
|
satisfactionAttempts: 0,
|
|
@@ -337,146 +297,116 @@ var MockSupport = class {
|
|
|
337
297
|
rating: null,
|
|
338
298
|
satisfactionComment: null
|
|
339
299
|
};
|
|
340
|
-
this._tickets.push(
|
|
341
|
-
return ticket;
|
|
300
|
+
return this._tickets.push(r), r;
|
|
342
301
|
}
|
|
343
|
-
async listMyTickets(
|
|
344
|
-
|
|
345
|
-
return this._tickets.filter((t) => t.productSlug === options.productSlug);
|
|
346
|
-
}
|
|
347
|
-
return [...this._tickets];
|
|
302
|
+
async listMyTickets(e) {
|
|
303
|
+
return e?.productSlug ? this._tickets.filter((r) => r.productSlug === e.productSlug) : [...this._tickets];
|
|
348
304
|
}
|
|
349
|
-
_find(
|
|
350
|
-
if (!
|
|
351
|
-
throw new
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
}
|
|
357
|
-
return ticket;
|
|
305
|
+
_find(e) {
|
|
306
|
+
if (!e || typeof e != "string")
|
|
307
|
+
throw new l("validation_failed", "ticketId is required");
|
|
308
|
+
let r = this._tickets.find((i) => i.id === e);
|
|
309
|
+
if (!r)
|
|
310
|
+
throw new l("not_found", `ticket ${e} not found`);
|
|
311
|
+
return r;
|
|
358
312
|
}
|
|
359
313
|
/** 3.4: espelha `markResolvedSeen` — idempotente (só seta se ainda null). */
|
|
360
|
-
async markResolvedSeen(
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
ticket.resolvedNotifiedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
364
|
-
}
|
|
314
|
+
async markResolvedSeen(e) {
|
|
315
|
+
let r = this._find(e);
|
|
316
|
+
r.resolvedNotifiedAt === null && (r.resolvedNotifiedAt = (/* @__PURE__ */ new Date()).toISOString());
|
|
365
317
|
}
|
|
366
318
|
/** 3.4: espelha `recordSatisfactionAttempt` — incrementa contador. */
|
|
367
|
-
async recordSatisfactionAttempt(
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
ticket.lastSatisfactionAttemptAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
319
|
+
async recordSatisfactionAttempt(e) {
|
|
320
|
+
let r = this._find(e);
|
|
321
|
+
r.satisfactionAttempts += 1, r.lastSatisfactionAttemptAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
371
322
|
}
|
|
372
323
|
/** 3.4: espelha `submitSatisfaction` — terminal, seta `satisfiedAt`. */
|
|
373
|
-
async submitSatisfaction(
|
|
374
|
-
if (!
|
|
375
|
-
throw new
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
if (typeof input.comment === "string" && input.comment.length > 2e3) {
|
|
383
|
-
throw new NeetruError("validation_failed", "comment max 2000 chars");
|
|
384
|
-
}
|
|
385
|
-
const ticket = this._find(input.ticketId);
|
|
386
|
-
ticket.satisfiedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
387
|
-
ticket.rating = input.rating ?? null;
|
|
388
|
-
ticket.satisfactionComment = input.comment ?? null;
|
|
324
|
+
async submitSatisfaction(e) {
|
|
325
|
+
if (!e || typeof e != "object")
|
|
326
|
+
throw new l("validation_failed", "input is required");
|
|
327
|
+
if (e.rating !== null && e.rating !== void 0 && (!Number.isInteger(e.rating) || e.rating < 1 || e.rating > 5))
|
|
328
|
+
throw new l("validation_failed", "rating must be an integer 1-5 or null");
|
|
329
|
+
if (typeof e.comment == "string" && e.comment.length > 2e3)
|
|
330
|
+
throw new l("validation_failed", "comment max 2000 chars");
|
|
331
|
+
let r = this._find(e.ticketId);
|
|
332
|
+
r.satisfiedAt = (/* @__PURE__ */ new Date()).toISOString(), r.rating = e.rating ?? null, r.satisfactionComment = e.comment ?? null;
|
|
389
333
|
}
|
|
390
334
|
/** 3.4: espelha `contestTicket` — reabre e zera o ciclo de satisfação. */
|
|
391
|
-
async contestTicket(
|
|
392
|
-
if (typeof
|
|
393
|
-
throw new
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
ticket.status = "open";
|
|
397
|
-
ticket.resolvedAt = null;
|
|
398
|
-
ticket.resolvedNotifiedAt = null;
|
|
399
|
-
ticket.satisfactionAttempts = 0;
|
|
400
|
-
ticket.lastSatisfactionAttemptAt = null;
|
|
401
|
-
ticket.satisfiedAt = null;
|
|
402
|
-
ticket.rating = null;
|
|
403
|
-
ticket.satisfactionComment = null;
|
|
335
|
+
async contestTicket(e, r) {
|
|
336
|
+
if (typeof r?.comment == "string" && r.comment.length > 2e3)
|
|
337
|
+
throw new l("validation_failed", "comment max 2000 chars");
|
|
338
|
+
let i = this._find(e);
|
|
339
|
+
i.status = "open", i.resolvedAt = null, i.resolvedNotifiedAt = null, i.satisfactionAttempts = 0, i.lastSatisfactionAttemptAt = null, i.satisfiedAt = null, i.rating = null, i.satisfactionComment = null;
|
|
404
340
|
}
|
|
405
341
|
/** Test helper. */
|
|
406
342
|
__reset() {
|
|
407
|
-
this._tickets = [];
|
|
408
|
-
this._ticketSeq = 0;
|
|
343
|
+
this._tickets = [], this._ticketSeq = 0;
|
|
409
344
|
}
|
|
410
|
-
}
|
|
411
|
-
var MockEntitlements = class {
|
|
345
|
+
}, D = class {
|
|
412
346
|
_denied = /* @__PURE__ */ new Set();
|
|
413
|
-
async check(
|
|
414
|
-
return !this._denied.has(`${
|
|
347
|
+
async check(e, r) {
|
|
348
|
+
return !this._denied.has(`${e}:${r}`);
|
|
415
349
|
}
|
|
416
|
-
async checkDetailed(
|
|
417
|
-
|
|
350
|
+
async checkDetailed(e, r) {
|
|
351
|
+
let i = await this.check(e, r);
|
|
418
352
|
return {
|
|
419
|
-
allowed,
|
|
420
|
-
productSlug,
|
|
421
|
-
feature,
|
|
422
|
-
reason:
|
|
353
|
+
allowed: i,
|
|
354
|
+
productSlug: e,
|
|
355
|
+
feature: r,
|
|
356
|
+
reason: i ? "granted" : "mock_denied"
|
|
423
357
|
};
|
|
424
358
|
}
|
|
425
359
|
/** Test helper. */
|
|
426
|
-
__deny(
|
|
427
|
-
this._denied.add(`${
|
|
360
|
+
__deny(e, r) {
|
|
361
|
+
this._denied.add(`${e}:${r}`);
|
|
428
362
|
}
|
|
429
363
|
/** Test helper. */
|
|
430
364
|
__reset() {
|
|
431
365
|
this._denied.clear();
|
|
432
366
|
}
|
|
433
|
-
}
|
|
434
|
-
var MockDb = class {
|
|
367
|
+
}, C = class {
|
|
435
368
|
_store = /* @__PURE__ */ new Map();
|
|
436
369
|
_fixtures;
|
|
437
|
-
constructor(
|
|
438
|
-
this._fixtures = new Map(Object.entries(
|
|
439
|
-
}
|
|
440
|
-
collection(
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
init ? new Map(Object.entries(init)) : /* @__PURE__ */ new Map()
|
|
370
|
+
constructor(e = {}) {
|
|
371
|
+
this._fixtures = new Map(Object.entries(e));
|
|
372
|
+
}
|
|
373
|
+
collection(e) {
|
|
374
|
+
let r = this._store, i = this._fixtures;
|
|
375
|
+
if (!r.has(e)) {
|
|
376
|
+
let s = i.get(e);
|
|
377
|
+
r.set(
|
|
378
|
+
e,
|
|
379
|
+
s ? new Map(Object.entries(s)) : /* @__PURE__ */ new Map()
|
|
448
380
|
);
|
|
449
381
|
}
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
switch (f.op) {
|
|
382
|
+
let o = r.get(e), a = (s, t) => {
|
|
383
|
+
let n = s[t.field];
|
|
384
|
+
switch (t.op) {
|
|
454
385
|
case "==":
|
|
455
|
-
return
|
|
386
|
+
return n === t.value;
|
|
456
387
|
case "!=":
|
|
457
|
-
return
|
|
388
|
+
return n !== t.value;
|
|
458
389
|
case "<":
|
|
459
|
-
return typeof
|
|
390
|
+
return typeof n == "number" && typeof t.value == "number" && n < t.value;
|
|
460
391
|
case "<=":
|
|
461
|
-
return typeof
|
|
392
|
+
return typeof n == "number" && typeof t.value == "number" && n <= t.value;
|
|
462
393
|
case ">":
|
|
463
|
-
return typeof
|
|
394
|
+
return typeof n == "number" && typeof t.value == "number" && n > t.value;
|
|
464
395
|
case ">=":
|
|
465
|
-
return typeof
|
|
396
|
+
return typeof n == "number" && typeof t.value == "number" && n >= t.value;
|
|
466
397
|
case "in":
|
|
467
|
-
return Array.isArray(
|
|
398
|
+
return Array.isArray(t.value) && t.value.includes(n);
|
|
468
399
|
case "array-contains":
|
|
469
|
-
return Array.isArray(
|
|
400
|
+
return Array.isArray(n) && n.includes(t.value);
|
|
470
401
|
case "not-in":
|
|
471
|
-
return Array.isArray(
|
|
402
|
+
return Array.isArray(t.value) && !t.value.includes(n);
|
|
472
403
|
default:
|
|
473
404
|
return true;
|
|
474
405
|
}
|
|
475
|
-
};
|
|
476
|
-
|
|
477
|
-
function buildListResult(items) {
|
|
406
|
+
}, c = 0;
|
|
407
|
+
function y(s) {
|
|
478
408
|
return {
|
|
479
|
-
docs:
|
|
409
|
+
docs: s.map((t, n) => ({ id: t.id ?? String(n), data: t })),
|
|
480
410
|
nextCursor: null,
|
|
481
411
|
fromCache: false,
|
|
482
412
|
stale: false,
|
|
@@ -484,141 +414,111 @@ var MockDb = class {
|
|
|
484
414
|
changes: []
|
|
485
415
|
};
|
|
486
416
|
}
|
|
487
|
-
function
|
|
417
|
+
function d(s, t) {
|
|
488
418
|
return {
|
|
489
|
-
docs: [{ id, data }],
|
|
419
|
+
docs: [{ id: t, data: s }],
|
|
490
420
|
fromCache: false,
|
|
491
421
|
stale: false,
|
|
492
422
|
hasPendingWrites: false,
|
|
493
423
|
changes: []
|
|
494
424
|
};
|
|
495
425
|
}
|
|
496
|
-
|
|
497
|
-
async list(
|
|
498
|
-
let
|
|
499
|
-
if (
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
items = items.slice().sort((a, b) => {
|
|
507
|
-
const av = a[field];
|
|
508
|
-
const bv = b[field];
|
|
509
|
-
const avs = av ?? "";
|
|
510
|
-
const bvs = bv ?? "";
|
|
511
|
-
const cmp = avs < bvs ? -1 : avs > bvs ? 1 : 0;
|
|
512
|
-
return direction === "desc" ? -cmp : cmp;
|
|
426
|
+
let f = {
|
|
427
|
+
async list(s) {
|
|
428
|
+
let t = Array.from(o.values());
|
|
429
|
+
if (s?.where && s.where.length > 0 && (t = t.filter(
|
|
430
|
+
(u) => s.where.every((g) => a(u, g))
|
|
431
|
+
)), s?.orderBy) {
|
|
432
|
+
let { field: u, direction: g } = s.orderBy;
|
|
433
|
+
t = t.slice().sort((p, b) => {
|
|
434
|
+
let h = p[u], v = b[u], k = h ?? "", w = v ?? "", S = k < w ? -1 : k > w ? 1 : 0;
|
|
435
|
+
return g === "desc" ? -S : S;
|
|
513
436
|
});
|
|
514
437
|
}
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
return buildListResult(items);
|
|
438
|
+
let n = s?.limit ?? 20;
|
|
439
|
+
return t = t.slice(0, n), y(t);
|
|
518
440
|
},
|
|
519
|
-
async get(
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
return buildGetResult(data, id);
|
|
441
|
+
async get(s) {
|
|
442
|
+
let t = o.get(s);
|
|
443
|
+
return t ? d(t, s) : null;
|
|
523
444
|
},
|
|
524
|
-
async add(
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
return { ok: true, id };
|
|
445
|
+
async add(s) {
|
|
446
|
+
let t = `mock-${++c}-${Math.random().toString(36).slice(2, 8)}`;
|
|
447
|
+
return o.set(t, { ...s, id: t }), { ok: true, id: t };
|
|
528
448
|
},
|
|
529
|
-
async set(
|
|
530
|
-
|
|
531
|
-
return { ok: true };
|
|
449
|
+
async set(s, t) {
|
|
450
|
+
return o.set(s, { ...t, id: s }), { ok: true };
|
|
532
451
|
},
|
|
533
|
-
async update(
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
coll.set(id, { ...data, id });
|
|
537
|
-
} else {
|
|
538
|
-
coll.set(id, { ...cur, ...data });
|
|
539
|
-
}
|
|
540
|
-
return { ok: true };
|
|
452
|
+
async update(s, t) {
|
|
453
|
+
let n = o.get(s);
|
|
454
|
+
return n ? o.set(s, { ...n, ...t }) : o.set(s, { ...t, id: s }), { ok: true };
|
|
541
455
|
},
|
|
542
|
-
async remove(
|
|
543
|
-
|
|
544
|
-
return { ok: true };
|
|
456
|
+
async remove(s) {
|
|
457
|
+
return o.delete(s), { ok: true };
|
|
545
458
|
},
|
|
546
|
-
async batch(
|
|
547
|
-
for (
|
|
548
|
-
|
|
549
|
-
if (
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
} else if (
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
} else
|
|
558
|
-
collMap.delete(op.id);
|
|
559
|
-
}
|
|
459
|
+
async batch(s) {
|
|
460
|
+
for (let t of s) {
|
|
461
|
+
let n = o;
|
|
462
|
+
if (t.kind === "add") {
|
|
463
|
+
let u = `mock-batch-${++c}`;
|
|
464
|
+
n.set(u, { ...t.data, id: u });
|
|
465
|
+
} else if (t.kind === "set")
|
|
466
|
+
n.set(t.id, { ...t.data, id: t.id });
|
|
467
|
+
else if (t.kind === "update") {
|
|
468
|
+
let u = n.get(t.id);
|
|
469
|
+
n.set(t.id, { ...u ?? {}, ...t.data, id: t.id });
|
|
470
|
+
} else t.kind === "remove" && n.delete(t.id);
|
|
560
471
|
}
|
|
561
472
|
return { ok: true };
|
|
562
473
|
},
|
|
563
|
-
onDoc(
|
|
564
|
-
|
|
565
|
-
Promise.resolve().then(() =>
|
|
566
|
-
return () => {
|
|
474
|
+
onDoc(s, t) {
|
|
475
|
+
let n = o.get(s);
|
|
476
|
+
return Promise.resolve().then(() => t(n || null)), () => {
|
|
567
477
|
};
|
|
568
478
|
},
|
|
569
|
-
onSnapshot(
|
|
570
|
-
Promise.resolve().then(async () => {
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
})
|
|
574
|
-
return () => {
|
|
479
|
+
onSnapshot(s, t) {
|
|
480
|
+
return Promise.resolve().then(async () => {
|
|
481
|
+
let n = await f.list(s);
|
|
482
|
+
t(n);
|
|
483
|
+
}), () => {
|
|
575
484
|
};
|
|
576
485
|
},
|
|
577
|
-
doc(
|
|
486
|
+
doc(s) {
|
|
578
487
|
return {
|
|
579
488
|
get id() {
|
|
580
|
-
return
|
|
489
|
+
return s;
|
|
581
490
|
},
|
|
582
491
|
get path() {
|
|
583
|
-
return `${
|
|
492
|
+
return `${e}/${s}`;
|
|
584
493
|
},
|
|
585
494
|
get collection() {
|
|
586
|
-
return
|
|
495
|
+
return e;
|
|
587
496
|
},
|
|
588
497
|
async get() {
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
return buildGetResult(data, id);
|
|
498
|
+
let t = o.get(s);
|
|
499
|
+
return t ? d(t, s) : null;
|
|
592
500
|
},
|
|
593
|
-
async set(
|
|
594
|
-
|
|
595
|
-
return { ok: true };
|
|
501
|
+
async set(t) {
|
|
502
|
+
return o.set(s, { ...t, id: s }), { ok: true };
|
|
596
503
|
},
|
|
597
|
-
async update(
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
coll.set(id, { ...data, id });
|
|
601
|
-
} else {
|
|
602
|
-
coll.set(id, { ...cur, ...data });
|
|
603
|
-
}
|
|
604
|
-
return { ok: true };
|
|
504
|
+
async update(t) {
|
|
505
|
+
let n = o.get(s);
|
|
506
|
+
return n ? o.set(s, { ...n, ...t }) : o.set(s, { ...t, id: s }), { ok: true };
|
|
605
507
|
},
|
|
606
508
|
async remove() {
|
|
607
|
-
|
|
608
|
-
return { ok: true };
|
|
509
|
+
return o.delete(s), { ok: true };
|
|
609
510
|
},
|
|
610
|
-
onSnapshot(
|
|
611
|
-
|
|
612
|
-
Promise.resolve().then(
|
|
613
|
-
() =>
|
|
614
|
-
)
|
|
615
|
-
return () => {
|
|
511
|
+
onSnapshot(t) {
|
|
512
|
+
let n = o.get(s);
|
|
513
|
+
return Promise.resolve().then(
|
|
514
|
+
() => t(n ? d(n, s) : null)
|
|
515
|
+
), () => {
|
|
616
516
|
};
|
|
617
517
|
}
|
|
618
518
|
};
|
|
619
519
|
}
|
|
620
520
|
};
|
|
621
|
-
return
|
|
521
|
+
return f;
|
|
622
522
|
}
|
|
623
523
|
/**
|
|
624
524
|
* Implementa SQL in-memory para testes — preferência: `@electric-sql/pglite`
|
|
@@ -639,80 +539,66 @@ var MockDb = class {
|
|
|
639
539
|
*
|
|
640
540
|
* Use `options.initSql` pra rodar DDL no setup (CREATE TABLE etc).
|
|
641
541
|
*/
|
|
642
|
-
async sql(
|
|
643
|
-
|
|
542
|
+
async sql(e, r) {
|
|
543
|
+
let i = r?.initSql ? Array.isArray(r.initSql) ? r.initSql : [r.initSql] : [];
|
|
644
544
|
try {
|
|
645
|
-
|
|
545
|
+
let n = await import(
|
|
646
546
|
/* webpackIgnore: true */
|
|
647
547
|
'@electric-sql/pglite'
|
|
648
|
-
)
|
|
649
|
-
const drizzlePglitePkg = await import(
|
|
548
|
+
), u = await import(
|
|
650
549
|
/* webpackIgnore: true */
|
|
651
550
|
'drizzle-orm/pglite'
|
|
652
|
-
);
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
}
|
|
657
|
-
const pgliteOrm = drizzlePglitePkg.drizzle(pglite, { schema });
|
|
658
|
-
const ormAsNode = pgliteOrm;
|
|
551
|
+
), g = await n.PGlite.create();
|
|
552
|
+
for (let h of i)
|
|
553
|
+
await g.query(h);
|
|
554
|
+
let p = u.drizzle(g, { schema: e });
|
|
659
555
|
return {
|
|
660
|
-
orm:
|
|
661
|
-
async transaction(
|
|
662
|
-
return await
|
|
556
|
+
orm: p,
|
|
557
|
+
async transaction(h, v) {
|
|
558
|
+
return await p.transaction(h);
|
|
663
559
|
},
|
|
664
560
|
async close() {
|
|
665
|
-
|
|
561
|
+
g.closed || await g.close();
|
|
666
562
|
}
|
|
667
563
|
};
|
|
668
|
-
} catch
|
|
564
|
+
} catch {
|
|
669
565
|
}
|
|
670
|
-
let
|
|
671
|
-
let drizzlePg;
|
|
566
|
+
let o, a;
|
|
672
567
|
try {
|
|
673
|
-
|
|
568
|
+
o = await import(
|
|
674
569
|
/* webpackIgnore: true */
|
|
675
570
|
'pg-mem'
|
|
676
|
-
)
|
|
677
|
-
drizzlePg = await import(
|
|
571
|
+
), a = await import(
|
|
678
572
|
/* webpackIgnore: true */
|
|
679
573
|
'drizzle-orm/node-postgres'
|
|
680
574
|
);
|
|
681
575
|
} catch {
|
|
682
|
-
throw new
|
|
576
|
+
throw new _(
|
|
683
577
|
"db_unavailable",
|
|
684
578
|
"[MockDb] sql() requer @electric-sql/pglite OU pg-mem + drizzle-orm + pg como devDependencies. Preferido: npm install -D @electric-sql/pglite drizzle-orm. Alternativo: npm install -D pg-mem drizzle-orm pg."
|
|
685
579
|
);
|
|
686
580
|
}
|
|
687
|
-
|
|
688
|
-
if (
|
|
689
|
-
for (
|
|
690
|
-
|
|
581
|
+
let c = o.newDb({ noAstCoverageCheck: true });
|
|
582
|
+
if (i.length > 0)
|
|
583
|
+
for (let n of i)
|
|
584
|
+
c.public.none(n);
|
|
585
|
+
let d = c.adapters.createPg().Pool, f = new d(), s = f.query.bind(f);
|
|
586
|
+
f.query = (n, ...u) => {
|
|
587
|
+
if (n !== null && typeof n == "object") {
|
|
588
|
+
let p = n.types;
|
|
589
|
+
p !== null && typeof p == "object" && "getTypeParser" in p && delete p.getTypeParser;
|
|
691
590
|
}
|
|
692
|
-
|
|
693
|
-
const adapters = memDb.adapters.createPg();
|
|
694
|
-
const PoolCtor = adapters.Pool;
|
|
695
|
-
const pool = new PoolCtor();
|
|
696
|
-
const origQuery = pool.query.bind(pool);
|
|
697
|
-
pool.query = (q, ...rest) => {
|
|
698
|
-
if (q !== null && typeof q === "object") {
|
|
699
|
-
const queryObj = q;
|
|
700
|
-
const types = queryObj["types"];
|
|
701
|
-
if (types !== null && typeof types === "object" && "getTypeParser" in types) {
|
|
702
|
-
delete types["getTypeParser"];
|
|
703
|
-
}
|
|
704
|
-
}
|
|
705
|
-
return origQuery(q, ...rest);
|
|
591
|
+
return s(n, ...u);
|
|
706
592
|
};
|
|
707
|
-
|
|
593
|
+
let t = a.drizzle(f, { schema: e });
|
|
708
594
|
return {
|
|
709
|
-
orm,
|
|
710
|
-
async transaction(
|
|
711
|
-
return await
|
|
595
|
+
orm: t,
|
|
596
|
+
async transaction(n, u) {
|
|
597
|
+
return await t.transaction(n);
|
|
712
598
|
},
|
|
713
599
|
async close() {
|
|
714
|
-
|
|
715
|
-
|
|
600
|
+
let n = f;
|
|
601
|
+
n.end && await n.end();
|
|
716
602
|
}
|
|
717
603
|
};
|
|
718
604
|
}
|
|
@@ -724,7 +610,7 @@ var MockDb = class {
|
|
|
724
610
|
isLeaderTab: true
|
|
725
611
|
};
|
|
726
612
|
}
|
|
727
|
-
onSyncStateChanged(
|
|
613
|
+
onSyncStateChanged(e) {
|
|
728
614
|
return () => {
|
|
729
615
|
};
|
|
730
616
|
}
|
|
@@ -737,65 +623,53 @@ var MockDb = class {
|
|
|
737
623
|
return [];
|
|
738
624
|
}
|
|
739
625
|
/** Test helper — substitui fixture inteira de uma collection. */
|
|
740
|
-
__setFixture(
|
|
741
|
-
this._store.set(
|
|
626
|
+
__setFixture(e, r) {
|
|
627
|
+
this._store.set(e, new Map(Object.entries(r)));
|
|
742
628
|
}
|
|
743
629
|
/** Test helper — reset total. */
|
|
744
630
|
__reset() {
|
|
745
631
|
this._store.clear();
|
|
746
632
|
}
|
|
747
|
-
}
|
|
748
|
-
var MockAi = class {
|
|
633
|
+
}, N = class {
|
|
749
634
|
_calls = [];
|
|
750
635
|
/** Extrai texto de um content string OU array multimodal (imagens ignoradas). */
|
|
751
|
-
_contentToText(
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
if (!Array.isArray(opts.messages) || opts.messages.length === 0) {
|
|
766
|
-
throw new NeetruError("validation_failed", "ai: messages must be a non-empty array");
|
|
767
|
-
}
|
|
768
|
-
this._calls.push({ model: opts.model, messages: opts.messages, stream: false });
|
|
769
|
-
const text = this._reply(opts);
|
|
770
|
-
const promptTokens = opts.messages.reduce((n, m) => n + this._contentToText(m.content).length, 0);
|
|
771
|
-
const completionTokens = text.length;
|
|
636
|
+
_contentToText(e) {
|
|
637
|
+
return typeof e == "string" ? e : Array.isArray(e) ? e.filter((r) => !!r && r.type === "text").map((r) => r.text).join(" ") : "";
|
|
638
|
+
}
|
|
639
|
+
_reply(e) {
|
|
640
|
+
let r = [...e.messages].reverse().find((o) => o.role === "user") ?? e.messages[e.messages.length - 1], i = this._contentToText(r?.content);
|
|
641
|
+
return i ? `mock-reply: ${i}` : "mock-reply";
|
|
642
|
+
}
|
|
643
|
+
async chat(e) {
|
|
644
|
+
if (!e || typeof e.model != "string" || e.model.length === 0)
|
|
645
|
+
throw new l("validation_failed", "ai: model is required");
|
|
646
|
+
if (!Array.isArray(e.messages) || e.messages.length === 0)
|
|
647
|
+
throw new l("validation_failed", "ai: messages must be a non-empty array");
|
|
648
|
+
this._calls.push({ model: e.model, messages: e.messages, stream: false });
|
|
649
|
+
let r = this._reply(e), i = e.messages.reduce((a, c) => a + this._contentToText(c.content).length, 0), o = r.length;
|
|
772
650
|
return {
|
|
773
|
-
choices: [{ message: { role: "assistant", content:
|
|
651
|
+
choices: [{ message: { role: "assistant", content: r }, finish_reason: "stop" }],
|
|
774
652
|
usage: {
|
|
775
|
-
prompt_tokens:
|
|
776
|
-
completion_tokens:
|
|
777
|
-
total_tokens:
|
|
653
|
+
prompt_tokens: i,
|
|
654
|
+
completion_tokens: o,
|
|
655
|
+
total_tokens: i + o
|
|
778
656
|
},
|
|
779
|
-
model:
|
|
657
|
+
model: e.model,
|
|
780
658
|
provider: "mock",
|
|
781
659
|
usageWarning: false
|
|
782
660
|
};
|
|
783
661
|
}
|
|
784
|
-
stream(
|
|
785
|
-
if (!
|
|
786
|
-
throw new
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
}
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
const parts = text.match(/\S+\s*/g) ?? [text];
|
|
794
|
-
const meta = Promise.resolve({ provider: "mock", usageWarning: false });
|
|
795
|
-
async function* iterate() {
|
|
796
|
-
for (const p of parts) yield p;
|
|
662
|
+
stream(e) {
|
|
663
|
+
if (!e || typeof e.model != "string" || e.model.length === 0)
|
|
664
|
+
throw new l("validation_failed", "ai: model is required");
|
|
665
|
+
if (!Array.isArray(e.messages) || e.messages.length === 0)
|
|
666
|
+
throw new l("validation_failed", "ai: messages must be a non-empty array");
|
|
667
|
+
this._calls.push({ model: e.model, messages: e.messages, stream: true });
|
|
668
|
+
let r = this._reply(e), i = r.match(/\S+\s*/g) ?? [r], o = Promise.resolve({ provider: "mock", usageWarning: false });
|
|
669
|
+
async function* a() {
|
|
670
|
+
for (let c of i) yield c;
|
|
797
671
|
}
|
|
798
|
-
return { meta, [Symbol.asyncIterator]:
|
|
672
|
+
return { meta: o, [Symbol.asyncIterator]: a };
|
|
799
673
|
}
|
|
800
674
|
/** Test helper — histórico de chamadas. */
|
|
801
675
|
__getCalls() {
|
|
@@ -803,12 +677,10 @@ var MockAi = class {
|
|
|
803
677
|
}
|
|
804
678
|
};
|
|
805
679
|
|
|
806
|
-
exports.DEV_FIXTURE_USER =
|
|
807
|
-
exports.MockAi =
|
|
808
|
-
exports.MockAuth =
|
|
809
|
-
exports.MockDb =
|
|
810
|
-
exports.MockEntitlements =
|
|
811
|
-
exports.MockSupport =
|
|
812
|
-
exports.MockUsage =
|
|
813
|
-
//# sourceMappingURL=mocks.cjs.map
|
|
814
|
-
//# sourceMappingURL=mocks.cjs.map
|
|
680
|
+
exports.DEV_FIXTURE_USER = x;
|
|
681
|
+
exports.MockAi = N;
|
|
682
|
+
exports.MockAuth = A;
|
|
683
|
+
exports.MockDb = C;
|
|
684
|
+
exports.MockEntitlements = D;
|
|
685
|
+
exports.MockSupport = P;
|
|
686
|
+
exports.MockUsage = T;
|