@sdeverywhere/plugin-check 0.1.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/package.json ADDED
@@ -0,0 +1,62 @@
1
+ {
2
+ "name": "@sdeverywhere/plugin-check",
3
+ "version": "0.1.0",
4
+ "files": [
5
+ "dist/**",
6
+ "template-bundle/**",
7
+ "template-report/**",
8
+ "template-tests/**"
9
+ ],
10
+ "type": "module",
11
+ "main": "dist/index.cjs",
12
+ "module": "dist/index.js",
13
+ "types": "dist/index.d.ts",
14
+ "exports": {
15
+ ".": {
16
+ "types": "./dist/index.d.ts",
17
+ "import": "./dist/index.js",
18
+ "require": "./dist/index.cjs"
19
+ }
20
+ },
21
+ "dependencies": {
22
+ "@rollup/plugin-node-resolve": "^13.3.0",
23
+ "@rollup/plugin-replace": "^2.4.1",
24
+ "@sdeverywhere/build": "^0.1.0",
25
+ "@sdeverywhere/check-core": "^0.1.0",
26
+ "@sdeverywhere/check-ui-shell": "^0.1.0",
27
+ "@sdeverywhere/runtime": "^0.1.0",
28
+ "@sdeverywhere/runtime-async": "^0.1.0",
29
+ "assert-never": "^1.2.1",
30
+ "picocolors": "^1.0.0",
31
+ "rollup-plugin-node-polyfills": "^0.2.1",
32
+ "vite": "^2.9.12",
33
+ "vite-plugin-glob": "^0.3.2"
34
+ },
35
+ "devDependencies": {
36
+ "@types/node": "^16.11.7"
37
+ },
38
+ "author": "Climate Interactive",
39
+ "license": "MIT",
40
+ "homepage": "https://sdeverywhere.org",
41
+ "repository": {
42
+ "type": "git",
43
+ "url": "https://github.com/climateinteractive/SDEverywhere.git",
44
+ "directory": "packages/plugin-check"
45
+ },
46
+ "bugs": {
47
+ "url": "https://github.com/climateinteractive/SDEverywhere/issues"
48
+ },
49
+ "scripts": {
50
+ "clean": "rm -rf dist",
51
+ "lint": "eslint src --ext .ts --max-warnings 0",
52
+ "prettier:check": "prettier --check .",
53
+ "prettier:fix": "prettier --write .",
54
+ "precommit": "../../scripts/precommit",
55
+ "test": "echo No tests yet",
56
+ "test:watch": "echo No tests yet",
57
+ "test:ci": "echo No tests yet",
58
+ "type-check": "tsc --noEmit -p tsconfig-build.json",
59
+ "build": "tsup",
60
+ "ci:build": "run-s clean lint prettier:check test:ci type-check build"
61
+ }
62
+ }
@@ -0,0 +1,8 @@
1
+ {
2
+ "dependencies": {
3
+ "@sdeverywhere/check-core": "^0.1.0",
4
+ "@sdeverywhere/runtime": "^0.1.0",
5
+ "@sdeverywhere/runtime-async": "^0.1.0",
6
+ "assert-never": "^1.2.1"
7
+ }
8
+ }
@@ -0,0 +1,172 @@
1
+ // Copyright (c) 2022 Climate Interactive / New Venture Fund
2
+
3
+ import type {
4
+ Bundle,
5
+ BundleGraphData,
6
+ BundleModel as CheckBundleModel,
7
+ Dataset,
8
+ DatasetKey,
9
+ DatasetMap,
10
+ DatasetsResult,
11
+ LinkItem,
12
+ ModelSpec,
13
+ Scenario
14
+ } from '@sdeverywhere/check-core'
15
+
16
+ import type { InputValue, InputVarId, ModelRunner, Point } from '@sdeverywhere/runtime'
17
+ import { Outputs } from '@sdeverywhere/runtime'
18
+ import { spawnAsyncModelRunner } from '@sdeverywhere/runtime-async'
19
+
20
+ import type { Input } from './inputs'
21
+ import { getInputVars, setInputsForScenario } from './inputs'
22
+ import { getOutputVars } from './outputs'
23
+
24
+ import { startTime, endTime, inputSpecs, outputSpecs } from 'virtual:model-spec'
25
+
26
+ import modelWorkerJs from '@_model_worker_/worker.js?raw'
27
+
28
+ // The current version of the check bundle format. This should be
29
+ // incremented when there is an incompatible change to the bundle format.
30
+ // The model-check tools can use this value to skip tests if two bundles
31
+ // have different version numbers.
32
+ const VERSION = 1
33
+
34
+ // The size (in bytes) of the model file(s), injected at build time.
35
+ const __MODEL_SIZE_IN_BYTES__ = 1
36
+ const modelSizeInBytes = __MODEL_SIZE_IN_BYTES__
37
+
38
+ // The size (in bytes) of the data file(s), injected at build time.
39
+ const __DATA_SIZE_IN_BYTES__ = 1
40
+ const dataSizeInBytes = __DATA_SIZE_IN_BYTES__
41
+
42
+ export class BundleModel implements CheckBundleModel {
43
+ private readonly inputs: InputValue[]
44
+ private outputs: Outputs
45
+
46
+ /**
47
+ * @param modelSpec The spec for the bundled model.
48
+ * @param inputMap The model inputs.
49
+ * @param modelRunner The model runner.
50
+ */
51
+ constructor(
52
+ public readonly modelSpec: ModelSpec,
53
+ private readonly inputMap: Map<InputVarId, Input>,
54
+ private readonly modelRunner: ModelRunner
55
+ ) {
56
+ // Derive an array of `InputValue` instances that can be passed to the runner
57
+ this.inputs = [...inputMap.values()].map(input => input.value)
58
+
59
+ // Create an `Outputs` instance that is initialized to hold output data
60
+ // produced by the Wasm model
61
+ const outputVarIds = outputSpecs.map(o => o.varId)
62
+ this.outputs = new Outputs(outputVarIds, startTime, endTime)
63
+ }
64
+
65
+ // from CheckBundleModel interface
66
+ async getDatasetsForScenario(scenario: Scenario, datasetKeys: DatasetKey[]): Promise<DatasetsResult> {
67
+ const datasetMap: DatasetMap = new Map()
68
+
69
+ // Set the input values according to the given scenario
70
+ setInputsForScenario(this.inputMap, scenario)
71
+
72
+ // Run the JS model
73
+ this.outputs = await this.modelRunner.runModel(this.inputs, this.outputs)
74
+ const modelRunTime = this.outputs.runTimeInMillis
75
+
76
+ // Extract the data for each requested output variable and put it into a map
77
+ for (const datasetKey of datasetKeys) {
78
+ // Get the output variable for the given dataset key; if the variable doesn't
79
+ // exist in this version of the model/bundle, just skip it
80
+ const outputVar = this.modelSpec.outputVars.get(datasetKey)
81
+ if (!outputVar) {
82
+ continue
83
+ }
84
+
85
+ if (outputVar.sourceName === undefined) {
86
+ // See if we have data for the requested model output variable
87
+ const series = this.outputs.getSeriesForVar(outputVar.varId)
88
+ if (series) {
89
+ datasetMap.set(datasetKey, datasetFromPoints(series.points))
90
+ }
91
+ } else {
92
+ console.error('Static data sources not yet handled in default model check bundle')
93
+ }
94
+ }
95
+
96
+ return {
97
+ datasetMap,
98
+ modelRunTime
99
+ }
100
+ }
101
+
102
+ // from CheckBundleModel interface
103
+ // TODO: This function should be optional
104
+ async getGraphDataForScenario(): Promise<BundleGraphData> {
105
+ return undefined
106
+ }
107
+
108
+ // from CheckBundleModel interface
109
+ // TODO: This function should be optional
110
+ getGraphLinksForScenario(): LinkItem[] {
111
+ return []
112
+ }
113
+ }
114
+
115
+ /**
116
+ * Initialize a `BundleModel` instance that supports the running the model
117
+ * under different scenarios.
118
+ */
119
+ async function initBundleModel(modelSpec: ModelSpec, inputMap: Map<InputVarId, Input>): Promise<BundleModel> {
120
+ // Initialize the Wasm model asynchronously. We inline the worker code in the
121
+ // rolled-up bundle so that we don't have to fetch a separate `worker.js` file
122
+ const modelRunner = await spawnAsyncModelRunner({ source: modelWorkerJs })
123
+
124
+ // Return a `BundleModel` that wraps the underlying config and Wasm model
125
+ return new BundleModel(modelSpec, inputMap, modelRunner)
126
+ }
127
+
128
+ /**
129
+ * Create a `Dataset` containing the given data points from the model.
130
+ */
131
+ export function datasetFromPoints(points: Point[]): Dataset {
132
+ const dataMap = new Map()
133
+ for (const point of points) {
134
+ // We omit points that have an undefined value. SDE represents `:NA:` values as
135
+ // a special value (`-DBL_MAX`); the `runtime` package detects these and converts
136
+ // them to undefined instead. We don't need them to appear in graphs, so omit them.
137
+ if (point.y !== undefined) {
138
+ dataMap.set(point.x, point.y)
139
+ }
140
+ }
141
+ return dataMap
142
+ }
143
+
144
+ /**
145
+ * Return a `Bundle` that can be used for running comparisons between two
146
+ * bundles containing different versions of the sample model.
147
+ */
148
+ export function createBundle(): Bundle {
149
+ // Gather information about the input and output variables used in the model
150
+ const inputVars = getInputVars(inputSpecs)
151
+ const outputVars = getOutputVars(outputSpecs)
152
+
153
+ const modelSpec: ModelSpec = {
154
+ modelSizeInBytes,
155
+ dataSizeInBytes,
156
+ inputVars,
157
+ outputVars,
158
+ implVars: new Map(),
159
+ inputGroups: new Map(),
160
+ datasetGroups: new Map(),
161
+ startTime,
162
+ endTime
163
+ }
164
+
165
+ return {
166
+ version: VERSION,
167
+ modelSpec,
168
+ initModel: () => {
169
+ return initBundleModel(modelSpec, inputVars)
170
+ }
171
+ }
172
+ }
@@ -0,0 +1,15 @@
1
+ // Copyright (c) 2022 Climate Interactive / New Venture Fund
2
+
3
+ /*
4
+ * This no-op module is configured as the default path alias in the tsconfig
5
+ * files so that TypeScript does not complain. (The actual module will be set
6
+ * up using aliases in the Vite config file.)
7
+ */
8
+
9
+ import type { InputSpec } from './inputs'
10
+ import type { OutputSpec } from './outputs'
11
+
12
+ export const startTime = 0
13
+ export const endTime = 0
14
+ export const inputSpecs: InputSpec[] = []
15
+ export const outputSpecs: OutputSpec[] = []
@@ -0,0 +1,3 @@
1
+ // Copyright (c) 2021-2022 Climate Interactive / New Venture Fund
2
+
3
+ export { createBundle } from './bundle'
@@ -0,0 +1,139 @@
1
+ // Copyright (c) 2022 Climate Interactive / New Venture Fund
2
+
3
+ import { assertNever } from 'assert-never'
4
+
5
+ import type { InputVar, Scenario } from '@sdeverywhere/check-core'
6
+ import type { InputValue, InputVarId } from '@sdeverywhere/runtime'
7
+ import { createInputValue } from '@sdeverywhere/runtime'
8
+
9
+ export interface InputSpec {
10
+ /** The variable identifier (as used by SDEverywhere). */
11
+ varId: string
12
+ /** The variable name (as used in the modeling tool). */
13
+ varName: string
14
+ /** The default value for the input. */
15
+ defaultValue: number
16
+ /** The minimum value for the input. */
17
+ minValue: number
18
+ /** The maximum value for the input. */
19
+ maxValue: number
20
+ }
21
+
22
+ export interface Input extends InputVar {
23
+ value: InputValue
24
+ }
25
+
26
+ /**
27
+ * Gather the set of input variables used in this version of the model.
28
+ */
29
+ export function getInputVars(inputSpecs: InputSpec[]): Map<InputVarId, Input> {
30
+ const inputs: Map<InputVarId, Input> = new Map()
31
+ for (const inputSpec of inputSpecs) {
32
+ const varId = inputSpec.varId
33
+ const input: Input = {
34
+ varId,
35
+ varName: inputSpec.varName,
36
+ defaultValue: inputSpec.defaultValue,
37
+ minValue: inputSpec.minValue,
38
+ maxValue: inputSpec.maxValue,
39
+ value: createInputValue(varId, inputSpec.defaultValue)
40
+ }
41
+ inputs.set(varId, input)
42
+ }
43
+ return inputs
44
+ }
45
+
46
+ /**
47
+ * Set the given `Input` instances according to the given scenario.
48
+ */
49
+ export function setInputsForScenario(inputs: Map<InputVarId, Input>, scenario: Scenario): void {
50
+ function setInputToValue(input: Input, value: number): void {
51
+ if (value < input.minValue) {
52
+ // TODO: Set an error status so that the scenario is flagged as an
53
+ // error in the UI (for now, just warn and clamp)
54
+ console.warn(
55
+ `WARNING: Scenario input value ${value} is < min value (${input.minValue}) ` + `for input '${input.varName}'`
56
+ )
57
+ value = input.minValue
58
+ } else if (value > input.maxValue) {
59
+ console.warn(
60
+ `WARNING: Scenario input value ${value} is > max value (${input.maxValue}) ` + `for input '${input.varName}'`
61
+ )
62
+ value = input.maxValue
63
+ }
64
+ input.value.set(value)
65
+ }
66
+
67
+ function setInputToDefault(input: Input): void {
68
+ input.value.reset()
69
+ }
70
+ function setInputToMinimum(input: Input): void {
71
+ input.value.set(input.minValue)
72
+ }
73
+ function setInputToMaximum(input: Input): void {
74
+ input.value.set(input.minValue)
75
+ }
76
+
77
+ function setAllToDefault(): void {
78
+ inputs.forEach(setInputToDefault)
79
+ }
80
+ function setAllToMinimum(): void {
81
+ inputs.forEach(setInputToMinimum)
82
+ }
83
+ function setAllToMaximum(): void {
84
+ inputs.forEach(setInputToMaximum)
85
+ }
86
+
87
+ // Set inputs according to the given scenario
88
+ switch (scenario.kind) {
89
+ case 'all-inputs': {
90
+ switch (scenario.position) {
91
+ case 'at-default':
92
+ setAllToDefault()
93
+ break
94
+ case 'at-minimum':
95
+ setAllToMinimum()
96
+ break
97
+ case 'at-maximum':
98
+ setAllToMaximum()
99
+ break
100
+ }
101
+ break
102
+ }
103
+ case 'settings': {
104
+ setAllToDefault()
105
+ for (const setting of scenario.settings) {
106
+ const input = inputs.get(setting.inputVarId)
107
+ if (input) {
108
+ switch (setting.kind) {
109
+ case 'position':
110
+ switch (setting.position) {
111
+ case 'at-default':
112
+ setInputToDefault(input)
113
+ break
114
+ case 'at-minimum':
115
+ setInputToMinimum(input)
116
+ break
117
+ case 'at-maximum':
118
+ setInputToMaximum(input)
119
+ break
120
+ default:
121
+ assertNever(setting.position)
122
+ }
123
+ break
124
+ case 'value':
125
+ setInputToValue(input, setting.value)
126
+ break
127
+ default:
128
+ assertNever(setting)
129
+ }
130
+ } else {
131
+ console.log(`No model input for scenario input ${setting.inputVarId}`)
132
+ }
133
+ }
134
+ break
135
+ }
136
+ default:
137
+ assertNever(scenario)
138
+ }
139
+ }
@@ -0,0 +1,36 @@
1
+ // Copyright (c) 2022 Climate Interactive / New Venture Fund
2
+
3
+ import type { DatasetKey, OutputVar, SourceName } from '@sdeverywhere/check-core'
4
+ import type { OutputVarId } from '@sdeverywhere/runtime'
5
+
6
+ export interface OutputSpec {
7
+ /** The variable identifier (as used by SDEverywhere). */
8
+ varId: string
9
+ /** The variable name (as used in the modeling tool). */
10
+ varName: string
11
+ }
12
+
13
+ /**
14
+ * Gather the list of output variables (and their related graphs, etc) used
15
+ * in this version of the model.
16
+ */
17
+ export function getOutputVars(outputSpecs: OutputSpec[]): Map<DatasetKey, OutputVar> {
18
+ // Convert the specs to `OutputVar` instances
19
+ const outputVars: Map<DatasetKey, OutputVar> = new Map()
20
+
21
+ for (const outputSpec of outputSpecs) {
22
+ const varId = outputSpec.varId
23
+ const datasetKey = datasetKeyForOutputVar(undefined, varId)
24
+ outputVars.set(datasetKey, {
25
+ sourceName: undefined,
26
+ varId,
27
+ varName: outputSpec.varName
28
+ })
29
+ }
30
+
31
+ return outputVars
32
+ }
33
+
34
+ export function datasetKeyForOutputVar(sourceName: SourceName | undefined, varId: OutputVarId): DatasetKey {
35
+ return `${sourceName || 'Model'}_${varId}`
36
+ }
@@ -0,0 +1,9 @@
1
+ // Copyright (c) 2022 Climate Interactive / New Venture Fund
2
+
3
+ /*
4
+ * This no-op module is configured as the default path alias in the tsconfig
5
+ * files so that TypeScript does not complain. (The actual module will be set
6
+ * up using aliases in the Vite config file.)
7
+ */
8
+
9
+ export const unused = 0
@@ -0,0 +1,27 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "es6",
4
+ // Use "es2020" for dynamic import
5
+ "module": "es2020",
6
+ // Emit additional JS to ease support for importing CommonJS modules
7
+ "esModuleInterop": true,
8
+ // Use Node.js-style module resolution
9
+ "moduleResolution": "node",
10
+ // Enable warnings for transpilation-unsafe code
11
+ "isolatedModules": true,
12
+ // Enable strict enforcement of `import type`
13
+ "importsNotUsedAsValues": "error",
14
+ "noImplicitAny": true,
15
+ "noUnusedLocals": true,
16
+ "noUnusedParameters": true,
17
+ "types": ["vite/client"],
18
+ // Use placeholders for path aliases that are configured in the Vite
19
+ // config; this prevents TypeScript from complaining but still allows
20
+ // for plugging in "real" files later
21
+ "baseUrl": ".",
22
+ "paths": {
23
+ "virtual:model-spec": ["./src/empty-model-spec.ts"],
24
+ "@_model_worker_": ["./src"]
25
+ }
26
+ }
27
+ }
@@ -0,0 +1,27 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <title>Model Check</title>
5
+
6
+ <meta charset="UTF-8" />
7
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
8
+
9
+ <link rel="preconnect" href="https://fonts.googleapis.com" />
10
+ <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
11
+ <link
12
+ href="https://fonts.googleapis.com/css2?family=Roboto+Condensed:wght@400&family=Roboto:wght@500;700&display=swap"
13
+ rel="stylesheet"
14
+ />
15
+
16
+ <script type="module" src="./src/index.ts"></script>
17
+ </head>
18
+
19
+ <body>
20
+ <div id="app-shell-container"></div>
21
+ <div id="overlay-container">
22
+ <div id="overlay-content">
23
+ <div id="overlay-text"></div>
24
+ </div>
25
+ </div>
26
+ </body>
27
+ </html>
@@ -0,0 +1,6 @@
1
+ {
2
+ "dependencies": {
3
+ "@sdeverywhere/check-core": "^0.1.0",
4
+ "@sdeverywhere/check-ui-shell": "^0.1.0"
5
+ }
6
+ }
@@ -0,0 +1,23 @@
1
+ // Copyright (c) 2022 Climate Interactive / New Venture Fund
2
+
3
+ import type { Bundle } from '@sdeverywhere/check-core'
4
+
5
+ /*
6
+ * This module serves two purposes:
7
+ *
8
+ * 1. It is configured as the default path alias in the tsconfig files so
9
+ * that TypeScript does not complain. (The actual bundles will be set
10
+ * up using aliases in the Vite config file.)
11
+ *
12
+ * 2. It is used as a default no-op bundle in the case where a baseline
13
+ * bundle is not used (in which case no comparison tests will be run
14
+ * and only the current bundle will be checked).
15
+ */
16
+
17
+ export function createBundle(): Bundle {
18
+ return {
19
+ version: -1,
20
+ modelSpec: undefined,
21
+ initModel: () => undefined
22
+ }
23
+ }
@@ -0,0 +1,24 @@
1
+ // Copyright (c) 2022 Climate Interactive / New Venture Fund
2
+
3
+ /*
4
+ * This no-op module is configured as the default path alias in the tsconfig
5
+ * files so that TypeScript does not complain. (The actual module will be set
6
+ * up using aliases in the Vite config file.)
7
+ */
8
+
9
+ import type { Bundle, ConfigOptions } from '@sdeverywhere/check-core'
10
+
11
+ export interface BundleOptions {
12
+ nameL?: string
13
+ nameR?: string
14
+ }
15
+
16
+ export async function getConfigOptions(
17
+ /* eslint-disable @typescript-eslint/no-unused-vars */
18
+ _bundleL: Bundle | undefined,
19
+ _bundleR: Bundle,
20
+ _opts: BundleOptions
21
+ /* eslint-enable @typescript-eslint/no-unused-vars */
22
+ ): Promise<ConfigOptions> {
23
+ return undefined
24
+ }
@@ -0,0 +1,7 @@
1
+ // Copyright (c) 2022 Climate Interactive / New Venture Fund
2
+
3
+ // These values are injected by Vite at build time, so we need to
4
+ // declare types for them here
5
+ declare const __BASELINE_NAME__: string
6
+ declare const __CURRENT_NAME__: string
7
+ declare const __SUITE_SUMMARY_JSON__: string
@@ -0,0 +1,22 @@
1
+ #overlay-content {
2
+ position: fixed;
3
+ display: flex;
4
+ flex-direction: column;
5
+ flex: 1;
6
+ bottom: 0;
7
+ right: 0;
8
+ margin-right: 1rem;
9
+ margin-bottom: 1rem;
10
+ max-width: 80%;
11
+ max-height: 80%;
12
+ overflow-y: auto;
13
+ padding: 1rem;
14
+ border-radius: 0.5rem;
15
+ background-color: #ddd;
16
+ color: #000;
17
+ box-shadow: 0 3px 6px rgba(0, 0, 0, 0.8);
18
+ }
19
+
20
+ #overlay-content .overlay-error {
21
+ color: crimson;
22
+ }
@@ -0,0 +1,56 @@
1
+ // Copyright (c) 2022 Climate Interactive / New Venture Fund
2
+
3
+ import type { Bundle, SuiteSummary } from '@sdeverywhere/check-core'
4
+
5
+ import { initAppShell } from '@sdeverywhere/check-ui-shell'
6
+ import '@sdeverywhere/check-ui-shell/dist/style.css'
7
+
8
+ import { initOverlay } from './overlay'
9
+
10
+ import './global.css'
11
+
12
+ // These aliases are specified in the Vite config to point to the actual bundles
13
+ import { createBundle as createBaselineBundle } from '@_baseline_bundle_'
14
+ import { createBundle as createCurrentBundle } from '@_current_bundle_'
15
+ import { getConfigOptions } from '@_test_config_'
16
+
17
+ // For "production" builds, load the summary from a JSON file that
18
+ // was generated as part of the build process. This makes the
19
+ // report load almost immediately instead of running all the checks
20
+ // in the user's browser.
21
+ const suiteSummaryJson = __SUITE_SUMMARY_JSON__
22
+ let suiteSummary: SuiteSummary
23
+ if (suiteSummaryJson) {
24
+ suiteSummary = JSON.parse(suiteSummaryJson) as SuiteSummary
25
+ }
26
+
27
+ async function init() {
28
+ // Load the bundles used by the model check/compare configuration. We
29
+ // always initialize the "current" bundle.
30
+ const bundleR: Bundle = createCurrentBundle()
31
+
32
+ // Only initialize the "baseline" bundle if it is defined and the version
33
+ // is the same as the "current" one. If the baseline bundle has a different
34
+ // version, we will skip the comparison tests and only run the checks on the
35
+ // current bundle.
36
+ let bundleL: Bundle
37
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
38
+ const rawBundleL: any = createBaselineBundle()
39
+ if (rawBundleL.version === bundleR.version) {
40
+ bundleL = rawBundleL as Bundle
41
+ }
42
+
43
+ // Prepare the model check/compare configuration
44
+ const checkOptions = await getConfigOptions(bundleL, bundleR, {
45
+ nameL: __BASELINE_NAME__ || undefined,
46
+ nameR: __CURRENT_NAME__
47
+ })
48
+
49
+ // Initialize the root Svelte component
50
+ initAppShell(checkOptions, suiteSummary)
51
+
52
+ // Initialize the overlay element used to show builder messages/errors
53
+ initOverlay()
54
+ }
55
+
56
+ init()
@@ -0,0 +1,6 @@
1
+ <!--
2
+ NOTE: This file is only referenced by `tsconfig.json` for the purposes of
3
+ configuring the '@_prep_' path alias; it is not included with the report
4
+ build. In the Vite config, we will use a different alias that points to
5
+ the actual `messages.html` file under the configured sde "prep" directory.
6
+ -->