@systemfsoftware/stryker-js-instrumenter 8.0.0 → 8.0.2

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 CHANGED
@@ -1,5 +1,19 @@
1
1
  # @systemfsoftware/stryker-js-instrumenter
2
2
 
3
+ ## 8.0.2
4
+
5
+ ### Patch Changes
6
+
7
+ - Exported declarations that previously took `unknown` now take a defaulted type parameter: calls that omit the type argument are unchanged, and calls that were previously rejected for passing an unconstrained value are accepted. No runtime behaviour changes.
8
+
9
+ ## 8.0.1
10
+
11
+ ### Patch Changes
12
+
13
+ - Effect moves to `4.0.0-rc.116` (with `@effect/platform-node`, `@effect/platform-node-shared`, `@effect/vitest` and `@effect/opentelemetry` on the same release), the `@systemfsoftware/*` toolchain pins move to their current releases, and `vitest` 5 with `oxc-parser` 0.150 come along. Both worker bundles (`stryker-js-typescript-checker`, `stryker-js-vitest-runner`) now inline their whole runtime rather than resolving `effect`, `@effect/*` and the sibling packages from the host's tree, so a worker runs on its own copy of the effect that built it; the project's `typescript` and `vitest` remain the only imports beside Node builtins. The filter-level `arbitrary.candidate` generators that the thresholds schemas carried are gone: v4 no longer reads them, so thresholds still reject a `low` above `high` and the property tests generate the pair from the schema again. Log calls inside `Effect.catch*` handlers moved to `Effect.tapError`/`Effect.tapCause` at the same level and message. `@systemfsoftware/stryker-ignorer-interface` re-exports the 0.150 AST, where `FormalParameterRest.decorators` is now `Array<Decorator>`.
14
+
15
+ - Mutating a negated property check such as `if (!obj.prop)` no longer aborts the run with a placement error. Mutations inside `as const` expressions are generated again; previously every literal inside an `as const` object or array was silently skipped, which inflated the reported mutation score.
16
+
3
17
  ## 8.0.0
4
18
 
5
19
  ### Major Changes
package/dist/index.d.mts CHANGED
@@ -2,7 +2,7 @@ import * as Effect from 'effect/Effect';
2
2
  import * as S from 'effect/Schema';
3
3
  import { YieldableError } from 'effect/Cause';
4
4
 
5
- export declare const causeText: (cause: unknown, depth: number) => string | undefined;
5
+ export declare const causeText: <A = unknown>(cause: A, depth: number) => string | undefined;
6
6
 
