@systemfsoftware/stryker-js-instrumenter 5.0.2 → 6.0.1

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,29 @@
1
1
  # @systemfsoftware/stryker-js-instrumenter
2
2
 
3
+ ## 6.0.1
4
+
5
+ ### Patch Changes
6
+
7
+ - Imports rewired to the collapsed `@systemfsoftware/stryker-js` root entry; each package now co-releases against the root-entry major.
8
+
9
+ - Updated dependencies:
10
+ - @systemfsoftware/effect-cell-types@8.0.0
11
+ - @systemfsoftware/stryker-js@4.0.0
12
+
13
+ ## 6.0.0
14
+
15
+ ### Major Changes
16
+
17
+ - Nothing a consumer can observe moved in the four packages above, so no release is warranted.
18
+
19
+ `@systemfsoftware/stryker-js-instrumenter` now answers with promises: `transform` and `placeHeader` return `Promise`, and `AstTransformer` is a promise-returning function type. Await them where you call them. The parser is read on first use rather than at import, so importing this package no longer constructs Node's WebAssembly runtime, and `ExperimentalWarning: WASI` no longer appears until something is actually parsed.
20
+
21
+ ### Patch Changes
22
+
23
+ - Releases the workspace so its published versions track the shared dependency graph this change moves.
24
+
25
+ - The `@systemfsoftware/source` export condition is gone. It resolved to a package's TypeScript sources for editors and in-repo typechecks; each package now exports only its built entry. If your tsconfig sets `customConditions: ["@systemfsoftware/source"]`, or a bundler config names that condition, remove it — resolution falls back to the built entry, which is what every consumer already got.
26
+
3
27
  ## 5.0.2
4
28
 
5
29
  ### Patch Changes
