as-test 0.5.1 → 0.5.3

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/bin/build.js CHANGED
@@ -3,35 +3,87 @@ import { glob } from "glob";
3
3
  import chalk from "chalk";
4
4
  import { execSync } from "child_process";
5
5
  import * as path from "path";
6
- import { getPkgRunner, loadConfig } from "./util.js";
6
+ import { applyMode, getPkgRunner, loadConfig } from "./util.js";
7
7
  const DEFAULT_CONFIG_PATH = path.join(process.cwd(), "./as-test.config.json");
8
- export async function build(configPath = DEFAULT_CONFIG_PATH, selectors = []) {
9
- const config = loadConfig(configPath, false);
10
- ensureDeps(config);
8
+ export async function build(configPath = DEFAULT_CONFIG_PATH, selectors = [], modeName, featureToggles = {}) {
9
+ const loadedConfig = loadConfig(configPath, false);
10
+ const mode = applyMode(loadedConfig, modeName);
11
+ const config = mode.config;
12
+ if (!hasCustomBuildCommand(config)) {
13
+ ensureDeps(config);
14
+ }
11
15
  const pkgRunner = getPkgRunner();
12
16
  const inputPatterns = resolveInputPatterns(config.input, selectors);
13
- const inputFiles = await glob(inputPatterns);
14
- const buildArgs = getBuildArgs(config);
17
+ const inputFiles = (await glob(inputPatterns)).sort((a, b) => a.localeCompare(b));
18
+ const coverageEnabled = resolveCoverageEnabled(config.coverage, featureToggles.coverage);
19
+ const buildEnv = {
20
+ ...mode.env,
21
+ AS_TEST_COVERAGE_ENABLED: coverageEnabled ? "1" : "0",
22
+ };
15
23
  for (const file of inputFiles) {
16
- let cmd = `${pkgRunner} asc ${file}${buildArgs}`;
17
- const outFile = `${config.outDir}/${file.slice(file.lastIndexOf("/") + 1).replace(".ts", ".wasm")}`;
18
- if (config.outDir) {
19
- cmd += " -o " + outFile;
20
- }
24
+ const outFile = `${config.outDir}/${resolveArtifactFileName(file, config.buildOptions.target, modeName)}`;
25
+ const cmd = getBuildCommand(config, pkgRunner, file, outFile, modeName, featureToggles);
21
26
  try {
22
- buildFile(cmd);
27
+ buildFile(cmd, buildEnv);
23
28
  }
24
29
  catch (error) {
25
- throw new Error(`Failed to build ${path.basename(file)} with ${getBuildStderr(error)}`);
30
+ const modeLabel = modeName ?? "default";
31
+ throw new Error(`Failed to build ${path.basename(file)} in mode ${modeLabel} with ${getBuildStderr(error)}\nBuild command: ${cmd}`);
26
32
  }
27
33
  }
28
34
  }
35
+ function hasCustomBuildCommand(config) {
36
+ return !!config.buildOptions.cmd.trim().length;
37
+ }
38
+ function getBuildCommand(config, pkgRunner, file, outFile, modeName, featureToggles = {}) {
39
+ const userArgs = getUserBuildArgs(config);
40
+ if (hasCustomBuildCommand(config)) {
41
+ return `${expandBuildCommand(config.buildOptions.cmd, file, outFile, config.buildOptions.target, modeName)}${userArgs}`;
42
+ }
43
+ const defaultArgs = getDefaultBuildArgs(config, featureToggles);
44
+ let cmd = `${pkgRunner} asc ${file}${userArgs}${defaultArgs}`;
45
+ if (config.outDir) {
46
+ cmd += " -o " + outFile;
47
+ }
48
+ return cmd;
49
+ }
50
+ function getUserBuildArgs(config) {
51
+ const args = config.buildOptions.args.filter((value) => value.length > 0);
52
+ if (args.length) {
53
+ return " " + args.join(" ");
54
+ }
55
+ return "";
56
+ }
57
+ function expandBuildCommand(template, file, outFile, target, modeName) {
58
+ const name = path
59
+ .basename(file)
60
+ .replace(/\.spec\.ts$/, "")
61
+ .replace(/\.ts$/, "");
62
+ return template
63
+ .replace(/<file>/g, file)
64
+ .replace(/<name>/g, name)
65
+ .replace(/<outFile>/g, outFile)
66
+ .replace(/<target>/g, target)
67
+ .replace(/<mode>/g, modeName ?? "");
68
+ }
69
+ function resolveArtifactFileName(file, target, modeName) {
70
+ const base = path
71
+ .basename(file)
72
+ .replace(/\.spec\.ts$/, "")
73
+ .replace(/\.ts$/, "");
74
+ if (!modeName) {
75
+ return `${path.basename(file).replace(".ts", ".wasm")}`;
76
+ }
77
+ return `${base}.${modeName}.${target}.wasm`;
78
+ }
29
79
  function resolveInputPatterns(configured, selectors) {
30
- const configuredInputs = Array.isArray(configured) ? configured : [configured];
80
+ const configuredInputs = Array.isArray(configured)
81
+ ? configured
82
+ : [configured];
31
83
  if (!selectors.length)
32
84
  return configuredInputs;
33
85
  const patterns = new Set();
34
- for (const selector of selectors) {
86
+ for (const selector of expandSelectors(selectors)) {
35
87
  if (!selector)
36
88
  continue;
37
89
  if (isBareSuiteSelector(selector)) {
@@ -45,6 +97,30 @@ function resolveInputPatterns(configured, selectors) {
45
97
  }
46
98
  return [...patterns];
47
99
  }
100
+ function expandSelectors(selectors) {
101
+ const expanded = [];
102
+ for (const selector of selectors) {
103
+ if (!selector)
104
+ continue;
105
+ if (!shouldSplitSelector(selector)) {
106
+ expanded.push(selector);
107
+ continue;
108
+ }
109
+ for (const token of selector.split(",")) {
110
+ const trimmed = token.trim();
111
+ if (!trimmed.length)
112
+ continue;
113
+ expanded.push(trimmed);
114
+ }
115
+ }
116
+ return expanded;
117
+ }
118
+ function shouldSplitSelector(selector) {
119
+ return (selector.includes(",") &&
120
+ !selector.includes("/") &&
121
+ !selector.includes("\\") &&
122
+ !/[*?[\]{}]/.test(selector));
123
+ }
48
124
  function isBareSuiteSelector(selector) {
49
125
  return (!selector.includes("/") &&
50
126
  !selector.includes("\\") &&
@@ -60,15 +136,12 @@ function ensureDeps(config) {
60
136
  process.exit(1);
61
137
  }
62
138
  }
63
- if (!hasJsonAsTransform()) {
64
- console.log(`${chalk.bgRed(" ERROR ")}${chalk.dim(":")} could not find json-as. Install it to compile as-test suites.`);
65
- process.exit(1);
66
- }
67
139
  }
68
- function buildFile(command) {
140
+ function buildFile(command, env) {
69
141
  execSync(command, {
70
142
  stdio: ["ignore", "pipe", "pipe"],
71
143
  encoding: "utf8",
144
+ env,
72
145
  });
73
146
  }
74
147
  function getBuildStderr(error) {
@@ -87,17 +160,17 @@ function getBuildStderr(error) {
87
160
  const message = typeof err?.message == "string" ? err.message.trim() : "";
88
161
  return message || "unknown error";
89
162
  }
90
- function getBuildArgs(config) {
163
+ function getDefaultBuildArgs(config, featureToggles) {
91
164
  let buildArgs = "";
165
+ const tryAsEnabled = resolveTryAsEnabled(featureToggles.tryAs);
92
166
  buildArgs += " --transform as-test/transform";
93
- buildArgs += " --transform json-as/transform";
94
- if (hasTryAsRuntime()) {
167
+ if (tryAsEnabled) {
95
168
  buildArgs += " --transform try-as/transform";
96
169
  }
97
170
  if (config.config && config.config !== "none") {
98
171
  buildArgs += " --config " + config.config;
99
172
  }
100
- if (hasTryAsRuntime()) {
173
+ if (tryAsEnabled) {
101
174
  buildArgs += " --use AS_TEST_TRY_AS=1";
102
175
  }
103
176
  // Should also strip any bindings-enabling from asconfig
@@ -114,18 +187,30 @@ function getBuildArgs(config) {
114
187
  console.log(`${chalk.bgRed(" ERROR ")}${chalk.dim(":")} could not determine target in config! Set target to 'bindings' or 'wasi'`);
115
188
  process.exit(1);
116
189
  }
117
- if (config.buildOptions.args.length &&
118
- config.buildOptions.args.find((v) => v.length > 0)) {
119
- buildArgs += " " + config.buildOptions.args.join(" ");
120
- }
121
190
  return buildArgs;
122
191
  }
192
+ function resolveTryAsEnabled(override) {
193
+ const installed = hasTryAsRuntime();
194
+ if (override === false)
195
+ return false;
196
+ if (override === true && !installed) {
197
+ throw new Error('try-as feature was enabled, but package "try-as" is not installed');
198
+ }
199
+ return installed;
200
+ }
201
+ function resolveCoverageEnabled(rawCoverage, override) {
202
+ if (override != undefined)
203
+ return override;
204
+ if (typeof rawCoverage == "boolean")
205
+ return rawCoverage;
206
+ if (rawCoverage && typeof rawCoverage == "object") {
207
+ const enabled = rawCoverage.enabled;
208
+ if (typeof enabled == "boolean")
209
+ return enabled;
210
+ }
211
+ return true;
212
+ }
123
213
  function hasTryAsRuntime() {
124
214
  return (existsSync(path.join(process.cwd(), "node_modules/try-as")) ||
125
215
  existsSync(path.join(process.cwd(), "node_modules/try-as/package.json")));
126
216
  }
127
- function hasJsonAsTransform() {
128
- return (existsSync(path.join(process.cwd(), "node_modules/json-as/transform.js")) ||
129
- existsSync(path.join(process.cwd(), "node_modules/json-as/transform.ts")) ||
130
- existsSync(path.join(process.cwd(), "node_modules/json-as/transform")));
131
- }