@dbml/cli 5.0.0-alpha.0 → 5.1.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.
Files changed (78) hide show
  1. package/__test__/cli.test.js +4 -3
  2. package/__test__/db2dbml/mssql/expect-out-files/schema.dbml +28 -51
  3. package/__test__/db2dbml/mssql/schema.sql +2 -1
  4. package/__test__/db2dbml/mysql/expect-out-files/schema.dbml +10 -2
  5. package/__test__/db2dbml/mysql/schema.sql +9 -3
  6. package/__test__/db2dbml/postgres/expect-out-files/schema.dbml +14 -10
  7. package/__test__/db2dbml/postgres/schema.sql +4 -3
  8. package/package.json +4 -4
  9. package/__test__/db2dbml/mssql/dbml-error.log +0 -337
  10. package/__test__/db2dbml/mssql/out-files/schema.dbml +0 -219
  11. package/__test__/db2dbml/mysql/dbml-error.log +0 -230
  12. package/__test__/db2dbml/mysql/out-files/schema.dbml +0 -188
  13. package/__test__/db2dbml/postgres/dbml-error.log +0 -63
  14. package/__test__/db2dbml/postgres/out-files/schema.dbml +0 -184
  15. package/__test__/dbml2sql/filename --mysql --out-file/dbml-error.log +0 -0
  16. package/__test__/dbml2sql/filename --mysql --out-file/out-files/schema.sql +0 -65
  17. package/__test__/dbml2sql/filename --mysql stdout/dbml-error.log +0 -0
  18. package/__test__/dbml2sql/filename --oracle --out-file/dbml-error.log +0 -0
  19. package/__test__/dbml2sql/filename --oracle --out-file/out-files/schema.sql +0 -61
  20. package/__test__/dbml2sql/filename --oracle stdout/dbml-error.log +0 -0
  21. package/__test__/dbml2sql/filename --out-file/dbml-error.log +0 -0
  22. package/__test__/dbml2sql/filename --out-file/out-files/schema.sql +0 -77
  23. package/__test__/dbml2sql/filename --postgres --out-file/dbml-error.log +0 -0
  24. package/__test__/dbml2sql/filename --postgres --out-file/out-files/schema.sql +0 -77
  25. package/__test__/dbml2sql/filename --postgres stdout/dbml-error.log +0 -0
  26. package/__test__/dbml2sql/filename stdout/dbml-error.log +0 -0
  27. package/__test__/dbml2sql/filenames --mysql --out-file/dbml-error.log +0 -0
  28. package/__test__/dbml2sql/filenames --mysql --out-file/out-files/schema.sql +0 -172
  29. package/__test__/dbml2sql/filenames --mysql stdout/dbml-error.log +0 -0
  30. package/__test__/dbml2sql/filenames --oracle --out-file/dbml-error.log +0 -0
  31. package/__test__/dbml2sql/filenames --oracle --out-file/out-files/schema.sql +0 -172
  32. package/__test__/dbml2sql/filenames --oracle stdout/dbml-error.log +0 -0
  33. package/__test__/dbml2sql/filenames --out-file/dbml-error.log +0 -0
  34. package/__test__/dbml2sql/filenames --out-file/out-files/schema.sql +0 -172
  35. package/__test__/dbml2sql/filenames --postgres --out-file/dbml-error.log +0 -0
  36. package/__test__/dbml2sql/filenames --postgres --out-file/out-files/schema.sql +0 -172
  37. package/__test__/dbml2sql/filenames --postgres stdout/dbml-error.log +0 -0
  38. package/__test__/dbml2sql/filenames stdout/dbml-error.log +0 -0
  39. package/__test__/dbml2sql/multiple_schema_mssql/dbml-error.log +0 -0
  40. package/__test__/dbml2sql/multiple_schema_mssql/out-files/multiple_schema.out.sql +0 -62
  41. package/__test__/dbml2sql/multiple_schema_mysql/dbml-error.log +0 -0
  42. package/__test__/dbml2sql/multiple_schema_mysql/out-files/multiple_schema.out.sql +0 -50
  43. package/__test__/dbml2sql/multiple_schema_oracle/dbml-error.log +0 -0
  44. package/__test__/dbml2sql/multiple_schema_oracle/out-files/multiple_schema.out.sql +0 -88
  45. package/__test__/dbml2sql/multiple_schema_pg/dbml-error.log +0 -0
  46. package/__test__/dbml2sql/multiple_schema_pg/out-files/multiple_schema.out.sql +0 -67
  47. package/__test__/dbml2sql/syntax-error/dbml-error.log +0 -342
  48. package/__test__/sql2dbml/filename --mssql --out-file/dbml-error.log +0 -0
  49. package/__test__/sql2dbml/filename --mssql --out-file/out-files/schema.dbml +0 -25
  50. package/__test__/sql2dbml/filename --mysql --out-file/dbml-error.log +0 -0
  51. package/__test__/sql2dbml/filename --mysql --out-file/out-files/schema.dbml +0 -74
  52. package/__test__/sql2dbml/filename --mysql stdout/dbml-error.log +0 -0
  53. package/__test__/sql2dbml/filename --out-file/dbml-error.log +0 -0
  54. package/__test__/sql2dbml/filename --out-file/out-files/schema.dbml +0 -74
  55. package/__test__/sql2dbml/filename --postgres --out-file/dbml-error.log +0 -0
  56. package/__test__/sql2dbml/filename --postgres --out-file/out-files/schema.dbml +0 -74
  57. package/__test__/sql2dbml/filename --postgres stdout/dbml-error.log +0 -0
  58. package/__test__/sql2dbml/filename --snowflake stdout/dbml-error.log +0 -0
  59. package/__test__/sql2dbml/filename stdout/dbml-error.log +0 -0
  60. package/__test__/sql2dbml/filenames --mysql --out-file/dbml-error.log +0 -0
  61. package/__test__/sql2dbml/filenames --mysql --out-file/out-files/schema.dbml +0 -170
  62. package/__test__/sql2dbml/filenames --mysql stdout/dbml-error.log +0 -0
  63. package/__test__/sql2dbml/filenames --out-file/dbml-error.log +0 -0
  64. package/__test__/sql2dbml/filenames --out-file/out-files/schema.dbml +0 -170
  65. package/__test__/sql2dbml/filenames --postgres --out-file/dbml-error.log +0 -0
  66. package/__test__/sql2dbml/filenames --postgres --out-file/out-files/schema.dbml +0 -170
  67. package/__test__/sql2dbml/filenames --postgres stdout/dbml-error.log +0 -0
  68. package/__test__/sql2dbml/filenames stdout/dbml-error.log +0 -0
  69. package/__test__/sql2dbml/multiple_schema_mssql/dbml-error.log +0 -0
  70. package/__test__/sql2dbml/multiple_schema_mssql/out-files/multiple_schema.out.dbml +0 -58
  71. package/__test__/sql2dbml/multiple_schema_mysql/dbml-error.log +0 -0
  72. package/__test__/sql2dbml/multiple_schema_mysql/out-files/multiple_schema.out.dbml +0 -136
  73. package/__test__/sql2dbml/multiple_schema_pg/dbml-error.log +0 -0
  74. package/__test__/sql2dbml/multiple_schema_pg/out-files/multiple_schema.out.dbml +0 -101
  75. package/__test__/sql2dbml/syntax-error/dbml-error.log +0 -339
  76. package/__test__/sql2dbml/syntax-error-duplicate-endpoints --mssql/dbml-error.log +0 -339
  77. package/__test__/sql2dbml/syntax-error-duplicate-endpoints --mysql/dbml-error.log +0 -336
  78. package/dbml-error.log +0 -0