package/dist/index.d.mts CHANGED
@@ -1,59 +1,68 @@
1
- import { FileDescription, Mutant } from "@systemfsoftware/stryker-js/Mutant";
2
- import * as Effect from "effect/Effect";
3
- import * as S from "effect/Schema";
4
- import "effect/Option";
5
- import { IgnorerService } from "@systemfsoftware/stryker-js/Ignorer";
6
- //#region src/Instrument.schema.d.ts
7
- declare const InstrumentError_base: S.Class<InstrumentError, S.TaggedStruct<"InstrumentError", {
8
- readonly message: S.String;
9
- readonly cause: S.Defect;
10
- }>, import("effect/Cause").YieldableError>;
11
- declare class InstrumentError extends InstrumentError_base {
12
- get message(): string;
13
- }
14
- declare const InstrumenterOptionsSchema: S.Struct<{
15
- readonly excludedMutations: S.$Array<S.String>;
16
- readonly ignorers: S.$Array<S.Unknown>;
17
- readonly noHeader: S.optional<S.Boolean>;
18
- }>;
19
- type InstrumenterOptions = typeof InstrumenterOptionsSchema.Type;
20
- declare const InstrumentResult_base: S.Class<InstrumentResult$1, S.TaggedStruct<"InstrumentResult", {
21
- readonly files: S.$Array<S.Struct<{
22
- readonly name: S.String;
23
- readonly content: S.String;
24
- readonly mutate: S.Union<readonly [S.Boolean, S.$Array<S.Struct<{
25
- readonly start: S.Struct<{
26
- readonly line: S.Finite;
27
- readonly column: S.Finite;
28
- }>;
29
- readonly end: S.Struct<{
30
- readonly line: S.Finite;
31
- readonly column: S.Finite;
32
- }>;
33
- }>>]>;
34
- }>>;
35
- readonly mutants: S.$Array<typeof Mutant>;
36
- }>, {}>;
37
- declare class InstrumentResult$1 extends InstrumentResult_base {}
38
- //#endregion
39
- //#region src/Instrument.d.ts
40
- interface File extends FileDescription {
41
- name: string;
42
- content: string;
43
- }
44
- interface InstrumentResult {
45
- files: readonly File[];
46
- mutants: readonly Mutant[];
47
- }
48
- declare function disableTypeChecks(file: File): Promise<File>;
49
- declare const instrument: (files: readonly File[], options: InstrumenterOptions) => Effect.Effect<InstrumentResult$1, InstrumentError>;
50
- //#endregion
51
- //#region src/Parser.d.ts
52
- interface ParserOptions {}
53
- //#endregion
54
- //#region src/Transformer.d.ts
55
- declare const angularIgnorer: IgnorerService;
56
- declare const strykerPlugins: readonly unknown[];
57
- declare const frameworkPluginsFileUrl: string;
58
- //#endregion
59
- export { type File, type InstrumentResult, type InstrumenterOptions, type ParserOptions, angularIgnorer, disableTypeChecks, frameworkPluginsFileUrl, instrument, strykerPlugins };
1
+ import * as Effect from 'effect/Effect';
2
+ import { FileDescription } from '@systemfsoftware/stryker-js';
3
+ import { IgnorerService } from '@systemfsoftware/stryker-js';
4
+ import { Mutant } from '@systemfsoftware/stryker-js';
5
+ import * as S from 'effect/Schema';
6
+ import { YieldableError } from 'effect/Cause';
7
+
8
+ export declare const angularIgnorer: IgnorerService;
9
+
10
+ export declare function disableTypeChecks(file: File_2): Promise<File_2>;
11
+
12
+ declare interface File_2 extends FileDescription {
13
+ name: string;
14
+ content: string;
15
+ }
16
+ export { File_2 as File }
17
+
18
+ export declare const frameworkPluginsFileUrl: string;
19
+
20
+ export declare const instrument: (files: readonly File_2[], options: InstrumenterOptions) => Effect.Effect<InstrumentResult$1, InstrumentError>;
21
+
22
+ export declare type InstrumenterOptions = typeof InstrumenterOptionsSchema.Type;
23
+
24
+ declare const InstrumenterOptionsSchema: S.Struct<{
25
+ readonly excludedMutations: S.$Array<S.String>;
26
+ readonly ignorers: S.$Array<S.Unknown>;
27
+ readonly noHeader: S.optional<S.Boolean>;
28
+ }>;
29
+
30
+ declare class InstrumentError extends InstrumentError_base {
31
+ get message(): string;
32
+ }
33
+
34
+ declare const InstrumentError_base: S.Class<InstrumentError, S.TaggedStruct<"InstrumentError", {
35
+ readonly message: S.String;
36
+ readonly cause: S.Defect;
37
+ }>, YieldableError>;
38
+
39
+ declare class InstrumentResult$1 extends InstrumentResult_base {}
40
+
41
+ export declare interface InstrumentResult {
42
+ files: readonly File_2[];
43
+ mutants: readonly Mutant[];
44
+ }
45
+
46
+ declare const InstrumentResult_base: S.Class<InstrumentResult$1, S.TaggedStruct<"InstrumentResult", {
47
+ readonly files: S.$Array<S.Struct<{
48
+ readonly name: S.String;
49
+ readonly content: S.String;
50
+ readonly mutate: S.Union<readonly [S.Boolean, S.$Array<S.Struct<{
51
+ readonly start: S.Struct<{
52
+ readonly line: S.Finite;
53
+ readonly column: S.Finite;
54
+ }>;
55
+ readonly end: S.Struct<{
56
+ readonly line: S.Finite;
57
+ readonly column: S.Finite;
58
+ }>;
59
+ }>>]>;
60
+ }>>;
61
+ readonly mutants: S.$Array<typeof Mutant>;
62
+ }>, {}>;
63
+
64
+ export declare interface ParserOptions {}
65
+
66
+ export declare const strykerPlugins: readonly unknown[];
67
+
68
+ export { }
package/dist/index.mjs CHANGED
@@ -1,14 +1,11 @@
1
- import { INSTRUMENTER_CONSTANTS, Mutant } from "@systemfsoftware/stryker-js/Mutant";
1
+ import { INSTRUMENTER_CONSTANTS, Mutant, propertyPath, strykerReportBugUrl } from "@systemfsoftware/stryker-js";
2
2
  import * as Effect from "effect/Effect";
