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