@sdeverywhere/plugin-check 0.3.19 → 0.3.21
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/sde-check.js +8 -14
- package/dist/index.cjs +289 -109
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +48 -5
- package/dist/index.d.ts +48 -5
- package/dist/index.js +275 -95
- package/dist/index.js.map +1 -1
- package/package.json +6 -6
- package/template-bundle/src/bundle-model-runner.ts +159 -0
- package/template-bundle/src/bundle.ts +20 -73
- package/template-bundle/src/empty-model-spec.ts +4 -0
- package/template-bundle/src/impl-vars.ts +59 -0
- package/template-report/index.html +22 -0
- package/template-report/src/{baselines → bundles}/unused.txt +1 -1
- package/template-report/src/env.d.ts +3 -1
- package/template-report/src/index.ts +289 -84
|
@@ -4,25 +4,24 @@ import type {
|
|
|
4
4
|
Bundle,
|
|
5
5
|
BundleGraphData,
|
|
6
6
|
BundleModel as CheckBundleModel,
|
|
7
|
-
Dataset,
|
|
8
7
|
DatasetKey,
|
|
9
|
-
DatasetMap,
|
|
10
8
|
DatasetsResult,
|
|
11
9
|
LinkItem,
|
|
12
10
|
ModelSpec,
|
|
13
11
|
ScenarioSpec
|
|
14
12
|
} from '@sdeverywhere/check-core'
|
|
15
13
|
|
|
16
|
-
import type {
|
|
14
|
+
import type { InputVarId } from '@sdeverywhere/runtime'
|
|
17
15
|
import { spawnAsyncModelRunner } from '@sdeverywhere/runtime-async'
|
|
18
16
|
|
|
19
|
-
import
|
|
20
|
-
import {
|
|
17
|
+
import { getImplVars } from './impl-vars'
|
|
18
|
+
import { type Input, getInputVars } from './inputs'
|
|
21
19
|
import { getOutputVars } from './outputs'
|
|
22
20
|
|
|
23
|
-
import { inputSpecs, outputSpecs, modelSizeInBytes, dataSizeInBytes } from 'virtual:model-spec'
|
|
21
|
+
import { encodedImplVars, inputSpecs, outputSpecs, modelSizeInBytes, dataSizeInBytes } from 'virtual:model-spec'
|
|
24
22
|
|
|
25
23
|
import modelWorkerJs from '@_model_worker_/worker.js?raw'
|
|
24
|
+
import { BundleModelRunner } from './bundle-model-runner'
|
|
26
25
|
|
|
27
26
|
// The current version of the check bundle format. This should be
|
|
28
27
|
// incremented when there is an incompatible change to the bundle format.
|
|
@@ -31,62 +30,18 @@ import modelWorkerJs from '@_model_worker_/worker.js?raw'
|
|
|
31
30
|
const VERSION = 1
|
|
32
31
|
|
|
33
32
|
export class BundleModel implements CheckBundleModel {
|
|
34
|
-
private readonly inputs: InputValue[]
|
|
35
|
-
private outputs: Outputs
|
|
36
|
-
|
|
37
33
|
/**
|
|
38
34
|
* @param modelSpec The spec for the bundled model.
|
|
39
|
-
* @param
|
|
40
|
-
* @param modelRunner The model runner.
|
|
35
|
+
* @param bundleModelRunner The bundle model runner.
|
|
41
36
|
*/
|
|
42
37
|
constructor(
|
|
43
38
|
public readonly modelSpec: ModelSpec,
|
|
44
|
-
private readonly
|
|
45
|
-
|
|
46
|
-
) {
|
|
47
|
-
// Derive an array of `InputValue` instances that can be passed to the runner
|
|
48
|
-
this.inputs = [...inputMap.values()].map(input => input.value)
|
|
49
|
-
|
|
50
|
-
// Create an `Outputs` instance that is initialized to hold output data
|
|
51
|
-
// produced by the Wasm model
|
|
52
|
-
this.outputs = modelRunner.createOutputs()
|
|
53
|
-
}
|
|
39
|
+
private readonly bundleModelRunner: BundleModelRunner
|
|
40
|
+
) {}
|
|
54
41
|
|
|
55
42
|
// from CheckBundleModel interface
|
|
56
43
|
async getDatasetsForScenario(scenario: ScenarioSpec, datasetKeys: DatasetKey[]): Promise<DatasetsResult> {
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
// Set the input values according to the given scenario
|
|
60
|
-
setInputsForScenario(this.inputMap, scenario)
|
|
61
|
-
|
|
62
|
-
// Run the JS model
|
|
63
|
-
this.outputs = await this.modelRunner.runModel(this.inputs, this.outputs)
|
|
64
|
-
const modelRunTime = this.outputs.runTimeInMillis
|
|
65
|
-
|
|
66
|
-
// Extract the data for each requested output variable and put it into a map
|
|
67
|
-
for (const datasetKey of datasetKeys) {
|
|
68
|
-
// Get the output variable for the given dataset key; if the variable doesn't
|
|
69
|
-
// exist in this version of the model/bundle, just skip it
|
|
70
|
-
const outputVar = this.modelSpec.outputVars.get(datasetKey)
|
|
71
|
-
if (!outputVar) {
|
|
72
|
-
continue
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
if (outputVar.sourceName === undefined) {
|
|
76
|
-
// See if we have data for the requested model output variable
|
|
77
|
-
const series = this.outputs.getSeriesForVar(outputVar.varId)
|
|
78
|
-
if (series) {
|
|
79
|
-
datasetMap.set(datasetKey, datasetFromPoints(series.points))
|
|
80
|
-
}
|
|
81
|
-
} else {
|
|
82
|
-
console.error('Static data sources not yet handled in default model check bundle')
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
return {
|
|
87
|
-
datasetMap,
|
|
88
|
-
modelRunTime
|
|
89
|
-
}
|
|
44
|
+
return this.bundleModelRunner.runModelForScenario(scenario, datasetKeys)
|
|
90
45
|
}
|
|
91
46
|
|
|
92
47
|
// from CheckBundleModel interface
|
|
@@ -107,28 +62,16 @@ export class BundleModel implements CheckBundleModel {
|
|
|
107
62
|
* under different scenarios.
|
|
108
63
|
*/
|
|
109
64
|
async function initBundleModel(modelSpec: ModelSpec, inputMap: Map<InputVarId, Input>): Promise<BundleModel> {
|
|
110
|
-
// Initialize the Wasm model asynchronously. We inline the worker code in the
|
|
65
|
+
// Initialize the JS/Wasm model asynchronously. We inline the worker code in the
|
|
111
66
|
// rolled-up bundle so that we don't have to fetch a separate `worker.js` file
|
|
112
67
|
const modelRunner = await spawnAsyncModelRunner({ source: modelWorkerJs })
|
|
113
68
|
|
|
114
|
-
//
|
|
115
|
-
|
|
116
|
-
|
|
69
|
+
// Create a `BundleModelRunner` that wraps the `ModelRunner` instance and takes
|
|
70
|
+
// care of translating `runtime` types to the types expected by `check-core`
|
|
71
|
+
const bundleModelRunner = new BundleModelRunner(modelSpec, inputMap, modelRunner)
|
|
117
72
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
*/
|
|
121
|
-
export function datasetFromPoints(points: Point[]): Dataset {
|
|
122
|
-
const dataMap = new Map()
|
|
123
|
-
for (const point of points) {
|
|
124
|
-
// We omit points that have an undefined value. SDE represents `:NA:` values as
|
|
125
|
-
// a special value (`-DBL_MAX`); the `runtime` package detects these and converts
|
|
126
|
-
// them to undefined instead. We don't need them to appear in graphs, so omit them.
|
|
127
|
-
if (point.y !== undefined) {
|
|
128
|
-
dataMap.set(point.x, point.y)
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
return dataMap
|
|
73
|
+
// Return a `BundleModel` that wraps the underlying config and Wasm model
|
|
74
|
+
return new BundleModel(modelSpec, bundleModelRunner)
|
|
132
75
|
}
|
|
133
76
|
|
|
134
77
|
/**
|
|
@@ -140,12 +83,16 @@ export function createBundle(): Bundle {
|
|
|
140
83
|
const inputVars = getInputVars(inputSpecs)
|
|
141
84
|
const outputVars = getOutputVars(outputSpecs)
|
|
142
85
|
|
|
86
|
+
// Gather information about internal/implementation variables
|
|
87
|
+
const { implVars, implVarGroups } = getImplVars(encodedImplVars)
|
|
88
|
+
|
|
143
89
|
const modelSpec: ModelSpec = {
|
|
144
90
|
modelSizeInBytes,
|
|
145
91
|
dataSizeInBytes,
|
|
146
92
|
inputVars,
|
|
147
93
|
outputVars,
|
|
148
|
-
implVars
|
|
94
|
+
implVars,
|
|
95
|
+
implVarGroups
|
|
149
96
|
// TODO: startTime and endTime are optional; the comparison graphs work OK if
|
|
150
97
|
// they are undefined. The main benefit of using these is to set a specific
|
|
151
98
|
// range for the x-axis on the comparison graphs, so maybe we should find
|
|
@@ -6,10 +6,14 @@
|
|
|
6
6
|
* up using aliases in the Vite config file.)
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
+
import type { EncodedImplVars } from '@sdeverywhere/check-core'
|
|
10
|
+
|
|
9
11
|
import type { InputSpec } from './inputs'
|
|
10
12
|
import type { OutputSpec } from './outputs'
|
|
11
13
|
|
|
12
14
|
export const inputSpecs: InputSpec[] = []
|
|
13
15
|
export const outputSpecs: OutputSpec[] = []
|
|
16
|
+
export const encodedImplVars: EncodedImplVars = undefined
|
|
17
|
+
|
|
14
18
|
export const modelSizeInBytes = 0
|
|
15
19
|
export const dataSizeInBytes = 0
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
// Copyright (c) 2022 Climate Interactive / New Venture Fund
|
|
2
|
+
|
|
3
|
+
import type { DatasetKey, EncodedImplVars, ImplVar, ImplVarGroup } from '@sdeverywhere/check-core'
|
|
4
|
+
import { decodeImplVars } from '@sdeverywhere/check-core'
|
|
5
|
+
|
|
6
|
+
/** The properties related to impl variables that will be included in the bundle model spec. */
|
|
7
|
+
export interface ImplSpec {
|
|
8
|
+
/** The map of all variables (both internal and exported) in this version of the model. */
|
|
9
|
+
implVars: Map<DatasetKey, ImplVar>
|
|
10
|
+
/** The groupings of internal/implementation variables in this version of the model. */
|
|
11
|
+
implVarGroups?: ImplVarGroup[]
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Gather the set of internal/implementation variables used in this version of the model.
|
|
16
|
+
*/
|
|
17
|
+
export function getImplVars(encodedImplVars: EncodedImplVars): ImplSpec {
|
|
18
|
+
// Decode the encoded impl variables into the original `ImplVar` objects
|
|
19
|
+
const decodedImplVars = decodeImplVars(encodedImplVars)
|
|
20
|
+
|
|
21
|
+
const implVars: Map<DatasetKey, ImplVar> = new Map()
|
|
22
|
+
const implVarGroups: ImplVarGroup[] = []
|
|
23
|
+
|
|
24
|
+
function addGroup(fn: string, implVarInstances: ImplVar[]): void {
|
|
25
|
+
// Add the var instances for this group to the map
|
|
26
|
+
const datasetKeysForGroup: DatasetKey[] = []
|
|
27
|
+
for (const implVarInstance of implVarInstances) {
|
|
28
|
+
// TODO: For now, skip lookup and data variables because we have no way to
|
|
29
|
+
// access them in the model
|
|
30
|
+
if (implVarInstance.varType === 'lookup' || implVarInstance.varType === 'data') {
|
|
31
|
+
continue
|
|
32
|
+
}
|
|
33
|
+
const varId = implVarInstance.varId
|
|
34
|
+
const datasetKey = `ModelImpl_${varId}`
|
|
35
|
+
implVars.set(datasetKey, implVarInstance)
|
|
36
|
+
datasetKeysForGroup.push(datasetKey)
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// Add the group info
|
|
40
|
+
implVarGroups.push({
|
|
41
|
+
title: fn,
|
|
42
|
+
fn,
|
|
43
|
+
datasetKeys: datasetKeysForGroup
|
|
44
|
+
})
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
addGroup('initConstants', decodedImplVars.constants || [])
|
|
48
|
+
// TODO: Include lookups and data variables
|
|
49
|
+
// addGroup('initLookups', decodedImplVars.lookupVars || [])
|
|
50
|
+
// addGroup('initData', decodedImplVars.dataVars || [])
|
|
51
|
+
addGroup('initLevels', decodedImplVars.initVars || [])
|
|
52
|
+
addGroup('evalLevels', decodedImplVars.levelVars || [])
|
|
53
|
+
addGroup('evalAux', decodedImplVars.auxVars || [])
|
|
54
|
+
|
|
55
|
+
return {
|
|
56
|
+
implVars,
|
|
57
|
+
implVarGroups
|
|
58
|
+
}
|
|
59
|
+
}
|
|
@@ -23,6 +23,28 @@
|
|
|
23
23
|
}
|
|
24
24
|
</style>
|
|
25
25
|
|
|
26
|
+
<!--
|
|
27
|
+
XXX: Include no-op polyfills for these modules that are used in the Node-specific
|
|
28
|
+
implementation of threads.js. This allows us to use one model-check bundle that
|
|
29
|
+
works in both Node and browser environments. Without this importmap, loading a
|
|
30
|
+
remote bundle would fail with the following error when trying to import Node
|
|
31
|
+
modules like `worker_threads` that aren't available in the browser:
|
|
32
|
+
TypeError: The specifier “worker_threads” was a bare specifier, but was not
|
|
33
|
+
remapped to anything.
|
|
34
|
+
-->
|
|
35
|
+
<script type="importmap">
|
|
36
|
+
{
|
|
37
|
+
"imports": {
|
|
38
|
+
"events": "./polyfills/noop-polyfills.js",
|
|
39
|
+
"fs": "./polyfills/noop-polyfills.js",
|
|
40
|
+
"os": "./polyfills/noop-polyfills.js",
|
|
41
|
+
"path": "./polyfills/noop-polyfills.js",
|
|
42
|
+
"url": "./polyfills/noop-polyfills.js",
|
|
43
|
+
"worker_threads": "./polyfills/noop-polyfills.js"
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
</script>
|
|
47
|
+
|
|
26
48
|
<script type="module" src="./src/index.ts"></script>
|
|
27
49
|
</head>
|
|
28
50
|
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
This file is not used but must remain present to ensure that the `template-report/src/
|
|
1
|
+
This file is not used but must remain present to ensure that the `template-report/src/bundles`
|
|
2
2
|
directory exists. See `vite-config-for-report.ts` for details.
|
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
// These values are injected by Vite at build time, so we need to
|
|
4
4
|
// declare types for them here
|
|
5
|
+
declare const __SUITE_SUMMARY_JSON__: string
|
|
5
6
|
declare const __BASELINE_NAME__: string
|
|
6
7
|
declare const __CURRENT_NAME__: string
|
|
7
|
-
declare const
|
|
8
|
+
declare const __CURRENT_BUNDLE_LAST_MODIFIED__: string
|
|
9
|
+
declare const __REMOTE_BUNDLES_URL__: string
|