3
3
  import * as Predicate from "effect/Predicate";
4
4
  import * as S from "effect/Schema";
5
5
  import * as Arr from "effect/Array";
6
6
  import * as Match from "effect/Match";
7
7
  import * as Option from "effect/Option";
8
- import { parseSync } from "oxc-parser";
9
8
  import path from "path";
10
- import "@systemfsoftware/stryker-js/Ignorer";
11
- import { propertyPath, strykerReportBugUrl } from "@systemfsoftware/stryker-js/Schema";
12
9
  import path$1 from "node:path";
13
10
  import { RegExpParser, visitRegExpAST } from "@eslint-community/regexpp";
14
11
  //#region src/Instrument.schema.ts
@@ -641,6 +638,13 @@ function isIndexedList(container, index) {
641
638
  return isNodeList(container) && Number.isInteger(index);
642
639
  }
643
640
  //#endregion
641
+ //#region src/Oxc.ts
642
+ let oxc;
643
+ const loadOxc = async () => {
644
+ if (oxc === void 0) oxc = await import("oxc-parser");
645
+ return oxc;
646
+ };
647
+ //#endregion
644
648
  //#region src/Parser.schema.ts
645
649
  var ParseFailed = class extends S.TaggedError("@systemfsoftware/stryker-js-instrumenter/ParseFailed")("ParseFailed", {
646
650
  fileName: S.String,
@@ -723,7 +727,8 @@ function fieldOf(value, key) {
723
727
  function appendIfDefined(values, value) {
724
728
  if (value !== void 0) values.push(value);
725
729
  }
726
- function parseWithOxc(text, fileName, lang) {
730
+ async function parseWithOxc(text, fileName, lang) {
731
+ const { parseSync } = await loadOxc();
727
732
  const result = parseSync(fileName, text, {
728
733
  lang,
729
734
  range: true
@@ -795,7 +800,7 @@ function getFormat(fileName, override) {
795
800
  }
796
801
  function createJSParser() {
797
802
  return async function parse(text, fileName) {
798
- const { root, comments } = parseWithOxc(text, fileName, "js");
803
+ const { root, comments } = await parseWithOxc(text, fileName, "js");
799
804
  return {
800
805
  originFileName: fileName,
801
806
  rawContent: text,
@@ -806,7 +811,7 @@ function createJSParser() {
806
811
  };
807
812
  }
808
813
  async function parseTS(text, fileName) {
809
- const { root, comments } = parseWithOxc(text, fileName, "ts");
814
+ const { root, comments } = await parseWithOxc(text, fileName, "ts");
810
815
  return {
811
816
  originFileName: fileName,
812
817
  rawContent: text,
@@ -816,7 +821,7 @@ async function parseTS(text, fileName) {
816
821
  };
817
822
  }
818
823
  async function parseTsx(text, fileName) {
819
- const { root, comments } = parseWithOxc(text, fileName, "tsx");
824
+ const { root, comments } = await parseWithOxc(text, fileName, "tsx");
820
825
  return {
821
826
  root,
822
827
  comments,
@@ -4794,7 +4799,7 @@ function isPropertyBearing(node) {
4794
4799
  }
4795
4800
  const strykerPlugins = [];
4796
4801
  const frameworkPluginsFileUrl = import.meta.url;
4797
- const parsedInstrumentationHeader = parseSync("instrumenter-header.js", `// @ts-nocheck
4802
+ const INSTRUMENTATION_HEADER_SOURCE = `// @ts-nocheck
4798
4803
  var ${STRYKER_NAMESPACE_HELPER} = function(){
4799
4804
  var g = typeof globalThis === 'object' && globalThis && globalThis.Math === Math && globalThis || new Function("return this")();
4800
4805
  var ns = g.${INSTRUMENTER_CONSTANTS.NAMESPACE} || (g.${INSTRUMENTER_CONSTANTS.NAMESPACE} = {});
@@ -4838,34 +4843,37 @@ var ${IS_MUTANT_ACTIVE_HELPER} = function(id) {
4838
4843
  }
4839
4844
  ${IS_MUTANT_ACTIVE_HELPER} = isActive;
4840
4845
  return isActive(id);
4841
- }`, {
4842
- lang: "js",
4843
- range: true
4844
- });
4845
- if (parsedInstrumentationHeader.errors.length > 0) throw new Error("Instrumentation header failed to parse");
4846
- const instrumentationHeader = parsedInstrumentationHeader.program.body;
4847
- deepFreeze(instrumentationHeader);
4848
- function placeHeaderIfNeeded(mutantCollector, originFileName, options, root) {
4849
- if (shouldPlaceHeader(mutantCollector, originFileName, options)) placeHeader(root);
4846
+ }`;
4847
+ let instrumentationHeaderValue;
4848
+ const instrumentationHeader = async () => {
4849
+ if (instrumentationHeaderValue === void 0) {
4850
+ instrumentationHeaderValue = (await parseWithOxc(INSTRUMENTATION_HEADER_SOURCE, "instrumenter-header.js", "js")).root.body;
4851
+ deepFreeze(instrumentationHeaderValue);
4852
+ }
4853
+ return instrumentationHeaderValue;
4854
+ };
4855
+ async function placeHeaderIfNeeded(mutantCollector, originFileName, options, root) {
4856
+ if (shouldPlaceHeader(mutantCollector, originFileName, options)) await placeHeader(root);
4850
4857
  }
4851
4858
  function shouldPlaceHeader(mutantCollector, originFileName, options) {
4852
4859
  return hasPlacedMutants(mutantCollector, originFileName) && options.noHeader !== true;
4853
4860
  }
4854
- function placeHeader(root) {
4855
- root.body.unshift(...headerFor(root));
4861
+ async function placeHeader(root) {
4862
+ root.body.unshift(...await headerFor(root));
4856
4863
  }
4857
- function headerFor(root) {
4864
+ async function headerFor(root) {
4865
+ const header = await instrumentationHeader();
4858
4866
  return Option.match(leadingCommentsOf(root), {
4859
- onNone: () => instrumentationHeader,
4860
- onSome: (leadingComments) => [commentedHeader(leadingComments), ...instrumentationHeader.slice(1)]
4867
+ onNone: () => header,
4868
+ onSome: (leadingComments) => [commentedHeader(leadingComments, header), ...header.slice(1)]
4861
4869
  });
4862
4870
  }
4863
4871
  function leadingCommentsOf(root) {
4864
4872
  const firstStatement = root.body[0];
4865
4873
  return Option.filter(Option.fromNullishOr(firstStatement?.leadingComments), isUnknownArray);
4866
4874
  }
4867
- function commentedHeader(leadingComments) {
4868
- const cloned = cloneNode(Option.getOrThrowWith(Option.fromNullishOr(instrumentationHeader[0]), () => /* @__PURE__ */ new Error("Instrumentation header is empty")));
4875
+ function commentedHeader(leadingComments, header) {
4876
+ const cloned = cloneNode(Option.getOrThrowWith(Option.fromNullishOr(header[0]), () => /* @__PURE__ */ new Error("Instrumentation header is empty")));
4869
4877
  cloned.leadingComments = leadingComments;
4870
4878
  return cloned;
4871
4879
  }
@@ -4905,7 +4913,7 @@ function isMap(value) {
4905
4913
  function isSet(value) {
4906
4914
  return value instanceof Set;
4907
4915
  }
4908
- function transform(ast, mutantCollector, transformerContext) {
4916
+ async function transform(ast, mutantCollector, transformerContext) {
4909
4917
  const context = {
4910
4918
  ...transformerContext,
4911
4919
  transform
@@ -4918,34 +4926,31 @@ function transform(ast, mutantCollector, transformerContext) {
4918
4926
  case "svelte": return transformSvelte(ast, mutantCollector, context);
4919
4927
  }
4920
4928
  }
4921
- const transformHtml = ({ root }, mutantCollector, context) => {
4929
+ const transformHtml = async ({ root }, mutantCollector, context) => {
4922
4930
  const warnings = [];
4923
- root.scripts.forEach((ast) => {
4924
- warnings.push(...context.transform(ast, mutantCollector, context));
4925
- });
4931
+ for (const script of root.scripts) warnings.push(...await context.transform(script, mutantCollector, context));
4926
4932
  return warnings;
4927
4933
  };
4928
4934
  const moduleScript = `<script context="module">
4929
4935
  \n<\/script>\n`;
4930
- const transformSvelte = (svelte, mutantCollector, context) => {
4936
+ const transformSvelte = async (svelte, mutantCollector, context) => {
4931
4937
  const warnings = [];
4932
4938
  const { root } = svelte;
4933
- [root.moduleScript, ...root.additionalScripts].filter(Predicate.isNotNullish).forEach((script) => {
4934
- warnings.push(...context.transform(script.ast, mutantCollector, {
4935
- ...context,
4936
- options: {
4937
- ...context.options,
4938
- noHeader: true
4939
- }
4940
- }));
4941
- });
4942
- placeModuleHeaderIfNeeded(svelte, mutantCollector);
4939
+ const scripts = [root.moduleScript, ...root.additionalScripts].filter(Predicate.isNotNullish);
4940
+ for (const script of scripts) warnings.push(...await context.transform(script.ast, mutantCollector, {
4941
+ ...context,
4942
+ options: {
4943
+ ...context.options,
4944
+ noHeader: true
4945
+ }
4946
+ }));
4947
+ await placeModuleHeaderIfNeeded(svelte, mutantCollector);
4943
4948
  return warnings;
4944
4949
  };
4945
- function placeModuleHeaderIfNeeded(svelte, mutantCollector) {
4946
- if (hasPlacedMutants(mutantCollector, svelte.originFileName)) placeModuleHeader(svelte);
4950
+ async function placeModuleHeaderIfNeeded(svelte, mutantCollector) {
4951
+ if (hasPlacedMutants(mutantCollector, svelte.originFileName)) await placeModuleHeader(svelte);
4947
4952
  }
4948
- function placeModuleHeader(svelte) {
4953
+ async function placeModuleHeader(svelte) {
4949
4954
  const { root, originFileName } = svelte;
4950
4955
  if (!root.moduleScript) {
4951
4956
  root.moduleScript = {
@@ -4968,7 +4973,7 @@ function placeModuleHeader(svelte) {
4968
4973
  script.range.end += moduleScript.length;
4969
4974
  });
4970
4975
  }
4971
- placeHeader(root.moduleScript.ast.root);
4976
+ await placeHeader(root.moduleScript.ast.root);
4972
4977
  }
4973
4978
  function emptyProgram() {
4974
4979
  return {
@@ -4980,7 +4985,7 @@ function emptyProgram() {
4980
4985
  function isMutateRangeList(value) {
4981
4986
  return Array.isArray(value);
4982
4987
  }
4983
- const transformScript = ({ root, originFileName, rawContent, offset, comments }, mutantCollector, { options, mutateDescription }, mutators, mutantPlacers) => {
4988
+ const transformScript = async ({ root, originFileName, rawContent, offset, comments }, mutantCollector, { options, mutateDescription }, mutators, mutantPlacers) => {
4984
4989
  const lineTable = buildLineTable(rawContent);
4985
4990
  attachComments(root, comments, lineTable);
4986
4991
  const placementMap = /* @__PURE__ */ new Map();
@@ -5001,7 +5006,7 @@ const transformScript = ({ root, originFileName, rawContent, offset, comments },
5001
5006
  if (hasAppliedMutants(placement)) applyPlacement(path, placement);
5002
5007
  }
5003
5008
  });
5004
- placeHeaderIfNeeded(mutantCollector, originFileName, options, root);
5009
+ await placeHeaderIfNeeded(mutantCollector, originFileName, options, root);
5005
5010
  return warnings;
5006
5011
  function visitNode(path) {
5007
5012
  if (shouldSkip(path)) {
@@ -5303,7 +5308,7 @@ const readCollected = (command) => Effect.gen(function* () {
5303
5308
  ast
5304
5309
  })));
5305
5310
  const collector = createMutantCollector();
5306
- yield* Effect.forEach(parsed, ({ file, ast }) => Effect.try({
5311
+ yield* Effect.forEach(parsed, ({ file, ast }) => Effect.tryPromise({
5307
5312
  try: () => transform(ast, collector, {
5308
5313
  options: toTransformerOptions(options),
5309
5314
  mutateDescription: toOneBasedLineNumber(file.mutate)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@systemfsoftware/stryker-js-instrumenter",
3
- "version": "5.0.2",
3
+ "version": "6.0.1",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "git+https://github.com/systemfsoftware/systemfsoftware.git",
@@ -24,11 +24,12 @@
24
24
  "angular-html-parser": "~10.4.0",
25
25
  "effect": "4.0.0-rc.112",
26
26
  "oxc-parser": "^0.140.0",
27
- "@systemfsoftware/effect-cell-types": "^7.0.0",
28
- "@systemfsoftware/stryker-js": "^3.0.1"
27
+ "@systemfsoftware/effect-cell-types": "^8.0.0",
28
+ "@systemfsoftware/stryker-js": "^4.0.0"
29
29
  },
30
30
  "devDependencies": {
31
- "@systemfsoftware/arethetypeswrong-cli": "^1.1.1",
31
+ "@microsoft/api-extractor": "^7.58.7",
32
+ "@systemfsoftware/arethetypeswrong-cli": "^4.1.0",
32
33
  "@types/estree": "1.0.8",
33
34
  "@types/node": "^24",
34
35
  "oxlint": "^1.77.0",
@@ -37,11 +38,11 @@
37
38
  "tsdown": "^0.22.14",
38
39
  "typescript": "^7",
39
40
  "vitest": "^4",
40
- "@systemfsoftware/all": "^2.0.0",
41
- "@systemfsoftware/effect-gherkin-spec": "^4.0.1",
41
+ "@systemfsoftware/all": "^2.0.2",
42
+ "@systemfsoftware/effect-gherkin-spec": "^4.0.2",
43
+ "@systemfsoftware/vitest-config": "^0.1.0",
42
44
  "@systemfsoftware/oxlint-config": "^0.1.0",
43
- "@systemfsoftware/tsconfig": "^1.3.3",
44
- "@systemfsoftware/vitest-config": "^0.1.0"
45
+ "@systemfsoftware/tsconfig": "^1.3.4"
45
46
  },
46
47
  "engines": {
47
48
  "node": ">=20.0.0"
@@ -59,10 +60,12 @@
59
60
  },
60
61
  "scripts": {
61
62
  "clean": "rimraf dist",
62
- "build": "tsdown",
63
+ "build": "tsdown && pnpm api:check",
63
64
  "typecheck": "tsc --noEmit --incremental",
64
65
  "attw": "attw --pack .",
65
66
  "test": "vitest run",
66
- "lint": "f=${OXLINT_FORMAT:-${AGENT:+agent}}; oxlint . --format=${f:-default}"
67
+ "lint": "f=${OXLINT_FORMAT:-${AGENT:+agent}}; oxlint . --format=${f:-default}",
68
+ "api:check": "tsdown && api-extractor run",
69
+ "api:update": "api-extractor run --local"
67
70
  }
68
71
  }