@@ -41,17 +41,18 @@ describe('@dbml/cli', () => {
41
41
  }
42
42
  };
43
43
 
44
+ const timeout = 100000;
44
45
  /* eslint-disable */
45
46
  test.each(scanDirNames(__dirname, 'dbml2sql'))('dbml2sql/%s', async (dirName) => {
46
47
  await runTest(path.join(__dirname, 'dbml2sql', dirName), '../bin/dbml2sql.js');
47
- }, 10000);
48
+ }, timeout);
48
49
 
49
50
  test.each(scanDirNames(__dirname, 'sql2dbml'))('sql2dbml/%s', async (dirName) => {
50
51
  await runTest(path.join(__dirname, 'sql2dbml', dirName), '../bin/sql2dbml.js');
51
- }, 10000);
52
+ }, timeout);
52
53
 
53
54
  test.each(scanDirNames(__dirname, 'db2dbml'))('db2dbml/%s', async (dirName) => {
54
55
  await runTest(path.join(__dirname, 'db2dbml', dirName), '../bin/db2dbml.js');
55
- }, 10000);
56
+ }, timeout);
56
57
  /* eslint-enable */
57
58
  });
@@ -1,48 +1,13 @@
1
- Enum "dbo"."chk_status_status" {
2
- "cancelled"
3
- "delivered"
4
- "shipped"
5
- "processing"
6
- "pending"
7
- }
8
-
9
- Enum "dbo"."chk_gender_gender" {
10
- "Other"
11
- "Female"
12
- "Male"
13
- }
14
-
15
- Enum "dbo"."CK_Address_Valid_AddressID_AddressFormatID" {
16
- "176029FA-D6D3-49E1-A48C-000000000002"
17
- "176029FA-D6D3-49E1-A48C-000000000001"
18
- }
19
-
20
- Enum "dbo"."CK_Address_Valid2_A1" {
21
- "333"
22
- "2222"
23
- "1111"
24
- }
25
-
26
- Enum "dbo"."CK_Address_Valid2_A2_A3" {
27
- "2222"
28
- "1111"
29
- }
30
-
31
- Enum "dbo"."CK_Address_Valid2_A4" {
32
- "3333"
33
- "2222"
34
- }
35
-
36
1
  Table "dbo"."users" {
37
2
  "user_id" int(10) [pk, not null, increment]
38
3
  "username" varchar(50) [unique, not null]
39
- "email" varchar(100) [unique, not null]
4
+ "email" varchar(100) [unique, not null, check: `[email] like '%_@_%._%'`]
40
5
  "password_hash" varchar(255) [not null]
41
6
  "first_name" varchar(50)
42
7
  "last_name" varchar(50)
43
8
  "full_name" varchar(100)
44
9
  "full_name_lower" varchar(100)
45
- "date_of_birth" date
10
+ "date_of_birth" date [check: `[date_of_birth]<=dateadd(year,(-13),getdate())`]
46
11
  "created_at" datetime2 [default: `getdate()`]
47
12
  "last_login" datetime2
48
13
  "is_active" bit [default: 1]
@@ -58,8 +23,8 @@ Table "dbo"."products" {
58
23
  "product_id" int(10) [pk, not null, increment]
59
24
  "name" varchar(100) [not null]
60
25
  "description" text
61
- "price" decimal(10,2) [not null]
62
- "stock_quantity" int(10) [not null, default: 0]
26
+ "price" decimal(10,2) [not null, check: `[price]>(0)`]
27
+ "stock_quantity" int(10) [not null, check: `[stock_quantity]>=(0)`, default: 0]
63
28
  "category" varchar(50)
64
29
  "created_at" datetime2 [default: `getdate()`]
65
30
  "updated_at" datetime2 [default: `getdate()`]
@@ -74,8 +39,8 @@ Table "dbo"."orders" {
74
39
  "order_id" int(10) [pk, not null, increment]
75
40
  "user_id" int(10) [not null]
76
41
  "order_date" datetime2 [default: `getdate()`]
77
- "total_amount" decimal(12,2) [not null]
78
- "status" dbo.chk_status_status [default: 'pending']
42
+ "total_amount" decimal(12,2) [not null, check: `[total_amount]>(0)`]
43
+ "status" varchar(20) [check: `[status]='cancelled' OR [status]='delivered' OR [status]='shipped' OR [status]='processing' OR [status]='pending'`, default: 'pending']
79
44
  "shipping_address" text [not null]
80
45
  "billing_address" text [not null]
81
46
 
@@ -88,8 +53,8 @@ Table "dbo"."order_items" {
88
53
  "order_item_id" int(10) [pk, not null, increment]
89
54
  "order_id" int(10) [unique, not null]
90
55
  "product_id" int(10) [unique, not null]
91
- "quantity" int(10) [not null]
92
- "unit_price" decimal(10,2) [not null]
56
+ "quantity" int(10) [not null, check: `[quantity]>(0)`]
57
+ "unit_price" decimal(10,2) [not null, check: `[unit_price]>(0)`]
93
58
 
94
59
  Indexes {
95
60
  (order_id, product_id) [type: nonclustered, name: "idx_order_items_order_product"]
@@ -183,11 +148,15 @@ Table "dbo"."gender_reference" {
183
148
  Table "dbo"."user_define_data_types" {
184
149
  "id" int(10) [pk, not null, increment]
185
150
  "name" nvarchar(50)
186
- "gender" dbo.chk_gender_gender
151
+ "gender" nvarchar(10) [check: `[gender]='Other' OR [gender]='Female' OR [gender]='Male'`]
187
152
  "age_start" int(10)
188
153
  "age_end" int(10)
189
154
  "height" float(53)
190
155
  "weight" float(53)
156
+
157
+ Checks {
158
+ `[age_start]<=[age_end]` [name: 'chk_age_range']
159
+ }
191
160
  }
192
161
 
193
162
  Table "dbo"."table_with_comments" {
@@ -214,20 +183,28 @@ Table "dbo"."Books" {
214
183
  }
215
184
 
216
185
  Table "dbo"."AddressInfo" {
217
- "AddressID" dbo.CK_Address_Valid_AddressID_AddressFormatID [not null]
218
- "AddressFormatID" dbo.CK_Address_Valid_AddressID_AddressFormatID [not null]
186
+ "AddressID" uniqueidentifier(16) [not null]
187
+ "AddressFormatID" uniqueidentifier(16) [not null]
188
+
189
+ Checks {
190
+ `([AddressID]='176029FA-D6D3-49E1-A48C-000000000002' OR [AddressID]='176029FA-D6D3-49E1-A48C-000000000001') AND ([AddressFormatID]='176029FA-D6D3-49E1-A48C-000000000002' OR [AddressFormatID]='176029FA-D6D3-49E1-A48C-000000000001')` [name: 'CK_Address_Valid']
191
+ }
219
192
  }
220
193
 
221
194
  Table "dbo"."AddressInfo2" {
222
- "A1" dbo.CK_Address_Valid2_A1 [not null]
223
- "A2" dbo.CK_Address_Valid2_A2_A3 [not null]
224
- "A3" dbo.CK_Address_Valid2_A2_A3 [not null]
225
- "A4" dbo.CK_Address_Valid2_A4 [not null]
195
+ "A1" uniqueidentifier(16) [not null]
196
+ "A2" uniqueidentifier(16) [not null]
197
+ "A3" uniqueidentifier(16) [not null]
198
+ "A4" uniqueidentifier(16) [not null]
199
+
200
+ Checks {
201
+ `([A1]='333' OR [A1]='2222' OR [A1]='1111') AND ([A2]='2222' OR [A2]='1111') AND ([A3]='1111' OR [A3]='2222') AND ([A4]='3333' OR [A4]='2222')` [name: 'CK_Address_Valid2']
202
+ }
226
203
  }
227
204
 
228
205
  Table "dbo"."TestDescriptionTable" {
229
206
  "Id" int(10) [note: 'Primary key identifier.']
230
- "Name" nvarchar(100) [note: 'Name of the entity.']
207
+ "Name" nvarchar(100) [check: `len([Name])>(6)`, note: 'Name of the entity.']
231
208
  Note: 'This is the custom comment name on table.'
232
209
  }
233
210
 
@@ -336,7 +336,7 @@ GO
336
336
 
337
337
  CREATE TABLE TestDescriptionTable (
338
338
  Id INT,
339
- Name NVARCHAR(100)
339
+ Name NVARCHAR(100) CONSTRAINT chk_name_len CHECK (LEN(Name) > 6)
340
340
  );
341
341
 
342
342
  EXEC sp_addextendedproperty
@@ -358,3 +358,4 @@ EXEC sp_addextendedproperty
358
358
  @level0type = N'SCHEMA', @level0name = 'dbo',
359
359
  @level1type = N'TABLE', @level1name = 'TestDescriptionTable',
360
360
  @level2type = N'COLUMN', @level2name = 'Name';
361
+ GO
@@ -136,9 +136,13 @@ Table "orders" {
136
136
  Table "products" {
137
137
  "id" "int unsigned" [pk, not null, increment]
138
138
  "price" decimal(10,2) [not null]
139
- "quantity" int [not null]
140
- "total_value" "decimal(10,2) GENERATED ALWAYS AS ((`price` * `quantity`)) STORED"
139
+ "quantity" int [not null, check: ``quantity` < 10000`]
140
+ "total_value" "decimal(10,2) GENERATED ALWAYS AS ((`price` * `quantity`)) STORED" [check: ``total_value` > 0`]
141
141
  "updated_at" "timestamp on update CURRENT_TIMESTAMP" [default: `CURRENT_TIMESTAMP`]
142
+
143
+ Checks {
144
+ `(`price` > 0) and (`price` < 1000000)` [name: 'products_chk_1']
145
+ }
142
146
  }
143
147
 
144
148
  Table "sqrt_triangle" {
@@ -169,6 +173,10 @@ Table "users" {
169
173
  "created_at" timestamp [default: `CURRENT_TIMESTAMP`]
170
174
  "last_login" timestamp [default: `CURRENT_TIMESTAMP`]
171
175
  "is_active" tinyint(1) [default: 1]
176
+
177
+ Checks {
178
+ ``created_at` <= `last_login`` [name: 'chk_last_login']
179
+ }
172
180
  }
173
181
 
174
182
  Ref "fk_test_composite":"composite_key_2".("id2_1", "id2_2") < "composite_key_1".("id1_1", "id1_2")
@@ -9,15 +9,21 @@ create table users (
9
9
  date_of_birth date,
10
10
  created_at timestamp default current_timestamp,
11
11
  last_login timestamp default now(),
12
- is_active tinyint(1) default 1
12
+ is_active tinyint(1) default 1,
13
+
14
+ constraint chk_last_login
15
+ check (created_at <= last_login)
13
16
  );
14
17
 
15
18
  create table products (
16
19
  id int unsigned primary key auto_increment,
17
- price decimal(10,2) not null,
20
+ price decimal(10,2) not null check (price > 0 AND price < 1000000),
18
21
  quantity int not null,
19
22
  total_value decimal(10,2) generated always as ((price * quantity)) stored,
20
- updated_at timestamp default current_timestamp on update current_timestamp
23
+ updated_at timestamp default current_timestamp on update current_timestamp,
24
+
25
+ constraint max_quantity check (quantity < 10000),
26
+ check (total_value > 0)
21
27
  );
22
28
 
23
29
  create table orders (
@@ -37,12 +37,12 @@ Enum "gender_type" {
37
37
  Table "users" {
38
38
  "user_id" int4 [pk, not null, increment]
39
39
  "username" varchar(50) [unique, not null]
40
- "email" varchar(100) [unique, not null]
40
+ "email" varchar(100) [unique, not null, check: `(email)::text ~* '^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}$'::text`]
41
41
  "password_hash" varchar(255) [not null]
42
42
  "first_name" varchar(50)
43
43
  "last_name" varchar(50)
44
44
  "full_name" varchar(100)
45
- "date_of_birth" date
45
+ "date_of_birth" date [check: `date_of_birth <= (CURRENT_DATE - '13 years'::interval)`]
46
46
  "created_at" timestamptz [default: `CURRENT_TIMESTAMP`]
47
47
  "last_login" timestamptz
48
48
  "is_active" bool [default: true]
@@ -58,13 +58,17 @@ Table "products" {
58
58
  "product_id" int4 [pk, not null, increment]
59
59
  "name" varchar(100) [not null]
60
60
  "description" text
61
- "price" numeric(10,2) [not null]
62
- "stock_quantity" int4 [not null, default: 0]
61
+ "price" numeric(10,2) [not null, check: `price > (0)::numeric`]
62
+ "stock_quantity" int4 [not null, check: `stock_quantity >= 0`, default: 0]
63
63
  "category" varchar(50)
64
64
  "created_at" timestamptz [default: `CURRENT_TIMESTAMP`]
65
65
  "updated_at" timestamptz [default: `CURRENT_TIMESTAMP`]
66
66
  "is_available" bool [default: true]
67
67
 
68
+ Checks {
69
+ `created_at <= updated_at` [name: 'chk_created_at']
70
+ }
71
+
68
72
  Indexes {
69
73
  category [type: btree, name: "idx_products_category"]
70
74
  }
@@ -74,8 +78,8 @@ Table "orders" {
74
78
  "order_id" int4 [pk, not null, increment]
75
79
  "user_id" int4 [not null]
76
80
  "order_date" timestamptz [default: `CURRENT_TIMESTAMP`]
77
- "total_amount" numeric(12,2) [not null]
78
- "status" varchar(20) [default: 'pending']
81
+ "total_amount" numeric(12,2) [not null, check: `total_amount > (0)::numeric`]
82
+ "status" varchar(20) [check: `(status)::text = ANY ((ARRAY['pending'::character varying, 'processing'::character varying, 'shipped'::character varying, 'delivered'::character varying, 'cancelled'::character varying])::text[])`, default: 'pending']
79
83
  "shipping_address" text [not null]
80
84
  "billing_address" text [not null]
81
85
 
@@ -88,8 +92,8 @@ Table "order_items" {
88
92
  "order_item_id" int4 [pk, not null, increment]
89
93
  "order_id" int4 [not null]
90
94
  "product_id" int4 [not null]
91
- "quantity" int4 [not null]
92
- "unit_price" numeric(10,2) [not null]
95
+ "quantity" int4 [not null, check: `quantity > 0`]
96
+ "unit_price" numeric(10,2) [not null, check: `unit_price > (0)::numeric`]
93
97
 
94
98
  Indexes {
95
99
  (order_id, product_id) [type: btree, name: "uq_order_product"]
@@ -130,8 +134,8 @@ Table "user_define_data_types" {
130
134
  "name" varchar(50)
131
135
  "gender" gender_type
132
136
  "age" int4range
133
- "height" float8
134
- "weight" float8
137
+ "height" float8 [check: `height > (0)::double precision`]
138
+ "weight" float8 [check: `weight > (0)::double precision`]
135
139
  }
136
140
 
137
141
  Table "table_with_comments" {
@@ -38,7 +38,8 @@ CREATE TABLE products (
38
38
  updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
39
39
  is_available BOOLEAN DEFAULT TRUE,
40
40
  CONSTRAINT chk_price_positive CHECK (price > 0),
41
- CONSTRAINT chk_stock_non_negative CHECK (stock_quantity >= 0)
41
+ CONSTRAINT chk_stock_non_negative CHECK (stock_quantity >= 0),
42
+ CONSTRAINT chk_created_at CHECK (created_at <= updated_at)
42
43
  );
43
44
 
44
45
  -- Create an index on the category column for faster filtering
@@ -117,8 +118,8 @@ CREATE TABLE user_define_data_types (
117
118
  name VARCHAR(50),
118
119
  gender gender_type,
119
120
  age int4range, -- Using built-in int4range for age range
120
- height FLOAT,
121
- weight FLOAT
121
+ height FLOAT CHECK (height > 0),
122
+ weight FLOAT CONSTRAINT chk_positive_weight CHECK (weight > 0)
122
123
  );
123
124
 
124
125
  -- Create table with comments
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dbml/cli",
3
- "version": "5.0.0-alpha.0",
3
+ "version": "5.1.0",
4
4
  "description": "",
5
5
  "main": "lib/index.js",
6
6
  "license": "Apache-2.0",
@@ -26,8 +26,8 @@
26
26
  ],
27
27
  "dependencies": {
28
28
  "@babel/cli": "^7.21.0",
29
- "@dbml/connector": "^5.0.0-alpha.0",
30
- "@dbml/core": "^5.0.0-alpha.0",
29
+ "@dbml/connector": "^5.1.0",
30
+ "@dbml/core": "^5.1.0",
31
31
  "bluebird": "^3.5.5",
32
32
  "chalk": "^2.4.2",
33
33
  "commander": "^2.20.0",
@@ -55,7 +55,7 @@
55
55
  "^.+\\.js$": "babel-jest"
56
56
  }
57
57
  },
58
- "gitHead": "630548187910efa893579e80ab07f447df1ef61e",
58
+ "gitHead": "376dca507512a3fe549f630e6f22d7d339939183",
59
59
  "engines": {
60
60
  "node": ">=18"
61
61
  }