@oxyhq/contracts 0.18.0 → 0.20.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.
@@ -0,0 +1,441 @@
1
+ /**
2
+ * Oxy Trust — reputation API contracts.
3
+ *
4
+ * SINGLE SOURCE OF TRUTH for the reputation ledger's wire shapes: the closed
5
+ * value sets (`REPUTATION_CATEGORIES`, `TRUST_TIERS`, …), the response entities
6
+ * (`ReputationTransaction`, the two balance views, `ReputationDispute`,
7
+ * `ReputationRule`, the leaderboard entry) and the request bodies the write
8
+ * endpoints accept. The API validates its OUTPUT against these schemas and its
9
+ * INPUT with the same request schemas the SDK's input types are derived from;
10
+ * `@oxyhq/core`'s reputation mixin imports every type from here rather than
11
+ * declaring its own.
12
+ *
13
+ * Why this module exists: the balance endpoint was view-split server-side
14
+ * without the SDK type moving with it, and for hours the SDK affirmatively
15
+ * type-checked a read of `balance.reliability.reportAccuracyScore` against a
16
+ * response that no longer carried `reliability`. Nothing structural connected
17
+ * the API's hand-written serializers (which returned `Record<string, unknown>`)
18
+ * to the SDK's interfaces — only human attention. With the serializers
19
+ * annotated against these definitions, that divergence is a build failure.
20
+ *
21
+ * Design anchors:
22
+ * - **Ids are strings, timestamps are ISO 8601 strings.** The server holds
23
+ * `ObjectId`s and `Date`s; every serializer converts at the boundary, so a
24
+ * `Date` leaking into a field this module types as `string` fails to compile.
25
+ * - **The balance has two views, and the union is the contract.** See
26
+ * {@link ReputationBalanceView} — the compile-time assertions below are what
27
+ * stop the private view's fields becoming reachable on a stranger's balance.
28
+ * - **The closed value sets live here, not beside the mongoose models.** The
29
+ * API's model enums and the SDK's unions are the same `as const` tuple, so a
30
+ * seventh category cannot be added on one side only.
31
+ *
32
+ * The response entities are declared as explicit `interface`s with their runtime
33
+ * schemas annotated `z.ZodType<Interface>`, following `./links` and
34
+ * `./userResponse`: a `z.infer<>` of a nested-object schema can degrade to `{}`
35
+ * under a consumer's `moduleResolution: "node"` (node10) resolution, while a
36
+ * literal interface emits the field types verbatim in the `.d.ts` and survives
37
+ * both `node` and `bundler`.
38
+ *
39
+ * Platform-agnostic — zod only, no react/react-native/expo. ESM-safe (no
40
+ * `require()`).
41
+ */
42
+ import { z } from 'zod';
43
+ import { type UserNameResponse } from './userResponse';
44
+ /**
45
+ * Category bucket a reputation transaction falls into. Drives the per-category
46
+ * balance breakdown; every rule and transaction carries exactly one.
47
+ *
48
+ * - `content` — posts, comments, media a user authored.
49
+ * - `social` — follows, likes, social interactions.
50
+ * - `trust` — identity / verification / trust-graph signals.
51
+ * - `moderation` — reports filed, moderation actions, review outcomes.
52
+ * - `physical` — real-world signals (event check-ins, verified purchases).
53
+ * - `penalty` — negative adjustments for abuse / policy violations.
54
+ * - `other` — anything that does not fit the buckets above.
55
+ */
56
+ export declare const REPUTATION_CATEGORIES: readonly ["content", "social", "trust", "moderation", "physical", "penalty", "other"];
57
+ export type ReputationCategory = (typeof REPUTATION_CATEGORIES)[number];
58
+ export declare const reputationCategorySchema: z.ZodEnum<["content", "social", "trust", "moderation", "physical", "penalty", "other"]>;
59
+ /**
60
+ * Transaction lifecycle status.
61
+ *
62
+ * - `active` — counts toward the balance.
63
+ * - `disputed` — under dispute; still counts until the dispute resolves.
64
+ * - `reversed` — superseded by a compensating reversal transaction; excluded.
65
+ * - `voided` — administratively excluded with no compensating entry.
66
+ */
67
+ export declare const REPUTATION_TRANSACTION_STATUSES: readonly ["active", "disputed", "reversed", "voided"];
68
+ export type ReputationTransactionStatus = (typeof REPUTATION_TRANSACTION_STATUSES)[number];
69
+ export declare const reputationTransactionStatusSchema: z.ZodEnum<["active", "disputed", "reversed", "voided"]>;
70
+ /**
71
+ * Trust tiers, lowest → highest trust, plus the punitive `restricted`.
72
+ *
73
+ * Publicly visible: this is the contribution ladder the reputation system
74
+ * exists to publish. Note it doubles as the sanction marker — a `restricted`
75
+ * account is publicly identifiable as such.
76
+ */
77
+ export declare const TRUST_TIERS: readonly ["restricted", "new", "trusted", "high_trust", "verified"];
78
+ export type TrustTier = (typeof TRUST_TIERS)[number];
79
+ export declare const trustTierSchema: z.ZodEnum<["restricted", "new", "trusted", "high_trust", "verified"]>;
80
+ /** Kind of entity a transaction may target. */
81
+ export declare const REPUTATION_TARGET_ENTITY_TYPES: readonly ["post", "comment", "report", "purchase", "event", "check_in", "manual_review", "user", "other"];
82
+ export type ReputationTargetEntityType = (typeof REPUTATION_TARGET_ENTITY_TYPES)[number];
83
+ export declare const reputationTargetEntityTypeSchema: z.ZodEnum<["post", "comment", "report", "purchase", "event", "check_in", "manual_review", "user", "other"]>;
84
+ /** Dispute lifecycle status. */
85
+ export declare const REPUTATION_DISPUTE_STATUSES: readonly ["open", "accepted", "rejected", "needs_review"];
86
+ export type ReputationDisputeStatus = (typeof REPUTATION_DISPUTE_STATUSES)[number];
87
+ export declare const reputationDisputeStatusSchema: z.ZodEnum<["open", "accepted", "rejected", "needs_review"]>;
88
+ /** Influence context selecting which capped weight axis to read. */
89
+ export declare const REPUTATION_INFLUENCE_CONTEXTS: readonly ["default", "report", "moderation", "ranking"];
90
+ export type ReputationInfluenceContext = (typeof REPUTATION_INFLUENCE_CONTEXTS)[number];
91
+ export declare const reputationInfluenceContextSchema: z.ZodEnum<["default", "report", "moderation", "ranking"]>;
92
+ /**
93
+ * A single immutable entry in the reputation ledger.
94
+ *
95
+ * The ledger is append-only: transactions are NEVER deleted. A correction is
96
+ * expressed either as a compensating REVERSAL (the original is marked
97
+ * `reversed` and a new `active` transaction with negated points and
98
+ * `reversedTransactionId` pointing at it is appended) or a VOID (the original is
99
+ * marked `voided` and excluded from the balance, with no compensating entry).
100
+ */
101
+ export interface ReputationTransaction {
102
+ /** The transaction's Mongo `_id` as a string. */
103
+ id: string;
104
+ /** Subject of the reputation change — the user whose balance moves. */
105
+ userId: string;
106
+ /** Signed point delta. Positive awards, negative penalties/reversals. */
107
+ points: number;
108
+ /** The rule/action key that produced this transaction (e.g. `post_created`). */
109
+ actionType: string;
110
+ /** Category bucket the points fall into. */
111
+ category: ReputationCategory;
112
+ /** Canonical source application that reported the action, if any. */
113
+ applicationId?: string;
114
+ /** The specific credential used by the source application, if any. */
115
+ credentialId?: string;
116
+ /** Opaque id of the originating action in the source system (idempotency key). */
117
+ sourceActionId?: string;
118
+ /** Source-system action type (e.g. `report_confirmed`, `event_check_in`). */
119
+ sourceActionType?: string;
120
+ /** Id of the entity the action targeted (post id, report id, etc.). */
121
+ targetEntityId?: string;
122
+ /** Kind of the targeted entity. */
123
+ targetEntityType?: ReputationTargetEntityType;
124
+ /** Lifecycle status — only `active` transactions count toward the balance. */
125
+ status: ReputationTransactionStatus;
126
+ /**
127
+ * Set ONLY on a compensating reversal transaction; references the original
128
+ * transaction it reverses. The original carries `status: 'reversed'`.
129
+ */
130
+ reversedTransactionId?: string;
131
+ /** Human-readable reason / note. */
132
+ reason?: string;
133
+ /**
134
+ * Free-form structured metadata from the source system.
135
+ *
136
+ * Names third parties (the attestor who physically met the subject, the
137
+ * staking voucher, a resolved validation's juror roster), which is why the
138
+ * ledger read is owner-or-staff rather than public.
139
+ */
140
+ metadata?: Record<string, unknown>;
141
+ /** The user who caused this change (the liker, the reporting user, staff). */
142
+ createdByUserId?: string;
143
+ /** Staff/service principal who reviewed (reversed/voided) this transaction. */
144
+ reviewedByUserId?: string;
145
+ /** ISO 8601 timestamp the transaction was reviewed at, if reviewed. */
146
+ reviewedAt?: string;
147
+ /** ISO 8601 creation timestamp. */
148
+ createdAt: string;
149
+ /** ISO 8601 last-update timestamp. */
150
+ updatedAt: string;
151
+ }
152
+ export declare const reputationTransactionSchema: z.ZodType<ReputationTransaction>;
153
+ /**
154
+ * Per-category sums of a user's ACTIVE transactions. `penalties` is the
155
+ * absolute sum of every negative-point transaction across all categories; the
156
+ * named buckets carry the signed sum of transactions in that category.
157
+ */
158
+ export interface ReputationBalanceBreakdown {
159
+ content: number;
160
+ social: number;
161
+ trust: number;
162
+ moderation: number;
163
+ physical: number;
164
+ penalties: number;
165
+ }
166
+ export declare const reputationBalanceBreakdownSchema: z.ZodType<ReputationBalanceBreakdown>;
167
+ /**
168
+ * Capped influence weights. Every weight is clamped to a configured range and
169
+ * restricted users are floored on every axis, so no single account can dominate
170
+ * ranking, moderation or reporting.
171
+ */
172
+ export interface ReputationInfluence {
173
+ /** General-purpose trust weight derived from the lifetime total. */
174
+ defaultWeight: number;
175
+ /** Weight applied to this user's reports (scales with report accuracy). */
176
+ reportWeight: number;
177
+ /** Weight applied to this user's moderation actions (scales with tier). */
178
+ moderationWeight: number;
179
+ /** Damped weight applied to this user's ranking feedback. */
180
+ rankingFeedbackWeight: number;
181
+ }
182
+ export declare const reputationInfluenceSchema: z.ZodType<ReputationInfluence>;
183
+ /** Reliability signals derived from the user's moderation track record. */
184
+ export interface ReputationReliability {
185
+ /** Count of active transactions stamped `report_confirmed`. */
186
+ accurateReports: number;
187
+ /** Count of active transactions stamped `report_rejected`. */
188
+ rejectedReports: number;
189
+ /** accurate / (accurate + rejected), or the neutral 0.5 when no history. */
190
+ reportAccuracyScore: number;
191
+ /** Smoothed 0..1 abuse signal; high values force the `restricted` tier. */
192
+ abuseScore: number;
193
+ }
194
+ export declare const reputationReliabilitySchema: z.ZodType<ReputationReliability>;
195
+ /**
196
+ * The PUBLIC view of a user's reputation — everything a caller who is neither
197
+ * the subject nor platform staff receives from `GET /reputation/:userId/balance`.
198
+ *
199
+ * Deliberately limited to the two signals the already-public
200
+ * `GET /reputation/leaderboard` publishes per user, so an untokened read of a
201
+ * balance exposes no class of signal that is not public already.
202
+ */
203
+ export interface ReputationBalanceSummary {
204
+ userId: string;
205
+ /** Net lifetime total across all active transactions. */
206
+ total: number;
207
+ trustTier: TrustTier;
208
+ }
209
+ export declare const reputationBalanceSummarySchema: z.ZodType<ReputationBalanceSummary>;
210
+ /**
211
+ * The SUBJECT view of a user's reputation — the cached, recomputable snapshot in
212
+ * full, served only to the subject themselves and to platform staff.
213
+ *
214
+ * Everything beyond {@link ReputationBalanceSummary} is the platform's internal
215
+ * judgement about the person and is withheld from third parties: `reliability`
216
+ * (the abuse verdict), `influence` (what the account is worth to ranking,
217
+ * reporting and moderation), the `positive` / `negative` / `breakdown`
218
+ * decomposition (which exposes sanction history the total alone hides), and the
219
+ * timestamps (a timing oracle for the subject's last reputation event).
220
+ *
221
+ * Reach this type by reading YOUR OWN balance (`getMyReputationBalance`), by
222
+ * narrowing a {@link ReputationBalanceView} with {@link isFullReputationBalance},
223
+ * or from the staff-only `recalculateReputation`.
224
+ */
225
+ export interface ReputationBalance extends ReputationBalanceSummary {
226
+ /** Sum of positive points only. */
227
+ positive: number;
228
+ /** Sum of negative points only (a negative number). */
229
+ negative: number;
230
+ breakdown: ReputationBalanceBreakdown;
231
+ influence: ReputationInfluence;
232
+ reliability: ReputationReliability;
233
+ /** ISO 8601 timestamp the snapshot was last recomputed at. */
234
+ recalculatedAt: string;
235
+ /** ISO 8601 last-update timestamp. */
236
+ updatedAt: string;
237
+ }
238
+ export declare const reputationBalanceSchema: z.ZodType<ReputationBalance>;
239
+ /**
240
+ * What `GET /reputation/:userId/balance` may return for an ARBITRARY subject:
241
+ * the full {@link ReputationBalance} when the caller is that subject or staff,
242
+ * the {@link ReputationBalanceSummary} otherwise.
243
+ *
244
+ * The server decides at request time from the caller's token, so a client asking
245
+ * for someone else's balance cannot know statically which view it will get —
246
+ * hence the union. Reading anything past `userId` / `total` / `trustTier`
247
+ * requires narrowing with {@link isFullReputationBalance}.
248
+ */
249
+ export type ReputationBalanceView = ReputationBalance | ReputationBalanceSummary;
250
+ /**
251
+ * Whether a balance came back as the SUBJECT view, and so carries the
252
+ * breakdown / influence / reliability blocks.
253
+ *
254
+ * Checks every extra field rather than one representative: the point of the
255
+ * guard is that the caller then dereferences those blocks, so a partial payload
256
+ * must not narrow.
257
+ *
258
+ * @param balance - A balance from `getReputationBalance`.
259
+ */
260
+ export declare function isFullReputationBalance(balance: ReputationBalanceView): balance is ReputationBalance;
261
+ /** A user-initiated dispute against a specific reputation transaction. */
262
+ export interface ReputationDispute {
263
+ /** The dispute's Mongo `_id` as a string. */
264
+ id: string;
265
+ /** The transaction being disputed. */
266
+ transactionId: string;
267
+ /** The user raising the dispute. */
268
+ userId: string;
269
+ /** Why the user believes the transaction is wrong. */
270
+ reason: string;
271
+ status: ReputationDisputeStatus;
272
+ /** Optional supporting evidence (URLs / references). */
273
+ evidence?: string[];
274
+ /** ISO 8601 timestamp the dispute was resolved at, if resolved. */
275
+ resolvedAt?: string;
276
+ /** Staff principal who resolved the dispute, if resolved. */
277
+ resolvedByUserId?: string;
278
+ /** ISO 8601 creation timestamp. */
279
+ createdAt: string;
280
+ /** ISO 8601 last-update timestamp. */
281
+ updatedAt: string;
282
+ }
283
+ export declare const reputationDisputeSchema: z.ZodType<ReputationDispute>;
284
+ /**
285
+ * A configurable reputation award/penalty rule, keyed by `actionType`. The
286
+ * `GET /reputation/rules` response emits no timestamps.
287
+ */
288
+ export interface ReputationRule {
289
+ /** The rule's Mongo `_id` as a string. */
290
+ id: string;
291
+ /** Unique action key (e.g. `post_created`). */
292
+ actionType: string;
293
+ /** Signed points the rule awards (may be negative for penalties). */
294
+ points: number;
295
+ /** Category the resulting transaction is filed under. */
296
+ category: ReputationCategory;
297
+ description: string;
298
+ /** Per (user, actionType) cooldown in minutes; 0 disables the cooldown. */
299
+ cooldownInMinutes: number;
300
+ isEnabled: boolean;
301
+ }
302
+ export declare const reputationRuleSchema: z.ZodType<ReputationRule>;
303
+ /**
304
+ * The user a {@link ReputationLeaderboardEntry} is about.
305
+ *
306
+ * A deliberately narrow projection, not a full user DTO: the leaderboard is
307
+ * public, so it publishes only what is needed to render a row and route to the
308
+ * profile. `name` comes from the same canonical composition every other user
309
+ * DTO uses, so `name.displayName` is present exactly when the API resolved a
310
+ * real name — fall back to the handle when it is absent, never recompose.
311
+ */
312
+ export interface ReputationLeaderboardUser {
313
+ /** The user's Mongo `_id` as a string. */
314
+ id: string;
315
+ username: string;
316
+ name: UserNameResponse;
317
+ /** Avatar FILE ID (not a URL) — resolve it through the SDK's media chokepoint. */
318
+ avatar?: string;
319
+ /** secp256k1 public key; absent for accounts with no self-custody identity. */
320
+ publicKey?: string;
321
+ }
322
+ export declare const reputationLeaderboardUserSchema: z.ZodType<ReputationLeaderboardUser>;
323
+ /** A single leaderboard row: the user, their lifetime total, tier and rank. */
324
+ export interface ReputationLeaderboardEntry {
325
+ user: ReputationLeaderboardUser;
326
+ /** Net lifetime total. */
327
+ total: number;
328
+ /** Derived trust tier. */
329
+ trustTier: TrustTier;
330
+ /** 1-based rank within the leaderboard (`offset + index + 1`). */
331
+ rank: number;
332
+ }
333
+ export declare const reputationLeaderboardEntrySchema: z.ZodType<ReputationLeaderboardEntry>;
334
+ /**
335
+ * `GET /reputation/:userId/influence` — the requested context, the single capped
336
+ * weight for that context, and the full influence block.
337
+ */
338
+ export interface ReputationInfluenceResult {
339
+ context: ReputationInfluenceContext;
340
+ weight: number;
341
+ influence: ReputationInfluence;
342
+ }
343
+ export declare const reputationInfluenceResultSchema: z.ZodType<ReputationInfluenceResult>;
344
+ /**
345
+ * `POST /reputation/transactions/:id/reverse` — the now-`reversed` original plus
346
+ * the compensating `active` reversal entry.
347
+ */
348
+ export interface ReverseReputationTransactionResult {
349
+ original: ReputationTransaction;
350
+ reversal: ReputationTransaction;
351
+ }
352
+ export declare const reverseReputationTransactionResultSchema: z.ZodType<ReverseReputationTransactionResult>;
353
+ /**
354
+ * `POST /reputation/award`.
355
+ *
356
+ * Awarding is restricted to service tokens carrying the privileged
357
+ * `reputation:write` scope (the canonical path — a source app reports an
358
+ * action) and to platform staff; regular users may NOT award reputation. When
359
+ * called with a service token, `applicationId` / `credentialId` are resolved
360
+ * from the token and any client-supplied values for those two are ignored.
361
+ */
362
+ export interface AwardReputationInput {
363
+ /** The subject whose reputation changes (`_id` or publicKey). */
364
+ userId: string;
365
+ /** The enabled rule's action key (e.g. `post_created`). */
366
+ actionType: string;
367
+ /** Source application id (ignored for service tokens). */
368
+ applicationId?: string;
369
+ /** Source credential id (ignored for service tokens). */
370
+ credentialId?: string;
371
+ /** Opaque originating-action id used as the idempotency key. */
372
+ sourceActionId?: string;
373
+ /** Source-system action type. */
374
+ sourceActionType?: string;
375
+ /** Id of the targeted entity. */
376
+ targetEntityId?: string;
377
+ /** Kind of the targeted entity. */
378
+ targetEntityType?: ReputationTargetEntityType;
379
+ /** Optional human-readable reason (max 500 chars). */
380
+ reason?: string;
381
+ /** Free-form structured metadata from the source system. */
382
+ metadata?: Record<string, unknown>;
383
+ }
384
+ export declare const awardReputationSchema: z.ZodType<AwardReputationInput>;
385
+ /**
386
+ * `POST /reputation/disputes` — open a dispute. The disputer is the
387
+ * authenticated user and must be the disputed transaction's subject.
388
+ */
389
+ export interface CreateReputationDisputeInput {
390
+ /** The transaction being disputed. */
391
+ transactionId: string;
392
+ /** Why the transaction is believed to be wrong (1..1000 chars). */
393
+ reason: string;
394
+ /** Optional supporting evidence (URLs / references; max 20). */
395
+ evidence?: string[];
396
+ }
397
+ export declare const createReputationDisputeSchema: z.ZodType<CreateReputationDisputeInput>;
398
+ /** `POST /reputation/disputes/:id/resolve` (staff). */
399
+ export interface ResolveReputationDisputeInput {
400
+ /** Accepting reverses the disputed transaction; rejecting restores it. */
401
+ status: 'accepted' | 'rejected';
402
+ }
403
+ export declare const resolveReputationDisputeSchema: z.ZodType<ResolveReputationDisputeInput>;
404
+ /**
405
+ * `POST /reputation/rules` (staff) — create or update a rule, keyed by
406
+ * `actionType`. `cooldownInMinutes` and `isEnabled` may be omitted; the server
407
+ * fills them in (see {@link UpsertReputationRuleRequest}).
408
+ */
409
+ export interface UpsertReputationRuleInput {
410
+ /** Unique action key (e.g. `post_created`). */
411
+ actionType: string;
412
+ /** Signed points the rule awards (may be negative). */
413
+ points: number;
414
+ /** Category the resulting transaction is filed under. */
415
+ category: ReputationCategory;
416
+ /** Human-readable description (1..500 chars). */
417
+ description: string;
418
+ /** Per (user, actionType) cooldown in minutes; defaults to 0. */
419
+ cooldownInMinutes?: number;
420
+ /** Whether the rule is active; defaults to true. */
421
+ isEnabled?: boolean;
422
+ }
423
+ /**
424
+ * The upsert body AFTER the schema's defaults are applied — what the route
425
+ * handler actually receives. Distinct from {@link UpsertReputationRuleInput},
426
+ * where the defaulted fields are still optional.
427
+ */
428
+ export interface UpsertReputationRuleRequest extends UpsertReputationRuleInput {
429
+ cooldownInMinutes: number;
430
+ isEnabled: boolean;
431
+ }
432
+ export declare const upsertReputationRuleSchema: z.ZodType<UpsertReputationRuleRequest, z.ZodTypeDef, UpsertReputationRuleInput>;
433
+ /**
434
+ * `POST /reputation/transactions/:id/reverse` and `.../void` (staff). The
435
+ * reviewing principal is the authenticated user.
436
+ */
437
+ export interface ReverseReputationTransactionInput {
438
+ /** Optional human-readable reason (max 500 chars). */
439
+ reason?: string;
440
+ }
441
+ export declare const reverseReputationTransactionSchema: z.ZodType<ReverseReputationTransactionInput>;
@@ -621,8 +621,8 @@ export declare const currentUserResponseSchema: z.ZodObject<{
621
621
  did?: string | undefined;
622
622
  verifiedDomains?: import("./identity").VerifiedDomain[] | undefined;
623
623
  verified?: boolean | undefined;
624
- _id?: string | undefined;
625
624
  email?: string | undefined;
625
+ _id?: string | undefined;
626
626
  phone?: string | undefined;
627
627
  address?: string | undefined;
628
628
  birthday?: string | undefined;
@@ -644,8 +644,8 @@ export declare const currentUserResponseSchema: z.ZodObject<{
644
644
  did?: string | undefined;
645
645
  verifiedDomains?: import("./identity").VerifiedDomain[] | undefined;
646
646
  verified?: boolean | undefined;
647
- _id?: string | undefined;
648
647
  email?: string | undefined;
648
+ _id?: string | undefined;
649
649
  phone?: string | undefined;
650
650
  address?: string | undefined;
651
651
  birthday?: string | undefined;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@oxyhq/contracts",
3
- "version": "0.18.0",
3
+ "version": "0.20.0",
4
4
  "description": "OxyHQ API contracts — single source of truth for request/response Zod schemas and inferred types, shared by the backend and the client SDKs",
5
5
  "main": "dist/cjs/index.js",
6
6
  "module": "dist/esm/index.js",