fraiseql 2.2.1 → 2.9.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/dist/index.mjs CHANGED
@@ -148,10 +148,12 @@ function extractFunctionSignature(_name, params, returnType) {
148
148
 
149
149
  // src/registry.ts
150
150
  var VALID_REST_METHODS = /* @__PURE__ */ new Set(["GET", "POST", "PUT", "PATCH", "DELETE"]);
151
- function normaliseConfig(config2) {
151
+ var VALID_INPUT_STYLES = /* @__PURE__ */ new Set(["flatten", "jsonb"]);
152
+ var INJECT_KEY_RE = /^[A-Za-z_][A-Za-z0-9_]*$/;
153
+ var INJECT_SOURCE_RE = /^jwt:[A-Za-z_][A-Za-z0-9_]*$/;
154
+ function normaliseConfig(config, argNames) {
152
155
  const keyMap = {
153
156
  sqlSource: "sql_source",
154
- sqlSourceDispatch: "sql_source_dispatch",
155
157
  autoParams: "auto_params",
156
158
  jsonbColumn: "jsonb_column",
157
159
  cacheTtlSeconds: "cache_ttl_seconds",
@@ -160,32 +162,65 @@ function normaliseConfig(config2) {
160
162
  relayCursorColumn: "relay_cursor_column",
161
163
  relayCursorType: "relay_cursor_type",
162
164
  requiresRole: "requires_role",
163
- additionalViews: "additional_views"
165
+ additionalViews: "additional_views",
166
+ inputStyle: "input_style",
167
+ changelogPreImage: "changelog_pre_image"
164
168
  };
165
- const hasRestPath = "restPath" in config2 && config2.restPath != null;
166
- const hasRestMethod = "restMethod" in config2 && config2.restMethod != null;
169
+ const hasRestPath = "restPath" in config && config.restPath != null;
170
+ const hasRestMethod = "restMethod" in config && config.restMethod != null;
167
171
  if (hasRestMethod && !hasRestPath) {
168
172
  throw new Error("restMethod requires restPath to be set");
169
173
  }
170
174
  if (hasRestMethod) {
171
- const method = String(config2.restMethod).toUpperCase();
175
+ const method = String(config.restMethod).toUpperCase();
172
176
  if (!VALID_REST_METHODS.has(method)) {
173
177
  throw new Error(
174
- `Invalid REST method '${config2.restMethod}'. Must be one of: ${[...VALID_REST_METHODS].join(", ")}`
178
+ `Invalid REST method '${config.restMethod}'. Must be one of: ${[...VALID_REST_METHODS].join(", ")}`
179
+ );
180
+ }
181
+ }
182
+ if ("changelog" in config && typeof config.changelog !== "boolean") {
183
+ throw new Error(`changelog must be a boolean (got ${typeof config.changelog})`);
184
+ }
185
+ if ("changelogPreImage" in config && typeof config.changelogPreImage !== "boolean") {
186
+ throw new Error(
187
+ `changelogPreImage must be a boolean (got ${typeof config.changelogPreImage})`
188
+ );
189
+ }
190
+ if ("inputStyle" in config) {
191
+ if (typeof config.inputStyle !== "string") {
192
+ throw new Error(`inputStyle must be a string (got ${typeof config.inputStyle})`);
193
+ }
194
+ if (!VALID_INPUT_STYLES.has(config.inputStyle)) {
195
+ throw new Error(
196
+ `inputStyle must be one of ${[...VALID_INPUT_STYLES].join(", ")} (got '${config.inputStyle}')`
175
197
  );
176
198
  }
177
199
  }
178
200
  const result = {};
179
- for (const [key, value] of Object.entries(config2)) {
201
+ for (const [key, value] of Object.entries(config)) {
180
202
  if (key === "restPath" || key === "restMethod") {
181
203
  continue;
182
204
  } else if (key === "inject" && value !== null && typeof value === "object") {
183
205
  const injected = {};
184
206
  for (const [param, spec] of Object.entries(value)) {
185
- const colonIdx = spec.indexOf(":");
186
- if (colonIdx > 0) {
187
- injected[param] = { source: spec.slice(0, colonIdx), claim: spec.slice(colonIdx + 1) };
207
+ if (!INJECT_KEY_RE.test(param)) {
208
+ throw new Error(
209
+ `inject key '${param}' is not a valid identifier. Keys must start with a letter or underscore and contain only letters, digits, and underscores.`
210
+ );
211
+ }
212
+ if (argNames?.has(param)) {
213
+ throw new Error(
214
+ `inject key '${param}' conflicts with a declared GraphQL argument of the same name. Use a different parameter name.`
215
+ );
216
+ }
217
+ if (typeof spec !== "string" || !INJECT_SOURCE_RE.test(spec)) {
218
+ throw new Error(
219
+ `inject source '${String(spec)}' for param '${param}' is invalid. Supported format: 'jwt:<claim_name>' (e.g. 'jwt:org_id', 'jwt:sub').`
220
+ );
188
221
  }
222
+ const colonIdx = spec.indexOf(":");
223
+ injected[param] = { source: spec.slice(0, colonIdx), claim: spec.slice(colonIdx + 1) };
189
224
  }
190
225
  result["inject_params"] = injected;
191
226
  } else if (key === "deprecated" && typeof value === "string") {
@@ -195,9 +230,9 @@ function normaliseConfig(config2) {
195
230
  }
196
231
  }
197
232
  if (hasRestPath) {
198
- const method = hasRestMethod ? String(config2.restMethod).toUpperCase() : void 0;
233
+ const method = hasRestMethod ? String(config.restMethod).toUpperCase() : void 0;
199
234
  result["rest"] = {
200
- path: config2.restPath,
235
+ path: config.restPath,
201
236
  method
202
237
  };
203
238
  }
@@ -250,32 +285,32 @@ var SchemaRegistry = class {
250
285
  * @param description - Optional query description
251
286
  * @param config - Additional configuration (sql_source, etc.)
252
287
  */
253
- static registerQuery(name, returnType, returnsList, nullable, args, description, config2) {
288
+ static registerQuery(name, returnType, returnsList, nullable, args, description, config) {
254
289
  if (this.queries.has(name)) {
255
290
  throw new Error(
256
291
  `Query '${name}' is already registered. Each name must be unique within a schema.`
257
292
  );
258
293
  }
259
294
  const cleanType = returnsList ? returnType.replace(/[[\]!]/g, "") : returnType;
260
- if (config2?.relay) {
295
+ if (config?.relay) {
261
296
  if (!returnsList) {
262
297
  throw new Error(
263
298
  `registerQuery('${name}'): relay: true requires returns_list to be true. Relay connections only apply to list queries.`
264
299
  );
265
300
  }
266
- if (!config2.sqlSource) {
301
+ if (!config.sqlSource) {
267
302
  throw new Error(
268
303
  `registerQuery('${name}'): relay: true requires sqlSource to be set. The compiler needs the view name to derive the cursor column.`
269
304
  );
270
305
  }
271
- if (config2.autoParams) {
272
- const ap = { ...config2.autoParams };
306
+ if (config.autoParams) {
307
+ const ap = { ...config.autoParams };
273
308
  delete ap["limit"];
274
309
  delete ap["offset"];
275
- config2 = { ...config2, autoParams: ap };
310
+ config = { ...config, autoParams: ap };
276
311
  }
277
312
  }
278
- const normalisedConfig = config2 ? normaliseConfig(config2) : void 0;
313
+ const normalisedConfig = config ? normaliseConfig(config, new Set(args.map((a) => a.name))) : void 0;
279
314
  if (normalisedConfig?.rest) {
280
315
  const rest = normalisedConfig.rest;
281
316
  if (!rest.method) {
@@ -303,14 +338,14 @@ var SchemaRegistry = class {
303
338
  * @param description - Optional mutation description
304
339
  * @param config - Additional configuration (sql_source, operation, etc.)
305
340
  */
306
- static registerMutation(name, returnType, returnsList, nullable, args, description, config2) {
341
+ static registerMutation(name, returnType, returnsList, nullable, args, description, config) {
307
342
  if (this.mutations.has(name)) {
308
343
  throw new Error(
309
344
  `Mutation '${name}' is already registered. Each name must be unique within a schema.`
310
345
  );
311
346
  }
312
347
  const cleanType = returnsList ? returnType.replace(/[[\]!]/g, "") : returnType;
313
- const normalisedConfig = config2 ? normaliseConfig(config2) : void 0;
348
+ const normalisedConfig = config ? normaliseConfig(config, new Set(args.map((a) => a.name))) : void 0;
314
349
  if (normalisedConfig?.rest) {
315
350
  const rest = normalisedConfig.rest;
316
351
  if (!rest.method) {
@@ -340,7 +375,7 @@ var SchemaRegistry = class {
340
375
  * @param description - Optional subscription description
341
376
  * @param config - Additional configuration (topic, operation, etc.)
342
377
  */
343
- static registerSubscription(name, entityType, nullable, args, description, config2) {
378
+ static registerSubscription(name, entityType, nullable, args, description, config) {
344
379
  if (this.subscriptions.has(name)) {
345
380
  throw new Error(
346
381
  `Subscription '${name}' is already registered. Each name must be unique within a schema.`
@@ -352,7 +387,7 @@ var SchemaRegistry = class {
352
387
  nullable,
353
388
  arguments: args,
354
389
  description,
355
- ...config2
390
+ ...config
356
391
  });
357
392
  }
358
393
  /**
@@ -649,11 +684,11 @@ function generateCrudOperations(typeName, fields, crud, sqlSource, cascade) {
649
684
  nullable: f.nullable
650
685
  }));
651
686
  SchemaRegistry.registerInputType(inputName, inputFields, `Input for creating a new ${typeName}.`);
652
- const config2 = {
687
+ const config = {
653
688
  sql_source: `fn_create_${snake}`,
654
689
  operation: "INSERT"
655
690
  };
656
- if (cascade) config2.cascade = true;
691
+ if (cascade) config.cascade = true;
657
692
  SchemaRegistry.registerMutation(
658
693
  `create_${snake}`,
659
694
  typeName,
@@ -661,7 +696,7 @@ function generateCrudOperations(typeName, fields, crud, sqlSource, cascade) {
661
696
  false,
662
697
  [{ name: "input", type: inputName, nullable: false }],
663
698
  `Create a new ${typeName}.`,
664
- config2
699
+ config
665
700
  );
666
701
  }
667
702
  if (ops.has("update")) {
@@ -672,11 +707,11 @@ function generateCrudOperations(typeName, fields, crud, sqlSource, cascade) {
672
707
  ...writableFields.map((f) => ({ name: f.name, type: f.type, nullable: true }))
673
708
  ];
674
709
  SchemaRegistry.registerInputType(inputName, inputFields, `Input for updating an existing ${typeName}.`);
675
- const config2 = {
710
+ const config = {
676
711
  sql_source: `fn_update_${snake}`,
677
712
  operation: "UPDATE"
678
713
  };
679
- if (cascade) config2.cascade = true;
714
+ if (cascade) config.cascade = true;
680
715
  SchemaRegistry.registerMutation(
681
716
  `update_${snake}`,
682
717
  typeName,
@@ -684,15 +719,15 @@ function generateCrudOperations(typeName, fields, crud, sqlSource, cascade) {
684
719
  true,
685
720
  [{ name: "input", type: inputName, nullable: false }],
686
721
  `Update an existing ${typeName}.`,
687
- config2
722
+ config
688
723
  );
689
724
  }
690
725
  if (ops.has("delete")) {
691
- const config2 = {
726
+ const config = {
692
727
  sql_source: `fn_delete_${snake}`,
693
728
  operation: "DELETE"
694
729
  };
695
- if (cascade) config2.cascade = true;
730
+ if (cascade) config.cascade = true;
696
731
  SchemaRegistry.registerMutation(
697
732
  `delete_${snake}`,
698
733
  typeName,
@@ -700,7 +735,7 @@ function generateCrudOperations(typeName, fields, crud, sqlSource, cascade) {
700
735
  false,
701
736
  [{ name: pkField.name, type: pkField.type, nullable: false }],
702
737
  `Delete a ${typeName}.`,
703
- config2
738
+ config
704
739
  );
705
740
  }
706
741
  }
@@ -718,7 +753,7 @@ function Type(_config) {
718
753
  return constructor;
719
754
  };
720
755
  }
721
- function Query(config2) {
756
+ function Query(config) {
722
757
  return function(_target, propertyKey, descriptor) {
723
758
  const originalMethod = descriptor.value;
724
759
  const methodName = propertyKey;
@@ -733,12 +768,12 @@ function Query(config2) {
733
768
  [],
734
769
  // Placeholder
735
770
  originalMethod?.toString?.().split("\n")[0] ?? void 0,
736
- config2
771
+ config
737
772
  );
738
773
  return descriptor;
739
774
  };
740
775
  }
741
- function Mutation(config2) {
776
+ function Mutation(config) {
742
777
  return function(_target, propertyKey, descriptor) {
743
778
  const originalMethod = descriptor.value;
744
779
  const methodName = propertyKey;
@@ -753,28 +788,28 @@ function Mutation(config2) {
753
788
  [],
754
789
  // Placeholder
755
790
  originalMethod?.toString?.().split("\n")[0] ?? void 0,
756
- config2
791
+ config
757
792
  );
758
793
  return descriptor;
759
794
  };
760
795
  }
761
- function enum_(name, values, config2) {
796
+ function enum_(name, values, config) {
762
797
  const enumValues = Object.keys(values).map((key) => ({
763
798
  name: key
764
799
  }));
765
- SchemaRegistry.registerEnum(name, enumValues, config2?.description);
800
+ SchemaRegistry.registerEnum(name, enumValues, config?.description);
766
801
  return values;
767
802
  }
768
- function interface_(name, fields, config2) {
769
- SchemaRegistry.registerInterface(name, fields, config2?.description);
803
+ function interface_(name, fields, config) {
804
+ SchemaRegistry.registerInterface(name, fields, config?.description);
770
805
  return {};
771
806
  }
772
- function union(name, memberTypes, config2) {
773
- SchemaRegistry.registerUnion(name, memberTypes, config2?.description);
807
+ function union(name, memberTypes, config) {
808
+ SchemaRegistry.registerUnion(name, memberTypes, config?.description);
774
809
  return {};
775
810
  }
776
- function input(name, fields, config2) {
777
- SchemaRegistry.registerInputType(name, fields, config2?.description);
811
+ function input(name, fields, config) {
812
+ SchemaRegistry.registerInputType(name, fields, config?.description);
778
813
  return {};
779
814
  }
780
815
  function registerTypeFields(typeName, fields, description, options) {
@@ -783,55 +818,10 @@ function registerTypeFields(typeName, fields, description, options) {
783
818
  generateCrudOperations(typeName, fields, options.crud, options.sqlSource, options.cascade);
784
819
  }
785
820
  }
786
- var SAFE_SQL_IDENT = /^[A-Za-z_][A-Za-z0-9_$]*$/;
787
- function registerQuery(name, returnTypeOrConfig, returnsList, nullable, args, description, config2) {
788
- if (typeof returnTypeOrConfig === "object" && returnTypeOrConfig !== null) {
789
- const cfg = returnTypeOrConfig;
790
- const dispatch = cfg.sqlSourceDispatch;
791
- if (dispatch !== void 0) {
792
- if (cfg.sqlSource !== void 0) {
793
- throw new Error(
794
- `registerQuery('${name}'): sqlSource and sqlSourceDispatch are mutually exclusive.`
795
- );
796
- }
797
- const dispatchArg = dispatch.argument;
798
- const queryArgs = cfg.arguments ?? [];
799
- const argDef = queryArgs.find((a) => a.name === dispatchArg);
800
- if (argDef === void 0) {
801
- throw new Error(
802
- `registerQuery('${name}'): sqlSourceDispatch argument '${dispatchArg}' not found in arguments list.`
803
- );
804
- }
805
- if (argDef.nullable) {
806
- throw new Error(
807
- `registerQuery('${name}'): sqlSourceDispatch argument '${dispatchArg}' must be non-nullable.`
808
- );
809
- }
810
- if (dispatch.mapping !== void 0) {
811
- for (const [key, value] of Object.entries(dispatch.mapping)) {
812
- if (!SAFE_SQL_IDENT.test(value)) {
813
- throw new Error(
814
- `registerQuery('${name}'): sql_source_dispatch mapping value '${value}' for key '${key}' is not a safe SQL identifier.`
815
- );
816
- }
817
- }
818
- }
819
- }
820
- const { returnType, returnsList: rl, nullable: nl, arguments: qArgs, description: desc, ...rest } = cfg;
821
- SchemaRegistry.registerQuery(
822
- name,
823
- returnType,
824
- rl ?? false,
825
- nl ?? false,
826
- qArgs ?? [],
827
- desc,
828
- rest
829
- );
830
- return;
831
- }
832
- SchemaRegistry.registerQuery(name, returnTypeOrConfig, returnsList ?? false, nullable ?? false, args ?? [], description, config2);
821
+ function registerQuery(name, returnType, returnsList, nullable, args, description, config) {
822
+ SchemaRegistry.registerQuery(name, returnType, returnsList, nullable, args, description, config);
833
823
  }
834
- function registerMutation(name, returnType, returnsList, nullable, args, description, config2) {
824
+ function registerMutation(name, returnType, returnsList, nullable, args, description, config) {
835
825
  SchemaRegistry.registerMutation(
836
826
  name,
837
827
  returnType,
@@ -839,14 +829,14 @@ function registerMutation(name, returnType, returnsList, nullable, args, descrip
839
829
  nullable,
840
830
  args,
841
831
  description,
842
- config2
832
+ config
843
833
  );
844
834
  }
845
- function Subscription(config2) {
835
+ function Subscription(config) {
846
836
  return function(_target, propertyKey, descriptor) {
847
837
  const originalMethod = descriptor.value;
848
838
  const methodName = propertyKey;
849
- const entityType = config2?.entityType || "Subscription";
839
+ const entityType = config?.entityType || "Subscription";
850
840
  SchemaRegistry.registerSubscription(
851
841
  methodName,
852
842
  entityType,
@@ -855,13 +845,13 @@ function Subscription(config2) {
855
845
  [],
856
846
  // Placeholder for arguments
857
847
  originalMethod?.toString?.().split("\n")[0] ?? void 0,
858
- config2
848
+ config
859
849
  );
860
850
  return descriptor;
861
851
  };
862
852
  }
863
- function registerSubscription(name, entityType, nullable, args, description, config2) {
864
- SchemaRegistry.registerSubscription(name, entityType, nullable, args, description, config2);
853
+ function registerSubscription(name, entityType, nullable, args, description, config) {
854
+ SchemaRegistry.registerSubscription(name, entityType, nullable, args, description, config);
865
855
  }
866
856
  function Scalar(target) {
867
857
  if (!isCustomScalarSubclass(target)) {
@@ -921,12 +911,6 @@ function validateSchemaBeforeExport(schema) {
921
911
  );
922
912
  }
923
913
  }
924
- var ConfigHolder = class {
925
- static pendingConfig = null;
926
- };
927
- function config(configObj) {
928
- ConfigHolder.pendingConfig = configObj;
929
- }
930
914
  function exportSchema(outputPath, options = {}) {
931
915
  const { pretty = true } = options;
932
916
  const schema = SchemaRegistry.getSchema();
@@ -1031,15 +1015,15 @@ var DEFAULT_RETRY_CONFIG = {
1031
1015
  initial_delay_ms: 100,
1032
1016
  max_delay_ms: 6e4
1033
1017
  };
1034
- function Observer(config2) {
1018
+ function Observer(config) {
1035
1019
  return function(_target, propertyKey, _descriptor) {
1036
1020
  SchemaRegistry.registerObserver(
1037
1021
  propertyKey,
1038
- config2.entity,
1039
- config2.event,
1040
- config2.actions,
1041
- config2.condition,
1042
- config2.retry
1022
+ config.entity,
1023
+ config.event,
1024
+ config.actions,
1025
+ config.condition,
1026
+ config.retry
1043
1027
  );
1044
1028
  };
1045
1029
  }
@@ -1132,7 +1116,7 @@ var RateLimitError = class extends FraiseQLError {
1132
1116
  };
1133
1117
 
1134
1118
  // src/http-retry.ts
1135
- async function executeWithRetry(fn, config2 = {}) {
1119
+ async function executeWithRetry(fn, config = {}) {
1136
1120
  const {
1137
1121
  maxAttempts = 1,
1138
1122
  baseDelayMs = 1e3,
@@ -1140,7 +1124,7 @@ async function executeWithRetry(fn, config2 = {}) {
1140
1124
  jitter = true,
1141
1125
  retryOn = [NetworkError, TimeoutError],
1142
1126
  onRetry
1143
- } = config2;
1127
+ } = config;
1144
1128
  let lastError;
1145
1129
  for (let attempt = 1; attempt <= maxAttempts; attempt++) {
1146
1130
  try {
@@ -1173,13 +1157,13 @@ var FraiseQLClient = class {
1173
1157
  extraHeaders;
1174
1158
  fetchFn;
1175
1159
  constructor(urlOrConfig) {
1176
- const config2 = typeof urlOrConfig === "string" ? { url: urlOrConfig } : urlOrConfig;
1177
- this.url = config2.url;
1178
- this.authorization = config2.authorization;
1179
- this.timeoutMs = config2.timeoutMs ?? 3e4;
1180
- this.retry = config2.retry ?? {};
1181
- this.extraHeaders = config2.headers ?? {};
1182
- this.fetchFn = config2.fetch ?? globalThis.fetch.bind(globalThis);
1160
+ const config = typeof urlOrConfig === "string" ? { url: urlOrConfig } : urlOrConfig;
1161
+ this.url = config.url;
1162
+ this.authorization = config.authorization;
1163
+ this.timeoutMs = config.timeoutMs ?? 3e4;
1164
+ this.retry = config.retry ?? {};
1165
+ this.extraHeaders = config.headers ?? {};
1166
+ this.fetchFn = config.fetch ?? globalThis.fetch.bind(globalThis);
1183
1167
  }
1184
1168
  async resolveAuth() {
1185
1169
  if (this.authorization === void 0) return void 0;
@@ -1268,7 +1252,7 @@ var FraiseQLClient = class {
1268
1252
  };
1269
1253
 
1270
1254
  // src/index.ts
1271
- var version = "2.0.0-alpha.1";
1255
+ var version = "2.9.0";
1272
1256
  export {
1273
1257
  AuthenticationError,
1274
1258
  CustomScalar,
@@ -1288,7 +1272,6 @@ export {
1288
1272
  Subscription,
1289
1273
  TimeoutError,
1290
1274
  Type,
1291
- config,
1292
1275
  email,
1293
1276
  enum_,
1294
1277
  executeWithRetry,
package/package.json CHANGED
@@ -1,7 +1,14 @@
1
1
  {
2
2
  "name": "fraiseql",
3
- "version": "2.2.1",
3
+ "version": "2.9.0",
4
4
  "description": "FraiseQL v2 - Compiled GraphQL execution engine (schema authoring + HTTP client)",
5
+ "repository": {
6
+ "type": "git",
7
+ "url": "git+https://github.com/fraiseql/fraiseql.git",
8
+ "directory": "sdks/official/fraiseql-typescript"
9
+ },
10
+ "homepage": "https://fraiseql.dev",
11
+ "bugs": "https://github.com/fraiseql/fraiseql/issues",
5
12
  "main": "dist/index.js",
6
13
  "module": "dist/index.mjs",
7
14
  "types": "dist/index.d.ts",
@@ -46,9 +53,9 @@
46
53
  "zod": "^3.22.0"
47
54
  },
48
55
  "peerDependencies": {
49
- "ai": "^3.0.0",
50
- "@langchain/core": "^0.1.0",
51
- "@mastra/core": "^0.1.0"
56
+ "@langchain/core": "^1.1.47",
57
+ "@mastra/core": "^1.35.0",
58
+ "ai": "^6.0.185"
52
59
  },
53
60
  "peerDependenciesMeta": {
54
61
  "ai": {
@@ -62,19 +69,19 @@
62
69
  }
63
70
  },
64
71
  "devDependencies": {
65
- "@types/node": "^20.0.0",
72
+ "@langchain/core": "^1.1.47",
73
+ "@mastra/core": "^1.35.0",
74
+ "@types/node": "^25.9.1",
66
75
  "@typescript-eslint/eslint-plugin": "^8.0.0",
67
76
  "@typescript-eslint/parser": "^8.0.0",
68
- "ai": "^4.0.0",
69
- "@langchain/core": "^0.3.0",
70
- "@mastra/core": "^0.9.0",
71
- "eslint": "^9.0.0",
77
+ "ai": "^6.0.185",
78
+ "eslint": "^10.4.0",
72
79
  "msw": "^2.0.0",
73
80
  "prettier": "^3.0.0",
74
81
  "tsup": "^8.0.0",
75
82
  "tsx": "^4.0.0",
76
83
  "typescript": "^5.3.0",
77
- "vitest": "^2.0.0"
84
+ "vitest": "^4.1.6"
78
85
  },
79
86
  "engines": {
80
87
  "node": ">=18.0.0"