|
1 |
| -/** |
| 1 | +/* |
2 | 2 | * Copyright (C) NIWA & British Crown (Met Office) & Contributors.
|
3 | 3 | *
|
4 | 4 | * This program is free software: you can redistribute it and/or modify
|
@@ -123,6 +123,8 @@ const RELATIVE_ID = new RegExp(`
|
123 | 123 |
|
124 | 124 | /* eslint-enable */
|
125 | 125 |
|
| 126 | +const JOB_ID = /^(\d+|NN)$/ |
| 127 | + |
126 | 128 | function detokenise (tokens, workflow = true, relative = true) {
|
127 | 129 | let parts = []
|
128 | 130 | let ret = ''
|
@@ -159,7 +161,7 @@ function detokenise (tokens, workflow = true, relative = true) {
|
159 | 161 | return ret
|
160 | 162 | }
|
161 | 163 |
|
162 |
| -class Tokens { |
| 164 | +export class Tokens { |
163 | 165 | /* Represents a Cylc UID.
|
164 | 166 | *
|
165 | 167 | * Provides the interfaces for parsing to and from string IDs.
|
@@ -262,19 +264,29 @@ class Tokens {
|
262 | 264 | this.job = undefined
|
263 | 265 | }
|
264 | 266 |
|
| 267 | + if (this.job && !JOB_ID.test(this.job)) { |
| 268 | + throw new Error(`Invalid job ID: ${this.job}`) |
| 269 | + } |
| 270 | + |
265 | 271 | this.workflowID = detokenise(this, true, false)
|
266 | 272 | this.relativeID = detokenise(this, false, true)
|
267 | 273 | }
|
268 | 274 |
|
269 | 275 | set (fields) {
|
270 |
| - for (const [key, value] of Object.entries(fields)) { |
271 |
| - if (Tokens.KEYS.indexOf(key) === -1) { |
272 |
| - throw new Error(`Invalid key: ${key}`) |
| 276 | + if (fields instanceof Tokens) { |
| 277 | + for (const key of Tokens.KEYS) { |
| 278 | + if (fields[key]) this[key] = fields[key] |
273 | 279 | }
|
274 |
| - if (typeof value !== 'string' && typeof value !== 'undefined') { |
275 |
| - throw new Error(`Invalid type for value: ${value}`) |
| 280 | + } else { |
| 281 | + for (const [key, value] of Object.entries(fields)) { |
| 282 | + if (!Tokens.KEYS.includes(key)) { |
| 283 | + throw new Error(`Invalid key: ${key}`) |
| 284 | + } |
| 285 | + if (typeof value !== 'string' && value != null) { |
| 286 | + throw new Error(`Invalid type for value: ${value}`) |
| 287 | + } |
| 288 | + this[key] = value ?? undefined |
276 | 289 | }
|
277 |
| - this[key] = value |
278 | 290 | }
|
279 | 291 | this.compute()
|
280 | 292 | }
|
@@ -360,6 +372,19 @@ class Tokens {
|
360 | 372 | }
|
361 | 373 | return ret
|
362 | 374 | }
|
363 |
| -} |
364 | 375 |
|
365 |
| -export { Tokens } |
| 376 | + /** |
| 377 | + * Validate an ID string without throwing an error. |
| 378 | + * |
| 379 | + * @param {string} id |
| 380 | + * @returns {string=} Error message if invalid, otherwise nothing. |
| 381 | + */ |
| 382 | + static validate (id, relative = false) { |
| 383 | + try { |
| 384 | + // eslint-disable-next-line no-new |
| 385 | + new Tokens(id, relative) |
| 386 | + } catch (e) { |
| 387 | + return e.message |
| 388 | + } |
| 389 | + } |
| 390 | +} |
0 commit comments