@xmtp/node-bindings 0.0.16 → 0.0.17

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.
Binary file
package/dist/index.d.ts CHANGED
@@ -1,64 +1,44 @@
1
1
  /* auto-generated by NAPI-RS */
2
2
  /* eslint-disable */
3
- export class NapiClient {
3
+ export class Client {
4
4
  accountAddress: string
5
- setConsentStates(records: Array<NapiConsent>): Promise<void>
6
- getConsentState(entityType: NapiConsentEntityType, entity: string): Promise<NapiConsentState>
7
- /**
8
- * Get the client's inbox state.
9
- *
10
- * If `refresh_from_network` is true, the client will go to the network first to refresh the state.
11
- * Otherwise, the state will be read from the local database.
12
- */
13
- inboxState(refreshFromNetwork: boolean): Promise<NapiInboxState>
14
- getLatestInboxState(inboxId: string): Promise<NapiInboxState>
15
5
  inboxId(): string
16
6
  isRegistered(): boolean
17
7
  installationId(): string
18
8
  canMessage(accountAddresses: Array<string>): Promise<Record<string, boolean>>
19
9
  registerIdentity(): Promise<void>
20
- conversations(): NapiConversations
21
- requestHistorySync(): Promise<void>
10
+ conversations(): Conversations
11
+ sendHistorySyncRequest(): Promise<void>
12
+ sendConsentSyncRequest(): Promise<void>
22
13
  findInboxIdByAddress(address: string): Promise<string | null>
23
- addressesFromInboxId(refreshFromNetwork: boolean, inboxIds: Array<string>): Promise<Array<NapiInboxState>>
14
+ addressesFromInboxId(refreshFromNetwork: boolean, inboxIds: Array<string>): Promise<Array<InboxState>>
15
+ setConsentStates(records: Array<Consent>): Promise<void>
16
+ getConsentState(entityType: ConsentEntityType, entity: string): Promise<ConsentState>
17
+ /**
18
+ * Get the client's inbox state.
19
+ *
20
+ * If `refresh_from_network` is true, the client will go to the network first to refresh the state.
21
+ * Otherwise, the state will be read from the local database.
22
+ */
23
+ inboxState(refreshFromNetwork: boolean): Promise<InboxState>
24
+ getLatestInboxState(inboxId: string): Promise<InboxState>
24
25
  createInboxSignatureText(): Promise<string | null>
25
26
  addWalletSignatureText(existingWalletAddress: string, newWalletAddress: string): Promise<string>
26
27
  revokeWalletSignatureText(walletAddress: string): Promise<string>
27
28
  revokeInstallationsSignatureText(): Promise<string>
28
- addSignature(signatureType: NapiSignatureRequestType, signatureBytes: Uint8Array): Promise<void>
29
+ addSignature(signatureType: SignatureRequestType, signatureBytes: Uint8Array): Promise<void>
29
30
  applySignatureRequests(): Promise<void>
30
31
  }
31
32
 
32
- export class NapiConversations {
33
- createGroup(accountAddresses: Array<string>, options?: NapiCreateGroupOptions | undefined | null): Promise<NapiGroup>
34
- createDm(accountAddress: string): Promise<NapiGroup>
35
- findGroupById(groupId: string): NapiGroup
36
- findDmByTargetInboxId(targetInboxId: string): NapiGroup
37
- findMessageById(messageId: string): NapiMessage
38
- processStreamedWelcomeMessage(envelopeBytes: Uint8Array): Promise<NapiGroup>
39
- sync(): Promise<void>
40
- list(opts?: NapiListConversationsOptions | undefined | null): Promise<Array<NapiGroup>>
41
- listGroups(opts?: NapiListConversationsOptions | undefined | null): Promise<Array<NapiGroup>>
42
- listDms(opts?: NapiListConversationsOptions | undefined | null): Promise<Array<NapiGroup>>
43
- stream(callback: (err: null | Error, result: NapiGroup) => void): NapiStreamCloser
44
- streamGroups(callback: (err: null | Error, result: NapiGroup) => void): NapiStreamCloser
45
- streamDms(callback: (err: null | Error, result: NapiGroup) => void): NapiStreamCloser
46
- streamAllMessages(callback: (err: null | Error, result: NapiMessage) => void): NapiStreamCloser
47
- streamAllGroupMessages(callback: (err: null | Error, result: NapiMessage) => void): NapiStreamCloser
48
- streamAllDmMessages(callback: (err: null | Error, result: NapiMessage) => void): NapiStreamCloser
49
- }
50
-
51
- export class NapiGroup {
33
+ export class Conversation {
52
34
  id(): string
53
- send(encodedContent: NapiEncodedContent): Promise<string>
54
- /** send a message without immediately publishing to the delivery service. */
55
- sendOptimistic(encodedContent: NapiEncodedContent): string
56
- /** Publish all unpublished messages */
35
+ send(encodedContent: EncodedContent): Promise<string>
36
+ sendOptimistic(encodedContent: EncodedContent): string
57
37
  publishMessages(): Promise<void>
58
38
  sync(): Promise<void>
59
- findMessages(opts?: NapiListMessagesOptions | undefined | null): Array<NapiMessage>
60
- processStreamedGroupMessage(envelopeBytes: Uint8Array): Promise<NapiMessage>
61
- listMembers(): Promise<Array<NapiGroupMember>>
39
+ findMessages(opts?: ListMessagesOptions | undefined | null): Array<Message>
40
+ processStreamedGroupMessage(envelopeBytes: Uint8Array): Promise<Message>
41
+ listMembers(): Promise<Array<GroupMember>>
62
42
  adminList(): Array<string>
63
43
  superAdminList(): Array<string>
64
44
  isAdmin(inboxId: string): boolean
@@ -68,7 +48,7 @@ export class NapiGroup {
68
48
  removeAdmin(inboxId: string): Promise<void>
69
49
  addSuperAdmin(inboxId: string): Promise<void>
70
50
  removeSuperAdmin(inboxId: string): Promise<void>
71
- groupPermissions(): NapiGroupPermissions
51
+ groupPermissions(): GroupPermissions
72
52
  addMembersByInboxId(inboxIds: Array<string>): Promise<void>
73
53
  removeMembers(accountAddresses: Array<string>): Promise<void>
74
54
  removeMembersByInboxId(inboxIds: Array<string>): Promise<void>
@@ -80,45 +60,54 @@ export class NapiGroup {
80
60
  groupDescription(): string
81
61
  updateGroupPinnedFrameUrl(pinnedFrameUrl: string): Promise<void>
82
62
  groupPinnedFrameUrl(): string
83
- stream(callback: (err: null | Error, result: NapiMessage) => void): NapiStreamCloser
63
+ stream(callback: (err: null | Error, result: Message | undefined) => void): StreamCloser
84
64
  createdAtNs(): number
85
65
  isActive(): boolean
86
66
  addedByInboxId(): string
87
- groupMetadata(): NapiGroupMetadata
88
- consentState(): NapiConsentState
89
- updateConsentState(state: NapiConsentState): void
67
+ groupMetadata(): GroupMetadata
68
+ consentState(): ConsentState
69
+ updateConsentState(state: ConsentState): void
90
70
  dmPeerInboxId(): string
91
71
  }
92
72
 
93
- export class NapiGroupMember {
73
+ export class Conversations {
74
+ createGroup(accountAddresses: Array<string>, options?: CreateGroupOptions | undefined | null): Promise<Conversation>
75
+ createDm(accountAddress: string): Promise<Conversation>
76
+ findGroupById(groupId: string): Conversation
77
+ findDmByTargetInboxId(targetInboxId: string): Conversation
78
+ findMessageById(messageId: string): Message
79
+ processStreamedWelcomeMessage(envelopeBytes: Uint8Array): Promise<Conversation>
80
+ sync(): Promise<void>
81
+ list(opts?: ListConversationsOptions | undefined | null): Promise<Array<Conversation>>
82
+ listGroups(opts?: ListConversationsOptions | undefined | null): Promise<Array<Conversation>>
83
+ listDms(opts?: ListConversationsOptions | undefined | null): Promise<Array<Conversation>>
84
+ stream(callback: (err: null | Error, result: Conversation | undefined) => void): StreamCloser
85
+ streamGroups(callback: (err: null | Error, result: Conversation | undefined) => void): StreamCloser
86
+ streamDms(callback: (err: null | Error, result: Conversation | undefined) => void): StreamCloser
87
+ streamAllMessages(callback: (err: null | Error, result: Message | undefined) => void): StreamCloser
88
+ streamAllGroupMessages(callback: (err: null | Error, result: Message | undefined) => void): StreamCloser
89
+ streamAllDmMessages(callback: (err: null | Error, result: Message | undefined) => void): StreamCloser
90
+ }
91
+
92
+ export class GroupMember {
94
93
  inboxId: string
95
94
  accountAddresses: Array<string>
96
95
  installationIds: Array<string>
97
- permissionLevel: NapiPermissionLevel
98
- consentState: NapiConsentState
96
+ permissionLevel: PermissionLevel
97
+ consentState: ConsentState
99
98
  }
100
99
 
101
- export class NapiGroupMetadata {
100
+ export class GroupMetadata {
102
101
  creatorInboxId(): string
103
102
  conversationType(): string
104
103
  }
105
104
 
106
- export class NapiGroupPermissions {
107
- policyType(): NapiGroupPermissionsOptions
108
- policySet(): NapiPermissionPolicySet
109
- }
110
-
111
- export class NapiMessage {
112
- id: string
113
- sentAtNs: number
114
- convoId: string
115
- senderInboxId: string
116
- content: NapiEncodedContent
117
- kind: NapiGroupMessageKind
118
- deliveryStatus: NapiDeliveryStatus
105
+ export class GroupPermissions {
106
+ policyType(): GroupPermissionsOptions
107
+ policySet(): PermissionPolicySet
119
108
  }
120
109
 
121
- export class NapiStreamCloser {
110
+ export class StreamCloser {
122
111
  /**
123
112
  * Signal the stream to end
124
113
  * Does not wait for the stream to end.
@@ -134,128 +123,134 @@ export class NapiStreamCloser {
134
123
  isClosed(): boolean
135
124
  }
136
125
 
137
- /**
138
- * Create an MLS client
139
- * Optionally specify a filter for the log level as a string.
140
- * It can be one of: `debug`, `info`, `warn`, `error` or 'off'.
141
- * By default, logging is set to `info`. `off` completely disables logging.
142
- */
143
- export declare function createClient(host: string, isSecure: boolean, dbPath: string, inboxId: string, accountAddress: string, encryptionKey?: Uint8Array | undefined | null, historySyncUrl?: string | undefined | null, envFilter?: string | undefined | null): Promise<NapiClient>
144
-
145
- export declare function generateInboxId(accountAddress: string): string
146
-
147
- export declare function getInboxIdForAddress(host: string, isSecure: boolean, accountAddress: string): Promise<string | null>
148
-
149
- export interface NapiConsent {
150
- entityType: NapiConsentEntityType
151
- state: NapiConsentState
126
+ export interface Consent {
127
+ entityType: ConsentEntityType
128
+ state: ConsentState
152
129
  entity: string
153
130
  }
154
131
 
155
- export const enum NapiConsentEntityType {
132
+ export const enum ConsentEntityType {
156
133
  GroupId = 0,
157
134
  InboxId = 1,
158
135
  Address = 2
159
136
  }
160
137
 
161
- export const enum NapiConsentState {
138
+ export const enum ConsentState {
162
139
  Unknown = 0,
163
140
  Allowed = 1,
164
141
  Denied = 2
165
142
  }
166
143
 
167
- export interface NapiContentTypeId {
144
+ export interface ContentTypeId {
168
145
  authorityId: string
169
146
  typeId: string
170
147
  versionMajor: number
171
148
  versionMinor: number
172
149
  }
173
150
 
174
- export const enum NapiConversationType {
151
+ export const enum ConversationType {
175
152
  Dm = 0,
176
153
  Group = 1,
177
154
  Sync = 2
178
155
  }
179
156
 
180
- export interface NapiCreateGroupOptions {
181
- permissions?: NapiGroupPermissionsOptions
157
+ /**
158
+ * Create a client
159
+ *
160
+ * Optionally specify a filter for the log level as a string.
161
+ * It can be one of: `debug`, `info`, `warn`, `error` or 'off'.
162
+ * By default, logging is disabled.
163
+ */
164
+ export declare function createClient(host: string, isSecure: boolean, dbPath: string, inboxId: string, accountAddress: string, encryptionKey?: Uint8Array | undefined | null, historySyncUrl?: string | undefined | null, envFilter?: "debug" | "info" | "warn" | "error" | "off" | undefined | null): Promise<Client>
165
+
166
+ export interface CreateGroupOptions {
167
+ permissions?: GroupPermissionsOptions
182
168
  groupName?: string
183
169
  groupImageUrlSquare?: string
184
170
  groupDescription?: string
185
171
  groupPinnedFrameUrl?: string
186
172
  }
187
173
 
188
- export const enum NapiDeliveryStatus {
174
+ export const enum DeliveryStatus {
189
175
  Unpublished = 0,
190
176
  Published = 1,
191
177
  Failed = 2
192
178
  }
193
179
 
194
- export const enum NapiDirection {
195
- Ascending = 0,
196
- Descending = 1
197
- }
198
-
199
- export interface NapiEncodedContent {
200
- type?: NapiContentTypeId
180
+ export interface EncodedContent {
181
+ type?: ContentTypeId
201
182
  parameters: Record<string, string>
202
183
  fallback?: string
203
184
  compression?: number
204
185
  content: Uint8Array
205
186
  }
206
187
 
207
- export const enum NapiGroupMembershipState {
188
+ export declare function generateInboxId(accountAddress: string): string
189
+
190
+ export declare function getInboxIdForAddress(host: string, isSecure: boolean, accountAddress: string): Promise<string | null>
191
+
192
+ export const enum GroupMembershipState {
208
193
  Allowed = 0,
209
194
  Rejected = 1,
210
195
  Pending = 2
211
196
  }
212
197
 
213
- export const enum NapiGroupMessageKind {
198
+ export const enum GroupMessageKind {
214
199
  Application = 0,
215
200
  MembershipChange = 1
216
201
  }
217
202
 
218
- export const enum NapiGroupPermissionsOptions {
203
+ export const enum GroupPermissionsOptions {
219
204
  AllMembers = 0,
220
205
  AdminOnly = 1,
221
206
  CustomPolicy = 2
222
207
  }
223
208
 
224
- export interface NapiInboxState {
209
+ export interface InboxState {
225
210
  inboxId: string
226
211
  recoveryAddress: string
227
- installations: Array<NapiInstallation>
212
+ installations: Array<Installation>
228
213
  accountAddresses: Array<string>
229
214
  }
230
215
 
231
- export interface NapiInstallation {
216
+ export interface Installation {
232
217
  id: string
233
218
  clientTimestampNs?: bigint
234
219
  }
235
220
 
236
- export interface NapiListConversationsOptions {
237
- allowedStates?: Array<NapiGroupMembershipState>
221
+ export interface ListConversationsOptions {
222
+ allowedStates?: Array<GroupMembershipState>
238
223
  createdAfterNs?: number
239
224
  createdBeforeNs?: number
240
225
  limit?: number
241
- conversationType?: NapiConversationType
226
+ conversationType?: ConversationType
242
227
  }
243
228
 
244
- export interface NapiListMessagesOptions {
229
+ export interface ListMessagesOptions {
245
230
  sentBeforeNs?: number
246
231
  sentAfterNs?: number
247
232
  limit?: number
248
- deliveryStatus?: NapiDeliveryStatus
249
- direction?: NapiDirection
233
+ deliveryStatus?: DeliveryStatus
234
+ direction?: SortDirection
235
+ }
236
+
237
+ export interface Message {
238
+ id: string
239
+ sentAtNs: number
240
+ convoId: string
241
+ senderInboxId: string
242
+ content: EncodedContent
243
+ kind: GroupMessageKind
244
+ deliveryStatus: DeliveryStatus
250
245
  }
251
246
 
252
- export const enum NapiPermissionLevel {
247
+ export const enum PermissionLevel {
253
248
  Member = 0,
254
249
  Admin = 1,
255
250
  SuperAdmin = 2
256
251
  }
257
252
 
258
- export const enum NapiPermissionPolicy {
253
+ export const enum PermissionPolicy {
259
254
  Allow = 0,
260
255
  Deny = 1,
261
256
  Admin = 2,
@@ -264,18 +259,18 @@ export const enum NapiPermissionPolicy {
264
259
  Other = 5
265
260
  }
266
261
 
267
- export interface NapiPermissionPolicySet {
268
- addMemberPolicy: NapiPermissionPolicy
269
- removeMemberPolicy: NapiPermissionPolicy
270
- addAdminPolicy: NapiPermissionPolicy
271
- removeAdminPolicy: NapiPermissionPolicy
272
- updateGroupNamePolicy: NapiPermissionPolicy
273
- updateGroupDescriptionPolicy: NapiPermissionPolicy
274
- updateGroupImageUrlSquarePolicy: NapiPermissionPolicy
275
- updateGroupPinnedFrameUrlPolicy: NapiPermissionPolicy
262
+ export interface PermissionPolicySet {
263
+ addMemberPolicy: PermissionPolicy
264
+ removeMemberPolicy: PermissionPolicy
265
+ addAdminPolicy: PermissionPolicy
266
+ removeAdminPolicy: PermissionPolicy
267
+ updateGroupNamePolicy: PermissionPolicy
268
+ updateGroupDescriptionPolicy: PermissionPolicy
269
+ updateGroupImageUrlSquarePolicy: PermissionPolicy
270
+ updateGroupPinnedFrameUrlPolicy: PermissionPolicy
276
271
  }
277
272
 
278
- export const enum NapiPermissionUpdateType {
273
+ export const enum PermissionUpdateType {
279
274
  AddMember = 0,
280
275
  RemoveMember = 1,
281
276
  AddAdmin = 2,
@@ -283,10 +278,15 @@ export const enum NapiPermissionUpdateType {
283
278
  UpdateMetadata = 4
284
279
  }
285
280
 
286
- export const enum NapiSignatureRequestType {
281
+ export const enum SignatureRequestType {
287
282
  AddWallet = 0,
288
283
  CreateInbox = 1,
289
284
  RevokeWallet = 2,
290
285
  RevokeInstallations = 3
291
286
  }
292
287
 
288
+ export const enum SortDirection {
289
+ Ascending = 0,
290
+ Descending = 1
291
+ }
292
+
package/dist/index.js CHANGED
@@ -361,26 +361,25 @@ if (!nativeBinding) {
361
361
  throw new Error(`Failed to load native binding`)
362
362
  }
363
363
 
364
- module.exports.NapiClient = nativeBinding.NapiClient
365
- module.exports.NapiConversations = nativeBinding.NapiConversations
366
- module.exports.NapiGroup = nativeBinding.NapiGroup
367
- module.exports.NapiGroupMember = nativeBinding.NapiGroupMember
368
- module.exports.NapiGroupMetadata = nativeBinding.NapiGroupMetadata
369
- module.exports.NapiGroupPermissions = nativeBinding.NapiGroupPermissions
370
- module.exports.NapiMessage = nativeBinding.NapiMessage
371
- module.exports.NapiStreamCloser = nativeBinding.NapiStreamCloser
364
+ module.exports.Client = nativeBinding.Client
365
+ module.exports.Conversation = nativeBinding.Conversation
366
+ module.exports.Conversations = nativeBinding.Conversations
367
+ module.exports.GroupMember = nativeBinding.GroupMember
368
+ module.exports.GroupMetadata = nativeBinding.GroupMetadata
369
+ module.exports.GroupPermissions = nativeBinding.GroupPermissions
370
+ module.exports.StreamCloser = nativeBinding.StreamCloser
371
+ module.exports.ConsentEntityType = nativeBinding.ConsentEntityType
372
+ module.exports.ConsentState = nativeBinding.ConsentState
373
+ module.exports.ConversationType = nativeBinding.ConversationType
372
374
  module.exports.createClient = nativeBinding.createClient
375
+ module.exports.DeliveryStatus = nativeBinding.DeliveryStatus
373
376
  module.exports.generateInboxId = nativeBinding.generateInboxId
374
377
  module.exports.getInboxIdForAddress = nativeBinding.getInboxIdForAddress
375
- module.exports.NapiConsentEntityType = nativeBinding.NapiConsentEntityType
376
- module.exports.NapiConsentState = nativeBinding.NapiConsentState
377
- module.exports.NapiConversationType = nativeBinding.NapiConversationType
378
- module.exports.NapiDeliveryStatus = nativeBinding.NapiDeliveryStatus
379
- module.exports.NapiDirection = nativeBinding.NapiDirection
380
- module.exports.NapiGroupMembershipState = nativeBinding.NapiGroupMembershipState
381
- module.exports.NapiGroupMessageKind = nativeBinding.NapiGroupMessageKind
382
- module.exports.NapiGroupPermissionsOptions = nativeBinding.NapiGroupPermissionsOptions
383
- module.exports.NapiPermissionLevel = nativeBinding.NapiPermissionLevel
384
- module.exports.NapiPermissionPolicy = nativeBinding.NapiPermissionPolicy
385
- module.exports.NapiPermissionUpdateType = nativeBinding.NapiPermissionUpdateType
386
- module.exports.NapiSignatureRequestType = nativeBinding.NapiSignatureRequestType
378
+ module.exports.GroupMembershipState = nativeBinding.GroupMembershipState
379
+ module.exports.GroupMessageKind = nativeBinding.GroupMessageKind
380
+ module.exports.GroupPermissionsOptions = nativeBinding.GroupPermissionsOptions
381
+ module.exports.PermissionLevel = nativeBinding.PermissionLevel
382
+ module.exports.PermissionPolicy = nativeBinding.PermissionPolicy
383
+ module.exports.PermissionUpdateType = nativeBinding.PermissionUpdateType
384
+ module.exports.SignatureRequestType = nativeBinding.SignatureRequestType
385
+ module.exports.SortDirection = nativeBinding.SortDirection
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xmtp/node-bindings",
3
- "version": "0.0.16",
3
+ "version": "0.0.17",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "git+https://git@github.com/xmtp/libxmtp.git",
@@ -20,32 +20,35 @@
20
20
  ],
21
21
  "scripts": {
22
22
  "artifacts": "napi artifacts",
23
- "build": "napi build --platform --release",
23
+ "build": "yarn build:clean && yarn build:release && yarn build:finish",
24
24
  "build:clean": "rm -rf dist",
25
25
  "build:debug": "napi build --platform",
26
26
  "build:finish": "mkdir dist && mv index.js dist && mv index.d.ts dist && mv *.node dist",
27
- "build:release": "yarn build:clean && yarn build && yarn build:finish",
27
+ "build:release": "napi build --platform --release",
28
28
  "clean": "yarn build:clean && yarn test:clean",
29
29
  "format": "prettier -w .",
30
30
  "format:check": "prettier -c .",
31
+ "lint": "yarn lint:clippy && yarn lint:fmt",
32
+ "lint:clippy": "cargo clippy --all-features --all-targets --no-deps -- -Dwarnings",
33
+ "lint:fmt": "cargo fmt --check",
31
34
  "test": "vitest run",
32
35
  "test:clean": "rm -rf test/*.db3*"
33
36
  },
34
37
  "devDependencies": {
35
- "@ianvs/prettier-plugin-sort-imports": "^4.2.1",
38
+ "@ianvs/prettier-plugin-sort-imports": "^4.4.0",
36
39
  "@napi-rs/cli": "^3.0.0-alpha.55",
37
- "@types/node": "^20.14.2",
38
- "@types/uuid": "^10",
39
- "prettier": "^3.3.2",
40
- "prettier-plugin-packagejson": "^2.5.0",
41
- "typescript": "^5.4.5",
42
- "uuid": "^10.0.0",
43
- "viem": "^2.11.1",
44
- "vite": "^5.2.13",
45
- "vite-tsconfig-paths": "^4.3.2",
46
- "vitest": "^1.6.0"
40
+ "@types/node": "^20.17.6",
41
+ "@types/uuid": "^10.0.0",
42
+ "prettier": "^3.3.3",
43
+ "prettier-plugin-packagejson": "^2.5.3",
44
+ "typescript": "^5.6.3",
45
+ "uuid": "^11.0.2",
46
+ "viem": "^2.21.41",
47
+ "vite": "^5.4.10",
48
+ "vite-tsconfig-paths": "^5.1.0",
49
+ "vitest": "^2.1.4"
47
50
  },
48
- "packageManager": "yarn@4.2.2",
51
+ "packageManager": "yarn@4.5.1",
49
52
  "engines": {
50
53
  "node": ">=18"
51
54
  },