7
7
  export declare interface Coverage {
8
8
  readonly static: CoverageData;
@@ -31,7 +31,7 @@ export declare const ERROR_CODES: Readonly<{
31
31
  NoSuchFileOrDirectory: 'ENOENT';
32
32
  }>;
33
33
 
34
- export declare function errorToString(error: unknown): string;
34
+ export declare function errorToString<A = unknown>(error: A): string;
35
35
 
36
36
  declare interface File_2 extends FileDescription {
37
37
  name: string;
package/dist/index.mjs CHANGED
@@ -182,6 +182,7 @@ const EXPRESSION_KINDS = /* @__PURE__ */ new Set([
182
182
  "JSXFragment",
183
183
  "Literal",
184
184
  "LogicalExpression",
185
+ "MemberExpression",
185
186
  "MetaProperty",
186
187
  "NewExpression",
187
188
  "ObjectExpression",
@@ -541,24 +542,29 @@ const COMMENT_KEYS = /* @__PURE__ */ new Set(["leadingComments", "trailingCommen
541
542
  function isCommentKey(key) {
542
543
  return typeof key === "string" && COMMENT_KEYS.has(key);
543
544
  }
545
+ function walkTraverse(root, stack, visitors) {
546
+ walk(walkableNode(root), {
547
+ enter(node, _parent, context) {
548
+ readPath(stack, node, this, context, visitors);
549
+ },
550
+ leave(_node, _parent, context) {
551
+ closePath(stack, context, visitors);
552
+ }
553
+ });
554
+ }
555
+ const toTraverseError = (error) => error instanceof Error ? error : new Error("Traversal failed", { cause: error });
556
+ const handleTraverseError = (error) => {
557
+ const err = toTraverseError(error);
558
+ if (!S.is(TraversalStopped)(err)) throw err;
559
+ };
544
560
  function traverse(root, visitors) {
545
561
  const stack = [];
546
562
  try {
547
- walk(walkableNode(root), {
548
- enter(node, _parent, context) {
549
- readPath(stack, node, this, context, visitors);
550
- },
551
- leave(_node, _parent, context) {
552
- closePath(stack, context, visitors);
553
- }
554
- });
563
+ walkTraverse(root, stack, visitors);
555
564
  } catch (error) {
556
- rethrowUnlessStopped(error);
565
+ handleTraverseError(error);
557
566
  }
558
567
  }
559
- const rethrowUnlessStopped = (error) => {
560
- if (!S.is(TraversalStopped)(error)) throw error;
561
- };
562
568
  const readPath = (stack, node, controls, context, visitors) => {
563
569
  if (isCommentKey(context.key)) return;
564
570
  const path = createPath(node, parentOf(stack), controls, context);
@@ -626,7 +632,7 @@ function writeInto(parent, key, index, replacement) {
626
632
  writeAtKey(parent, key, index, replacement);
627
633
  }
628
634
  function writeAtKey(parent, key, index, replacement) {
629
- Match.value(key).pipe(Match.when(Predicate.isString, (slot) => writeAtSlot(parent, slot, index, replacement)), Match.orElse(() => void 0));
635
+ if (Predicate.isString(key)) writeAtSlot(parent, key, index, replacement);
630
636
  }
631
637
  function writeAtSlot(parent, key, index, replacement) {
632
638
  Match.value(index).pipe(Match.when(Match.null, () => overwrite(parent, key, replacement)), Match.orElse((position) => writeElement(parent[key], position, replacement)));
@@ -712,17 +718,16 @@ function isRangedBaseNode(value) {
712
718
  function isNonEmptyArray(value) {
713
719
  return Array.isArray(value) && value.length > 0;
714
720
  }
715
- function hasField(value, key) {
716
- return isPlainRecord(value) && key in value;
721
+ function hasContentField(value) {
722
+ return isPlainRecord(value) && "content" in value;
717
723
  }
718
- function hasContent(value) {
719
- return hasField(value, "content");
720
- }
721
- function hasHtml(value) {
722
- return hasField(value, "html");
724
+ function hasHtmlField(value) {
725
+ return isPlainRecord(value) && "html" in value;
723
726
  }
727
+ const readRecordField = (record, key) => record[key];
724
728
  function fieldOf$1(value, key) {
725
- return Match.value(value).pipe(Match.when(isPlainRecord, (record) => record[key]), Match.orElse(() => void 0));
729
+ if (!isPlainRecord(value)) return void 0;
730
+ return readRecordField(value, key);
726
731
  }
727
732
  function appendIfDefined(values, value) {
728
733
  if (value !== void 0) values.push(value);
@@ -997,12 +1002,12 @@ function isTextRange(value) {
997
1002
  function isTemplateExpressionTag(value) {
998
1003
  return isTypedRecord(value) && TEMPLATE_EXPRESSION_TYPES[value["type"]] === true;
999
1004
  }
1000
- /**
1001
- * The first child of a `<script>` element node. A template `<script>` tag
1002
- * carries its code as that single `Text` child.
1003
- */
1005
+ const firstChild = (element) => {
1006
+ const children = element["children"];
1007
+ return isNonEmptyArray(children) ? Option.getOrUndefined(Arr.head(children)) : void 0;
1008
+ };
1004
1009
  function scriptChild(node) {
1005
- return Match.value(node).pipe(Match.when(isScriptElement, (element) => Match.value(element["children"]).pipe(Match.when(isNonEmptyArray, (values) => Option.getOrUndefined(Arr.head(values))), Match.orElse(() => void 0))), Match.orElse(() => void 0));
1010
+ return isScriptElement(node) ? firstChild(node) : void 0;
1006
1011
  }
1007
1012
  function tryGetScriptRangeFromElement(node) {
1008
1013
  return Match.value(scriptChild(node)).pipe(Match.when(isTextRange, (range) => ({
@@ -1012,14 +1017,14 @@ function tryGetScriptRangeFromElement(node) {
1012
1017
  })), Match.orElse(() => void 0));
1013
1018
  }
1014
1019
  function templateExpressionRange(node) {
1015
- return Match.value(node).pipe(Match.when(isTemplateExpressionTag, (tag) => rangedExpressionOf(tag["expression"])), Match.orElse(() => void 0));
1020
+ return isTemplateExpressionTag(node) ? rangedExpressionOf(node["expression"]) : void 0;
1016
1021
  }
1017
1022
  function rangedExpressionOf(payload) {
1018
- return Match.value(payload).pipe(Match.when(isRangedBaseNode, (expression) => ({
1019
- start: expression.start,
1020
- end: expression.end,
1023
+ if (isRangedBaseNode(payload)) return {
1024
+ start: payload.start,
1025
+ end: payload.end,
1021
1026
  isExpression: true
1022
- })), Match.orElse(() => void 0));
1027
+ };
1023
1028
  }
1024
1029
  /**
1025
1030
  * Allow instrumentation of Svelte 5 projects without dropping support for Svelte 4.
@@ -1031,9 +1036,10 @@ const loadWalker = (version, fileName) => Match.value(isAtLeast(version, SVELTE_
1031
1036
  * The specifier is chosen at run time and both modules are optional peers of
1032
1037
  * this package, so neither can be a static import.
1033
1038
  */
1039
+ const findWalker = (module) => isRecordWithWalk(module) ? module.walk : void 0;
1034
1040
  const loadWalkerModule = (specifier, fileName, cause) => Effect.gen(function* () {
1035
1041
  const module = yield* Effect.promise(() => import(specifier));
1036
- const walk = Match.value(module).pipe(Match.when(isRecordWithWalk, (record) => record.walk), Match.orElse(() => void 0));
1042
+ const walk = findWalker(module);
1037
1043
  if (walk === void 0) return yield* SvelteWalkerNotFound.make({
1038
1044
  fileName,
1039
1045
  cause
@@ -1108,29 +1114,31 @@ function getTemplateScriptRanges(ast, walker) {
1108
1114
  return ranges;
1109
1115
  }
1110
1116
  function htmlRootOf(ast) {
1111
- return Match.value(ast).pipe(Match.when(hasHtml, (record) => record["html"]), Match.orElse(() => {
1112
- throw new Error("Svelte AST without html");
1113
- }));
1117
+ if (!hasHtmlField(ast)) throw new Error("Svelte AST without html");
1118
+ return ast["html"];
1114
1119
  }
1115
1120
  function instanceScriptRange(ast) {
1116
- return Match.value(fieldOf$1(ast, "instance")).pipe(Match.when(hasContent, (instance) => scriptContentRange(instance["content"], INSTANCE_RANGE_MISSING)), Match.orElse(() => void 0));
1121
+ const record = contentFieldOf(fieldOf$1(ast, "instance"));
1122
+ return record === void 0 ? void 0 : scriptContentRange(record["content"], INSTANCE_RANGE_MISSING);
1117
1123
  }
1118
1124
  function scriptContentRange(content, missingRange) {
1119
- return Match.value(content).pipe(Match.when(isRange, (range) => ({
1120
- start: range.start,
1121
- end: range.end,
1125
+ if (isRange(content)) return {
1126
+ start: content.start,
1127
+ end: content.end,
1122
1128
  isExpression: false
1123
- })), Match.orElse(() => {
1124
- throw new Error(missingRange);
1125
- }));
1129
+ };
1130
+ throw new Error(missingRange);
1126
1131
  }
1127
1132
  function getModuleScriptRange(svelteAst) {
1128
1133
  return Match.value(fieldOf$1(svelteAst, "module")).pipe(Match.when(void 0, () => void 0), Match.when(null, () => void 0), Match.orElse((block) => moduleBlockRange(block)));
1129
1134
  }
1135
+ function contentFieldOf(value) {
1136
+ return Option.getOrUndefined(Option.filter(Option.fromNullishOr(value), hasContentField));
1137
+ }
1130
1138
  function moduleBlockRange(block) {
1131
- return Match.value(block).pipe(Match.when(hasContent, (record) => scriptContentRange(record["content"], MODULE_RANGE_MISSING)), Match.orElse(() => {
1132
- throw new Error(MODULE_RANGE_MISSING);
1133
- }));
1139
+ const record = contentFieldOf(block);
1140
+ if (record === void 0) throw new Error(MODULE_RANGE_MISSING);
1141
+ return scriptContentRange(record["content"], MODULE_RANGE_MISSING);
1134
1142
  }
1135
1143
  /**
1136
1144
  * Remaps script locations back to the original places using the script map
@@ -3330,16 +3338,19 @@ function literalWithoutRegex(node) {
3330
3338
  return valueLiteralText(node.value);
3331
3339
  }
3332
3340
  function valueLiteralText(value) {
3333
- switch (typeof value) {
3334
- case "string": return JSON.stringify(value);
3335
- case "number": return String(value);
3336
- case "boolean": return String(value);
3337
- case "bigint": return `${value}n`;
3338
- case "symbol":
3339
- case "undefined":
3340
- case "object":
3341
- case "function": return "null";
3342
- }
3341
+ if (typeof value === "string") return JSON.stringify(value);
3342
+ return nonStringLiteralText(value);
3343
+ }
3344
+ function nonStringLiteralText(value) {
3345
+ if (typeof value === "number") return String(value);
3346
+ return booleanOrBigintText(value);
3347
+ }
3348
+ function booleanOrBigintText(value) {
3349
+ if (typeof value === "boolean") return String(value);
3350
+ return bigintText(value);
3351
+ }
3352
+ function bigintText(value) {
3353
+ return typeof value === "bigint" ? `${value}n` : "null";
3343
3354
  }
3344
3355
  function flagText(present, text) {
3345
3356
  switch (Boolean(present)) {
@@ -3393,13 +3404,12 @@ const HASHBANG_FIELDS = {
3393
3404
  function isHashbang(value) {
3394
3405
  return Predicate.isObject(value) && Object.entries(HASHBANG_FIELDS).every(([key, accepts]) => accepts(value[key]));
3395
3406
  }
3396
- const hashbangOf = (root) => {
3397
- const hashbang = Reflect.get(root, "hashbang");
3398
- if (!isHashbang(hashbang)) return null;
3399
- return hashbang;
3400
- };
3401
- const jsPrint = (file) => printProgram(file.root, { hashbang: hashbangOf(file.root) });
3402
- const tsPrint = (file) => printProgram(file.root, { hashbang: hashbangOf(file.root) });
3407
+ const toHashbang = (hashbang) => isHashbang(hashbang) ? hashbang : null;
3408
+ function getHashbang(root) {
3409
+ return toHashbang("hashbang" in root ? root.hashbang : null);
3410
+ }
3411
+ const jsPrint = (file) => printProgram(file.root, { hashbang: getHashbang(file.root) });
3412
+ const tsPrint = (file) => printProgram(file.root, { hashbang: getHashbang(file.root) });
3403
3413
  function getScriptStart$1(script) {
3404
3414
  const span = spanOf(script.root);
3405
3415
  if (span === void 0) throw new Error("Script AST root without start");
@@ -3466,9 +3476,14 @@ function normalizeFileName(fileName) {
3466
3476
  }
3467
3477
  const hasText = (value) => Predicate.isString(value) && value.length > 0;
3468
3478
  const textIfNonEmpty = (value) => Option.getOrUndefined(Option.filter(Option.fromUndefinedOr(value), hasText));
3469
- const fieldOf = (value, key) => Match.value(key in value).pipe(Match.when(true, () => {
3470
- return Reflect.get(value, key);
3471
- }), Match.orElse(() => void 0));
3479
+ function readFieldOf(record, key) {
3480
+ return record[key];
3481
+ }
3482
+ const hasFieldIn = (value, key) => key in value;
3483
+ const fieldOf = (value, key) => {
3484
+ if (!hasFieldIn(value, key)) return;
3485
+ return readFieldOf(value, key);
3486
+ };
3472
3487
  const hasStringCode = (error) => Match.value(fieldOf(error, "code")).pipe(Match.when(Match.string, () => true), Match.orElse(() => false));
3473
3488
  function isErrnoException(error) {
3474
3489
  return Match.value(error).pipe(Match.when(Match.instanceOf(Error), hasStringCode), Match.orElse(() => false));
@@ -3493,7 +3508,7 @@ const isNonPlaceholderText = (text) => Match.value({
3493
3508
  isPlaceholder: false
3494
3509
  }, () => true), Match.orElse(() => false));
3495
3510
  const isUsableText = (value) => Match.value(value).pipe(Match.when(Match.string, isNonPlaceholderText), Match.orElse(() => false));
3496
- const usableText = (value) => Match.value(value).pipe(Match.when(isUsableText, (text) => text), Match.orElse(() => ""));
3511
+ const usableText = (value) => isUsableText(value) ? value : "";
3497
3512
  const objectToStringText = (value) => Match.value(fieldOf(value, "toString")).pipe(Match.when(Match.instanceOf(Function), (callable) => {
3498
3513
  try {
3499
3514
  return usableText(Reflect.apply(callable, value, []));
@@ -3502,9 +3517,19 @@ const objectToStringText = (value) => Match.value(fieldOf(value, "toString")).pi
3502
3517
  }
3503
3518
  }), Match.orElse(() => ""));
3504
3519
  const isObjectType = (cause) => typeof cause === "object";
3505
- const toStringText = (error) => Match.value(error).pipe(Match.when(Match.null, () => ""), Match.when(isObjectType, (value) => objectToStringText(value)), Match.orElse(() => ""));
3506
- const stringifyRest = (error) => Match.value(jsonText(error)).pipe(Match.when(hasText, (json) => json), Match.orElse(() => toStringText(error)));
3507
- const stringifyNonError = (error) => Match.value(error).pipe(Match.when(Match.string, (text) => text), Match.when(isJsonPrimitive, (primitive) => JSON.stringify(primitive)), Match.orElse(() => stringifyRest(error)));
3520
+ const isNonNullObjectType = (error) => error !== null && isObjectType(error);
3521
+ const toStringText = (error) => isNonNullObjectType(error) ? objectToStringText(error) : "";
3522
+ const stringifyRest = (error) => {
3523
+ const json = jsonText(error);
3524
+ return hasText(json) ? json : toStringText(error);
3525
+ };
3526
+ function primitiveJsonOf(error) {
3527
+ return isJsonPrimitive(error) ? JSON.stringify(error) : void 0;
3528
+ }
3529
+ const stringifyNonError = (error) => typeof error === "string" ? error : nonStringTextOf(error);
3530
+ function nonStringTextOf(error) {
3531
+ return primitiveJsonOf(error) ?? stringifyRest(error);
3532
+ }
3508
3533
  const errorText = (error) => Match.value(error).pipe(Match.when(isErrnoException, formatErrnoException), Match.orElse(() => formatError(error)));
3509
3534
  function errorToString(error) {
3510
3535
  return Match.value(error).pipe(Match.when(isEmptyError, () => ""), Match.when(Match.instanceOf(Error), errorText), Match.orElse(() => stringifyNonError(error)));
@@ -3518,7 +3543,18 @@ const errorMessage = (error) => Match.value(error.message.length > 0).pipe(Match
3518
3543
  const errorMessageOrTag = (value) => Match.value(value).pipe(Match.when(Match.instanceOf(Error), errorMessage), Match.orElse(() => tagOf(value)));
3519
3544
  const messageText = (value) => Match.value(textIfNonEmpty(fieldOf(value, "message"))).pipe(Match.when(hasText, (message) => message), Match.orElse(() => errorMessageOrTag(value)));
3520
3545
  const ownCauseText = (value) => Match.value(textIfNonEmpty(fieldOf(value, "reason"))).pipe(Match.when(hasText, (reason) => reason), Match.orElse(() => messageText(value)));
3521
- const causeText = (cause, depth) => Match.value(cause).pipe(Match.when(() => depth > 4, () => void 0), Match.when(Match.undefined, () => void 0), Match.when(Match.null, () => void 0), Match.when(Match.string, textIfNonEmpty), Match.when(isObjectType, (value) => textWithNested(ownCauseText(value), causeText(fieldOf(value, "cause"), depth + 1))), Match.orElse(() => void 0));
3546
+ const isPastDepth = (depth) => depth > 4;
3547
+ const isMissingCause = (cause) => cause === void 0 || cause === null;
3548
+ const causeText = (cause, depth) => isPastDepth(depth) ? void 0 : missingCauseTextOf(cause, depth);
3549
+ function missingCauseTextOf(cause, depth) {
3550
+ return isMissingCause(cause) ? void 0 : causeTextOfValue(cause, depth);
3551
+ }
3552
+ function causeTextOfValue(cause, depth) {
3553
+ return typeof cause === "string" ? textIfNonEmpty(cause) : objectCauseTextOf(cause, depth);
3554
+ }
3555
+ function objectCauseTextOf(cause, depth) {
3556
+ return isObjectType(cause) ? textWithNested(ownCauseText(cause), causeText(fieldOf(cause, "cause"), depth + 1)) : void 0;
3557
+ }
3522
3558
  //#endregion
3523
3559
  //#region src/Mutator.ts
3524
3560
  /**
@@ -3808,9 +3844,10 @@ function withOperator(node, operator) {
3808
3844
  function mutantsWhen(holds, build) {
3809
3845
  return Match.value(holds).pipe(Match.when(true, build), Match.orElse(() => NO_MUTANTS));
3810
3846
  }
3811
- /** A named property of a node that may or may not carry it. */
3847
+ const hasPropertyIn = (node, key) => key in node;
3848
+ const readPropertyOf = (node, key) => hasPropertyIn(node, key) ? node[key] : void 0;
3812
3849
  function propertyOf(node, key) {
3813
- return Match.value(node).pipe(Match.when((candidate) => Predicate.hasProperty(candidate, key), (host) => host[key]), Match.orElse(() => void 0));
3850
+ return Predicate.isObject(node) ? readPropertyOf(node, key) : void 0;
3814
3851
  }
3815
3852
  function isIdentifier(node) {
3816
3853
  return nodeType(node) === "Identifier";
@@ -4517,7 +4554,6 @@ function isDeclared(node) {
4517
4554
  return "declare" in node && node.declare === true;
4518
4555
  }
4519
4556
  const tsTypeAnnotationNodeTypes = Object.freeze([
4520
- "TSAsExpression",
4521
4557
  "TSInterfaceDeclaration",
4522
4558
  "TSTypeAnnotation",
4523
4559
  "TSTypeAliasDeclaration",
@@ -4877,7 +4913,8 @@ function frozenContainer(value) {
4877
4913
  freezableChildren(object).forEach((child) => {
4878
4914
  deepFreeze(child);
4879
4915
  });
4880
- return Object.freeze(object);
4916
+ Object.freeze(object);
4917
+ return value;
4881
4918
  });
4882
4919
  }
4883
4920
  function freezableChildren(value) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@systemfsoftware/stryker-js-instrumenter",
3
- "version": "8.0.0",
3
+ "version": "8.0.2",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "git+https://github.com/systemfsoftware/stryker-js-effect.git",
@@ -22,31 +22,31 @@
22
22
  },
23
23
  "license": "Apache-2.0",
24
24
  "dependencies": {
25
- "@eslint-community/regexpp": "4.12.2",
26
- "@oxc-project/types": "^0.140.0",
27
- "@systemfsoftware/effect-cell-types": "^8",
28
- "angular-html-parser": "~10.4.0",
29
- "effect": "4.0.0-rc.112",
30
- "oxc-parser": "^0.140.0",
25
+ "@eslint-community/regexpp": "^4.12.2",
26
+ "@oxc-project/types": "^0.150.0",
27
+ "@systemfsoftware/effect-cell-types": "^8.3.2",
28
+ "angular-html-parser": "~10.12.0",
29
+ "effect": "4.0.0-rc.116",
30
+ "oxc-parser": "^0.150.0",
31
31
  "oxc-walker": "^1"
32
32
  },
33
33
  "devDependencies": {
34
34
  "@effect/tsgo": "^0.45.0",
35
35
  "@microsoft/api-extractor": "^7",
36
- "@systemfsoftware/all": "^2",
37
- "@systemfsoftware/arethetypeswrong-cli": "^4",
38
- "@systemfsoftware/effect-gherkin-spec": "^4",
39
- "@systemfsoftware/tsconfig": "^1",
36
+ "@systemfsoftware/arethetypeswrong-cli": "^4.2.0",
37
+ "@systemfsoftware/effect-gherkin-spec": "^4.2.2",
38
+ "@systemfsoftware/oxlint-config-recommended": "^1.1.0",
39
+ "@systemfsoftware/tsconfig": "^1.3.6",
40
40
  "@types/node": "^24",
41
41
  "oxlint": "^1",
42
42
  "rimraf": "^6.1.3",
43
- "svelte": "5.55.1",
43
+ "svelte": "^5",
44
44
  "tsdown": "^0.23.0",
45
45
  "typescript": "^7",
46
- "vitest": "^4",
47
- "@systemfsoftware/stryker-ignorer-interface": "^0.1.0",
48
- "@systemfsoftware/vitest-config": "^0.1.0",
49
- "@systemfsoftware/tsdown-config": "^0.1.0"
46
+ "vitest": "^5",
47
+ "@systemfsoftware/stryker-ignorer-interface": "^0.1.1",
48
+ "@systemfsoftware/tsdown-config": "^0.1.0",
49
+ "@systemfsoftware/vitest-config": "^0.1.0"
50
50
  },
51
51
  "engines": {
52
52
  "node": ">=20.0.0"