@isentinel/jest-roblox 0.3.8 → 0.3.10

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/README.md CHANGED
@@ -352,7 +352,7 @@ Create a file named drillbit.toml in your project's directory.
352
352
 
353
353
  ```toml
354
354
  [plugins.jest_roblox]
355
- github = "https://github.com/christopher-buss/jest-roblox-cli/releases/download/v0.3.8/JestRobloxRunner.rbxm"
355
+ github = "https://github.com/christopher-buss/jest-roblox-cli/releases/download/v0.2.7/JestRobloxRunner.rbxm"
356
356
  ```
357
357
 
358
358
  Then run `drillbit` and it will download the plugin and install it in Studio for
@@ -10,10 +10,7 @@ const sourceEntry = resolve(dirname(fileURLToPath(import.meta.url)), "../src/cli
10
10
 
11
11
  registerHooks({ load, resolve: resolveLuau });
12
12
 
13
- if (existsSync(sourceEntry)) {
14
- const { main } = await import("../src/cli.ts");
15
- await main();
16
- } else {
17
- const { main } = await import("../dist/cli.mjs");
18
- await main();
19
- }
13
+ const { main } = existsSync(sourceEntry)
14
+ ? await import("../src/cli.ts")
15
+ : await import("../dist/cli.mjs");
16
+ await main();
package/dist/cli.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { A as outputSingleResult, I as parseGameOutput, W as formatBanner, Z as LuauScriptError, ct as VALID_BACKENDS, dt as isValidBackend, et as mergeCliWithConfig, ft as ConfigError, h as walkErrorChain, k as outputMultiResult, m as formatMissingScopes, n as runJestRoblox, pt as version, tt as loadConfig } from "./run-Cirdb_CB.mjs";
1
+ import { B as parseGameOutput, J as formatBanner, N as outputMultiResult, P as outputSingleResult, bt as version, ct as loadConfig, ht as VALID_BACKENDS, n as runJestRoblox, st as mergeCliWithConfig, tt as LuauScriptError, v as formatMissingScopes, vt as isValidBackend, y as walkErrorChain, yt as ConfigError } from "./run-BKP7mem2.mjs";
2
2
  import { OpenCloudError } from "@bedrock-rbx/ocale";
3
3
  import process from "node:process";
4
4
  import { parseArgs as parseArgs$1 } from "node:util";
@@ -215,6 +215,7 @@ async function main() {
215
215
  process.exitCode = await run(process.argv.slice(2));
216
216
  }
217
217
  const PARALLEL_FLAG = "--parallel";
218
+ const IntegerLikePattern = /^-?\d+$/;
218
219
  function normalizeParallelFlag(args) {
219
220
  const out = [];
220
221
  for (let index = 0; index < args.length; index++) {
@@ -224,7 +225,7 @@ function normalizeParallelFlag(args) {
224
225
  continue;
225
226
  }
226
227
  const next = args[index + 1];
227
- if (next !== void 0 && !next.startsWith("-") && (next === "auto" || /^-?\d+$/.test(next))) {
228
+ if (next !== void 0 && !next.startsWith("-") && (next === "auto" || IntegerLikePattern.test(next))) {
228
229
  out.push(PARALLEL_FLAG, next);
229
230
  index += 1;
230
231
  } else out.push(PARALLEL_FLAG, "auto");
package/dist/index.d.mts CHANGED
@@ -106,6 +106,44 @@ interface CoverageArtifacts {
106
106
  }
107
107
  declare function readBuildManifest(filePath: string, options?: ReadBuildManifestOptions): ReadBuildManifestResult;
108
108
  //#endregion
109
+ //#region src/artifacts/build-coverage-place.d.ts
110
+ /**
111
+ * Everything a caller (a Node-only "Machine A") needs after producing the
112
+ * coverage-instrumented place offline, without executing any suite: the built
113
+ * place (`coveragePlace.path` + content hash) and the paths of the sibling
114
+ * manifests it shares a `buildId` with. The place is left on disk for the caller
115
+ * to copy to the run machine — it is never cleaned.
116
+ */
117
+ interface CoveragePlaceBundle {
118
+ buildId: string;
119
+ /** The always-on build record's path (`build-manifest.json`). */
120
+ buildManifestPath: string;
121
+ /** The coverage-data sibling manifest's path (`coverage-manifest.json`). */
122
+ coverageManifestPath: string;
123
+ /** The instrumented place: cwd-relative path + SHA-256 of its bytes. */
124
+ coveragePlace: BuildManifestArtifact;
125
+ /** Per-project DataModel paths baked into the place. */
126
+ projects: Array<BuildManifestProject>;
127
+ /** `false` on the incremental no-change reuse path (place was not rebuilt). */
128
+ rebuilt: boolean;
129
+ }
130
+ /**
131
+ * Build the coverage-instrumented place **without running it** — the offline
132
+ * half of the split producer. Instruments (incrementally) and rojo-builds the
133
+ * place, bakes each project's `jest.config` stub into it so any runner that
134
+ * opens the place can discover and run the suite unaided, publishes the sibling
135
+ * Build + Coverage manifests, and hands back the place. No backend is resolved,
136
+ * no suite executes, nothing hits the network. Coverage collection is forced on
137
+ * regardless of the input config.
138
+ *
139
+ * The counterpart to `prepareArtifacts`, minus the run and the Clean Place —
140
+ * the entry point for a machine that cannot execute Roblox at all. It shares the
141
+ * `prepareBakedCoverage` seam with the run path but always bakes stubs (the run
142
+ * path skips baking for studio-cli, which injects configs at runtime), because a
143
+ * place handed to a foreign runner must be self-contained.
144
+ */
145
+ declare function buildCoveragePlace(config: ResolvedConfig): Promise<CoveragePlaceBundle>;
146
+ //#endregion
109
147
  //#region src/coverage-pipeline/types.d.ts
110
148
  /**
111
149
  * Raw hit counts for a single file, keyed by statement/function index.
@@ -423,9 +461,25 @@ interface OpenCloudOptions {
423
461
  }
424
462
  declare class OpenCloudBackend implements Backend {
425
463
  private readonly runner;
426
- readonly kind = "open-cloud";
464
+ /** One-shot per run so parallel raced tasks don't repeat the warning. */
465
+ private raceWarned;
466
+ readonly kind: "open-cloud";
427
467
  constructor(credentials: OpenCloudCredentials, options?: OpenCloudOptions);
428
468
  runTests(options: BackendOptions): Promise<BackendResult>;
469
+ /**
470
+ * Optimistic version pinning. Pinned tasks
471
+ * (`/versions/{v}/luau-execution-session-tasks`) miss the warm-server pool
472
+ * whenever no server holds the freshly-uploaded version yet, costing a cold
473
+ * place boot per task (~10-45s, scaling with place size). Unpinned tasks
474
+ * boot the latest saved version from the warm pool, so the first attempt
475
+ * runs unpinned with a guard prepended: if the booted server is not on this
476
+ * run's version (a concurrent upload won the boot race), the task returns
477
+ * {@link PLACE_VERSION_RACE_SENTINEL} instead of running. On the sentinel,
478
+ * the task is retried once, pinned — correct by construction, no re-upload
479
+ * (the version exists even when it is no longer head), and no unpinned
480
+ * retry loop for a concurrent uploader to keep winning against.
481
+ */
482
+ private executeGuarded;
429
483
  private runBucket;
430
484
  private runStaticBuckets;
431
485
  private runWorkStealing;
@@ -568,7 +622,7 @@ declare class StudioCliBackend implements Backend {
568
622
  private readonly launch;
569
623
  private readonly studioPath?;
570
624
  private readonly timeout;
571
- readonly kind = "studio-cli";
625
+ readonly kind: "studio-cli";
572
626
  constructor(options?: StudioCliOptions);
573
627
  runTests(options: BackendOptions): Promise<BackendResult>;
574
628
  /**
@@ -597,7 +651,7 @@ declare class StudioBackend implements Backend {
597
651
  private readonly timeout;
598
652
  private preConnected?;
599
653
  private wss?;
600
- readonly kind = "studio";
654
+ readonly kind: "studio";
601
655
  constructor(options: StudioOptions);
602
656
  close(): void;
603
657
  runTests(options: BackendOptions): Promise<BackendResult>;
@@ -761,6 +815,40 @@ type ReadManifestResult = ParsedManifest<CoverageManifest>;
761
815
  declare const manifestSchema: type<CoverageManifest>;
762
816
  declare function readManifest(filePath: string): ReadManifestResult;
763
817
  //#endregion
818
+ //#region src/coverage-pipeline/merge-raw-coverage.d.ts
819
+ /**
820
+ * Additively merge two raw coverage datasets. Overlapping files have their
821
+ * hit counts summed (matching istanbul-lib-coverage's semantics).
822
+ */
823
+ declare function mergeRawCoverage(target: RawCoverageData | undefined, source: RawCoverageData | undefined): RawCoverageData | undefined;
824
+ //#endregion
825
+ //#region src/coverage-pipeline/raw-coverage.d.ts
826
+ /**
827
+ * Normalize a raw coverage table into typed {@link RawCoverageData}. The input
828
+ * is the per-file hit table the coverage probes accumulate at runtime — the
829
+ * `_G.__jest_roblox_cov` global, or the `_coverage` field of a run envelope —
830
+ * keyed by the stable per-file join key (`fileKey`). Luau serializes the
831
+ * `s`/`f` counters as 1-based arrays and `b` as an array of arrays; this
832
+ * canonicalizes them to string-keyed records while leaving the fileKey verbatim
833
+ * (it is the byte-identical join key the static maps are also keyed to). Returns
834
+ * `undefined` when the input is not an object or carries no file with a
835
+ * statement map.
836
+ */
837
+ declare function normalizeRawCoverage(coverage: unknown): RawCoverageData | undefined;
838
+ /**
839
+ * Extract raw coverage from a completed run's result envelope — the companion
840
+ * seam for a run this CLI did not launch. Accepts the plugin's `jestOutput`
841
+ * (a JSON string or an already-parsed object), or the bare `_G.__jest_roblox_cov`
842
+ * table read straight off the run. When an object carries a `_coverage` field it
843
+ * is used; otherwise the object is treated as the hit table itself. Returns
844
+ * `undefined` for malformed JSON or an envelope with no coverage.
845
+ *
846
+ * A multi-project result (`{ entries: [{ jestOutput }, …] }`) carries one
847
+ * envelope per project; parse each `entries[i].jestOutput` and combine with
848
+ * `mergeRawCoverage`.
849
+ */
850
+ declare function parseCoverageEnvelope(output: unknown): RawCoverageData | undefined;
851
+ //#endregion
764
852
  //#region src/coverage-pipeline/attribution.d.ts
765
853
  interface AttributionResult {
766
854
  /** Per Luau file: statement id → ids of the tests that covered it. */
@@ -1608,4 +1696,4 @@ declare function visitExpression(expression: AstExpr, visitor: LuauVisitor): voi
1608
1696
  declare function visitStatement(statement: AstStat, visitor: LuauVisitor): void;
1609
1697
  declare function visitBlock(block: AstStatBlock, visitor: LuauVisitor): void; //#endregion
1610
1698
  //#endregion
1611
- export { type ArtifactBundle, type AstExpr, type AstExprBinary, type AstExprCall, type AstExprFunction, type AstStat, type AstStatBlock, BUILD_MANIFEST_VERSION, type Backend, type BackendOptions, type BuildManifest, type BuildManifestArtifact, type BuildManifestFileRecord, type BuildManifestProject, type CliOptions, type Config, type ConfigInput, type CoverageManifest, DEFAULT_CONFIG, type DisplayName, type ExecuteResult, type FormatOutputOptions, type FormatterEntry, GLOBAL_TEST_KEYS, type GameOutputEntry, type GitHubActionsFormatterOptions, type GlobalTestConfig, type InlineProjectConfig, type InstrumentedFileRecord, JEST_ARGV_EXCLUDED_KEYS, type JestArgv, type JestResult, type LuauSpan, type LuauVisitor, MANIFEST_VERSION, type MultiProjectMerged, type MultiRunResult, type NonInstrumentedFileRecord, OpenCloudBackend, type ProjectEntry, type ProjectInput, type ProjectResult, type ProjectTestConfig, ROOT_CLI_KEYS, type ReadBuildManifestOptions, type ReadBuildManifestResult, type ReadManifestResult as ReadCoverageManifestResult, type ResolvedConfig, type ResolvedProjectConfig, type RunMode, type RunOptions, type RunProjectsOptions, type RunProjectsResult, type RunResult, SHARED_TEST_KEYS, type SharedTestConfig, type SingleRunResult, StudioBackend, StudioCliBackend, type TestCaseResult, type TestDefinition, type TestFileResult, type TestRecord, type TestStatus, type TscErrorInfo, type TypecheckOptions, type WorkspaceConfig, type WorkspaceRunResult, buildJestArgv, buildManifestSchema, manifestSchema as coverageManifestSchema, createOpenCloudBackend, createStudioBackend, createStudioCliBackend, defineConfig, defineProject, extractJsonFromOutput, formatAnnotations, formatExecuteOutput, formatFailure, formatGameOutputNotice, formatJobSummary, formatJson, formatResult, formatTestSummary, generateTestScript, hashFile, loadConfig, parseGameOutput, parseJestOutput, prepareArtifacts, readBuildManifest, readManifest as readCoverageManifest, resolveConfig, runJestRoblox, runProjects, runTypecheck, visitBlock, visitExpression, visitStatement, writeGameOutput, writeJsonFile };
1699
+ export { type ArtifactBundle, type AstExpr, type AstExprBinary, type AstExprCall, type AstExprFunction, type AstStat, type AstStatBlock, BUILD_MANIFEST_VERSION, type Backend, type BackendOptions, type BuildManifest, type BuildManifestArtifact, type BuildManifestFileRecord, type BuildManifestProject, type CliOptions, type Config, type ConfigInput, type CoverageManifest, type CoveragePlaceBundle, DEFAULT_CONFIG, type DisplayName, type ExecuteResult, type FormatOutputOptions, type FormatterEntry, GLOBAL_TEST_KEYS, type GameOutputEntry, type GitHubActionsFormatterOptions, type GlobalTestConfig, type InlineProjectConfig, type InstrumentedFileRecord, JEST_ARGV_EXCLUDED_KEYS, type JestArgv, type JestResult, type LuauSpan, type LuauVisitor, MANIFEST_VERSION, type MultiProjectMerged, type MultiRunResult, type NonInstrumentedFileRecord, OpenCloudBackend, type ProjectEntry, type ProjectInput, type ProjectResult, type ProjectTestConfig, ROOT_CLI_KEYS, type RawCoverageData, type RawFileCoverage, type ReadBuildManifestOptions, type ReadBuildManifestResult, type ReadManifestResult as ReadCoverageManifestResult, type ResolvedConfig, type ResolvedProjectConfig, type RunMode, type RunOptions, type RunProjectsOptions, type RunProjectsResult, type RunResult, SHARED_TEST_KEYS, type SharedTestConfig, type SingleRunResult, StudioBackend, StudioCliBackend, type TestCaseResult, type TestDefinition, type TestFileResult, type TestRecord, type TestStatus, type TscErrorInfo, type TypecheckOptions, type WorkspaceConfig, type WorkspaceRunResult, buildCoveragePlace, buildJestArgv, buildManifestSchema, manifestSchema as coverageManifestSchema, createOpenCloudBackend, createStudioBackend, createStudioCliBackend, defineConfig, defineProject, extractJsonFromOutput, formatAnnotations, formatExecuteOutput, formatFailure, formatGameOutputNotice, formatJobSummary, formatJson, formatResult, formatTestSummary, generateTestScript, hashFile, loadConfig, mergeRawCoverage, normalizeRawCoverage, parseCoverageEnvelope, parseGameOutput, parseJestOutput, prepareArtifacts, readBuildManifest, readManifest as readCoverageManifest, resolveConfig, runJestRoblox, runProjects, runTypecheck, visitBlock, visitExpression, visitStatement, writeGameOutput, writeJsonFile };
package/dist/index.mjs CHANGED
@@ -1,5 +1,55 @@
1
- import { $ as parseJestOutput, B as writeJsonFile, C as visitStatement, D as emitBuildManifest, E as buildManifestSchema, F as formatGameOutputNotice, G as hashFile, H as formatResult, I as parseGameOutput, J as readManifest, K as MANIFEST_VERSION, L as writeGameOutput, M as formatJobSummary, N as formatExecuteOutput, O as readBuildManifest, P as runProjects, Q as extractJsonFromOutput, R as createTimingCollector, S as visitExpression, T as BUILD_MANIFEST_VERSION, U as formatTestSummary, V as formatFailure, X as applyAttribution, Y as writeManifest, _ as generateTestScript, a as loadRojoTree, at as JEST_ARGV_EXCLUDED_KEYS, b as findRojoProject, c as StudioBackend, d as createStudioCliBackend, et as mergeCliWithConfig, f as OpenCloudBackend, g as buildJestArgv, i as collectStubMounts, it as GLOBAL_TEST_KEYS, j as formatAnnotations, l as createStudioBackend, lt as defineConfig, n as runJestRoblox, nt as resolveConfig, o as runTypecheck, ot as ROOT_CLI_KEYS, p as createOpenCloudBackend, q as manifestSchema, r as runSingleOrMulti, rt as DEFAULT_CONFIG, s as resolveAllProjects, st as SHARED_TEST_KEYS, t as getRawProjects, tt as loadConfig, u as StudioCliBackend, ut as defineProject, v as COVERAGE_BUILD_MANIFEST_PATH, w as buildPlace, x as visitBlock, y as COVERAGE_MANIFEST_PATH, z as formatJson } from "./run-Cirdb_CB.mjs";
1
+ import { $ as writeManifest, A as buildManifestSchema, B as parseGameOutput, C as COVERAGE_MANIFEST_PATH, D as visitStatement, E as visitExpression, F as formatAnnotations, G as formatFailure, H as createTimingCollector, I as formatJobSummary, K as formatResult, L as formatExecuteOutput, M as readBuildManifest, O as buildPlace, Q as readManifest, R as runProjects, S as COVERAGE_BUILD_MANIFEST_PATH, T as visitBlock, U as formatJson, V as writeGameOutput, W as writeJsonFile, X as MANIFEST_VERSION, Y as hashFile, Z as manifestSchema, _ as createOpenCloudBackend, _t as defineProject, a as collectStubMounts, at as parseCoverageEnvelope, b as buildJestArgv, c as runTypecheck, ct as loadConfig, d as resolveAllProjects, dt as GLOBAL_TEST_KEYS, et as applyAttribution, f as StudioBackend, ft as JEST_ARGV_EXCLUDED_KEYS, g as OpenCloudBackend, gt as defineConfig, h as createStudioCliBackend, i as buildImplicitProject, it as normalizeRawCoverage, j as emitBuildManifest, k as BUILD_MANIFEST_VERSION, l as cleanLeftoverStubs, lt as resolveConfig, m as StudioCliBackend, mt as SHARED_TEST_KEYS, n as runJestRoblox, nt as extractJsonFromOutput, o as loadRojoTree, ot as mergeRawCoverage, p as createStudioBackend, pt as ROOT_CLI_KEYS, q as formatTestSummary, r as runSingleOrMulti, rt as parseJestOutput, s as prepareBakedCoverage, st as mergeCliWithConfig, t as getRawProjects, u as generateProjectStubs, ut as DEFAULT_CONFIG, w as findRojoProject, x as generateTestScript, z as formatGameOutputNotice } from "./run-BKP7mem2.mjs";
2
2
  import * as path$1 from "node:path";
3
+ //#region src/artifacts/build-coverage-place.ts
4
+ const CACHE_DIR$1 = path$1.join(".jest-roblox", "cache");
5
+ /**
6
+ * Build the coverage-instrumented place **without running it** — the offline
7
+ * half of the split producer. Instruments (incrementally) and rojo-builds the
8
+ * place, bakes each project's `jest.config` stub into it so any runner that
9
+ * opens the place can discover and run the suite unaided, publishes the sibling
10
+ * Build + Coverage manifests, and hands back the place. No backend is resolved,
11
+ * no suite executes, nothing hits the network. Coverage collection is forced on
12
+ * regardless of the input config.
13
+ *
14
+ * The counterpart to `prepareArtifacts`, minus the run and the Clean Place —
15
+ * the entry point for a machine that cannot execute Roblox at all. It shares the
16
+ * `prepareBakedCoverage` seam with the run path but always bakes stubs (the run
17
+ * path skips baking for studio-cli, which injects configs at runtime), because a
18
+ * place handed to a foreign runner must be self-contained.
19
+ */
20
+ async function buildCoveragePlace(config) {
21
+ const merged = mergeCliWithConfig({}, {
22
+ ...config,
23
+ collectCoverage: true
24
+ });
25
+ const projects = await resolveProjects(merged);
26
+ const cacheRoot = path$1.resolve(merged.rootDir, CACHE_DIR$1);
27
+ cleanLeftoverStubs(projects, merged.rootDir);
28
+ generateProjectStubs(projects, merged.rootDir, cacheRoot);
29
+ const { artifacts } = prepareBakedCoverage(merged, projects, cacheRoot, true);
30
+ if (artifacts.rebuilt) emitBuildManifest(COVERAGE_BUILD_MANIFEST_PATH, artifacts);
31
+ return {
32
+ buildId: artifacts.buildId,
33
+ buildManifestPath: COVERAGE_BUILD_MANIFEST_PATH,
34
+ coverageManifestPath: COVERAGE_MANIFEST_PATH,
35
+ coveragePlace: artifacts.coveragePlace,
36
+ projects: artifacts.projects,
37
+ rebuilt: artifacts.rebuilt
38
+ };
39
+ }
40
+ /**
41
+ * Resolve the project set the place is built from, mirroring `runSingleOrMulti`
42
+ * dispatch: an explicit `projects:` config resolves through `resolveAllProjects`;
43
+ * a bare config collapses to the single implicit project derived from its luau
44
+ * roots. Type-only configs are irrelevant here — a build always instruments.
45
+ */
46
+ async function resolveProjects(config) {
47
+ const rojoTree = loadRojoTree(config);
48
+ const rawProjects = getRawProjects(config);
49
+ if (rawProjects !== void 0 && rawProjects.length > 0) return resolveAllProjects(rawProjects, config, rojoTree, config.rootDir);
50
+ return [buildImplicitProject(config, rojoTree)];
51
+ }
52
+ //#endregion
3
53
  //#region src/artifacts/prepare-artifacts.ts
4
54
  const COVERAGE_DIR = path$1.dirname(COVERAGE_BUILD_MANIFEST_PATH);
5
55
  const CLEAN_PLACE_FILE = path$1.join(COVERAGE_DIR, "clean.rbxl");
@@ -81,4 +131,4 @@ async function buildCleanPlace(config) {
81
131
  });
82
132
  }
83
133
  //#endregion
84
- export { BUILD_MANIFEST_VERSION, DEFAULT_CONFIG, GLOBAL_TEST_KEYS, JEST_ARGV_EXCLUDED_KEYS, MANIFEST_VERSION, OpenCloudBackend, ROOT_CLI_KEYS, SHARED_TEST_KEYS, StudioBackend, StudioCliBackend, buildJestArgv, buildManifestSchema, manifestSchema as coverageManifestSchema, createOpenCloudBackend, createStudioBackend, createStudioCliBackend, defineConfig, defineProject, extractJsonFromOutput, formatAnnotations, formatExecuteOutput, formatFailure, formatGameOutputNotice, formatJobSummary, formatJson, formatResult, formatTestSummary, generateTestScript, hashFile, loadConfig, parseGameOutput, parseJestOutput, prepareArtifacts, readBuildManifest, readManifest as readCoverageManifest, resolveConfig, runJestRoblox, runProjects, runTypecheck, visitBlock, visitExpression, visitStatement, writeGameOutput, writeJsonFile };
134
+ export { BUILD_MANIFEST_VERSION, DEFAULT_CONFIG, GLOBAL_TEST_KEYS, JEST_ARGV_EXCLUDED_KEYS, MANIFEST_VERSION, OpenCloudBackend, ROOT_CLI_KEYS, SHARED_TEST_KEYS, StudioBackend, StudioCliBackend, buildCoveragePlace, buildJestArgv, buildManifestSchema, manifestSchema as coverageManifestSchema, createOpenCloudBackend, createStudioBackend, createStudioCliBackend, defineConfig, defineProject, extractJsonFromOutput, formatAnnotations, formatExecuteOutput, formatFailure, formatGameOutputNotice, formatJobSummary, formatJson, formatResult, formatTestSummary, generateTestScript, hashFile, loadConfig, mergeRawCoverage, normalizeRawCoverage, parseCoverageEnvelope, parseGameOutput, parseJestOutput, prepareArtifacts, readBuildManifest, readManifest as readCoverageManifest, resolveConfig, runJestRoblox, runProjects, runTypecheck, visitBlock, visitExpression, visitStatement, writeGameOutput, writeJsonFile };