(actionScript)
| 152 | } |
| 153 | |
| 154 | validateActionScript(actionScript) { |
| 155 | if ( |
| 156 | !( |
| 157 | TYPE_CHECKERS.object(actionScript) && |
| 158 | "name" in actionScript && |
| 159 | TYPE_CHECKERS.string(actionScript.name) |
| 160 | ) |
| 161 | ) { |
| 162 | throw new Error( |
| 163 | "All action scripts must be non-array objects with a name" |
| 164 | ); |
| 165 | } |
| 166 | |
| 167 | const name = actionScript.name; |
| 168 | |
| 169 | for (let [field, type] of Object.entries( |
| 170 | TOP_LEVEL_FIELDS_AND_TYPES |
| 171 | )) { |
| 172 | if (!(field in actionScript)) { |
| 173 | throw new Error( |
| 174 | `Action script "${name}" must contain a "${field}" field` |
| 175 | ); |
| 176 | } |
| 177 | if (!TYPE_CHECKERS[type](actionScript[field])) { |
| 178 | // TODO: allow for chainId to match a declared variable with the |
| 179 | // correct type |
| 180 | throw new Error( |
| 181 | `Action script "${name}" field "${field}" must be of type "${type}"` |
| 182 | ); |
| 183 | } |
| 184 | } |
| 185 | |
| 186 | const validFields = new Set( |
| 187 | Object.keys(TOP_LEVEL_FIELDS_AND_TYPES) |
| 188 | ); |
| 189 | for (let field of Object.keys(actionScript)) { |
| 190 | if (!validFields.has(field)) { |
| 191 | throw new Error( |
| 192 | `Action script "${name}" contains invalid field "${field}"` |
| 193 | ); |
| 194 | } |
| 195 | } |
| 196 | |
| 197 | Validator.validateVariablesAndResults(actionScript); |
| 198 | this.validateDefinitions(actionScript); |
| 199 | const isAdvanced = Validator.validateActions(actionScript); |
| 200 | Validator.validateInputs(actionScript); |
| 201 | Validator.validateOutputs(actionScript); |
| 202 | Validator.validateAssociations(actionScript); |
| 203 | // TODO: validate operations / results |
| 204 | // TODO: validate description strings |
| 205 | |
| 206 | return isAdvanced; |
| 207 | } |
| 208 | |
| 209 | static validateVariablesAndResults(actionScript) { |
| 210 | const { name, variables, results } = actionScript; |
no test coverage detected