Skip to content

Commit d6230a9

Browse files
committed
Specification
1 parent 735e9c5 commit d6230a9

File tree

553 files changed

+42790
-17356
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

553 files changed

+42790
-17356
lines changed

deno.jsonc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
"publish": "deno run -A tasks.ts publish", // Publish Package
1212
"report": "deno run -A tasks.ts report", // Test Converage
1313
"range": "deno run -A tasks.ts range", // TypeScript Compiler Ranges
14+
"spec": "deno run -A tasks.ts spec", // Refresh JSON Schema Spec
1415
"start": "deno run -A tasks.ts start", // Run Example
1516
"syntax": "deno run -A tasks.ts syntax", // Build Parsers
1617
"test": "deno run -A tasks.ts test", // Test Project

design/website/docs/type/overview.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ JSON Schema Type Builder with Static Type Resolution for TypeScript
44

55
## Overview
66

7-
TypeBox types are JSON Schema fragments that can compose into more complex types. The library offers a set of types used to construct JSON Schema compliant schematics as well as a set of extended types used to model constructs native to the JavaScript language. The schematics produced by TypeBox can be passed directly to any JSON Schema compliant validator.
7+
TypeBox types are JSON Schema fragments that compose into more complex types. The library offers a set of types used to construct JSON Schema compliant schematics as well as a set of extended types used to model constructs native to the JavaScript language. The schematics produced by TypeBox can be passed directly to any JSON Schema compliant validator.
88

99
## Example
1010

docs/docs/type/overview.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<h1>Type</h1>
22
<p>JSON Schema Type Builder with Static Type Resolution for TypeScript</p>
33
<h2>Overview</h2>
4-
<p>TypeBox types are JSON Schema fragments that can compose into more complex types. The library offers a set of types used to construct JSON Schema compliant schematics as well as a set of extended types used to model constructs native to the JavaScript language. The schematics produced by TypeBox can be passed directly to any JSON Schema compliant validator.</p>
4+
<p>TypeBox types are JSON Schema fragments that compose into more complex types. The library offers a set of types used to construct JSON Schema compliant schematics as well as a set of extended types used to model constructs native to the JavaScript language. The schematics produced by TypeBox can be passed directly to any JSON Schema compliant validator.</p>
55
<h2>Example</h2>
66
<p>The following creates a User type and infers with Static.</p>
77
<pre><code class="language-typescript">import Type from &#39;typebox&#39;

readme.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ License: MIT
7070
7171
[Documentation](https://sinclairzx81.github.io/typebox/#/docs/type/overview) | [Example](https://www.typescriptlang.org/play/?#code/JYWwDg9gTgLgBAFQJ5gKZwGZQiOByGFVAIwgA88AoSgehrgFonmXW32POvueHb7kafo16ix4ic2oBjCADsAzvACqC1FDgBeREQB0AeWIArVNJgAKAN5wbtu-Yc26cWYpVqN2y5RvAAJgBcOmi6AMowUMByAObmAJQANI7JKfbONoRoQXgQxqYweAk+cHIAhiCoQYKoYRFRsYmpTQ7pcGDYaLDAqApB3jaoIKXAADZVeuGRMVaY0EMw2YPDI3hwAL5xya2+gXDWmZX4SlPRq2tFG81X11v0dmUVfXAH2cf1Z0U3X99w23BLoyexR+INSfwyRFedRihTgwNBCLSd3sGDmpQW+ABKzhiNxdj+a3heIRrUJxLxrSgqAAjgBXYBU3YAbSJ5J+fzw-lhrLZXw5D1Q3N5JORNjwWKowtBrQAujypc1nIThJJVWr1XxnOF0cBpCqNQbDZxqAc4Kp1FpgjVtTBdQAeA4QDBmjwAPmuzlN5s8e3lCqarX8QTeMU+-u+rQFweh0TD4ZurSx0ZOfvjjiVQA)
7272
73-
TypeBox types are JSON Schema fragments that can compose into more complex types. The library offers a set of types used to construct JSON Schema compliant schematics as well as a set of extended types used to model constructs native to the JavaScript language. The schematics produced by TypeBox can be passed directly to any JSON Schema compliant validator.
73+
TypeBox types are JSON Schema fragments that compose into more complex types. The library offers a set of types used to construct JSON Schema compliant schematics as well as a set of extended types used to model constructs native to the JavaScript language. The schematics produced by TypeBox can be passed directly to any JSON Schema compliant validator.
7474
7575
## Example
7676
@@ -196,9 +196,9 @@ type UserUpdate = Type.Static<typeof UserUpdate> // type UserUpdate = {
196196

197197
## Schema
198198

199-
[Documentation](https://sinclairzx81.github.io/typebox/#/docs/schema/overview) | [Example 1](https://www.typescriptlang.org/play/?#code/JYWwDg9gTgLgBAZQMYAsCmICGcBmUIhwDkMAnmGgEYQAeA9AM6oaZEBQokscAKuWrnyES-ajXZs6dOAFo58hYqXKVqteo0zJ0gMIEwwADZptszeYuWr8tmyQQAdg3gBVBmihwAvImZYAdHrgRmgAFHwU-gDylABWaEgwoQDebHBwwAAmAFy8-P4IMFDADgDmoQCUADRpcA6YIGi5EWgFRSXl1bUsRs35hcVlKbjQWDC5RD2GRHAAvhVs8wum1qtr61pScAAKmFDuKxtHx6q29k7wAK7unj5uHv67+2HJ6W-vH5-vW+fOcNceXKpdJZCYANgArDgAIyYABMlAAzEgACyZCFoME4ADsmAAHJQAJxIAAMmWhRCqX2pcC2IJycGcg1KNXS9UaEwBUEpNN5fO+0jZDSajPaZVZcCmnJuAAFMgRMCV-PYQDN+by6ZKsL1RczFhV1YajR8trNvHB-JagA) | [Example 2](https://www.typescriptlang.org/play/?#code/JYWwDg9gTgLgBAZQMYAsCmICGcBmUIhwDkMAnmGgEYQAeA9AM6oaZEBQbddcAtH-wMFDhI0WPESenbgGECYYABs003pPUbNW-hyQQAdg3gBVBmihwAvImZYAdHPBK0ACgDebOHDIUAXMQhKACs0JBgiABpPODB8ClhgNAZ-Dy8vYAATFO9yNH8iIyhgfQBzIjgAXyi0uH1MEDy4Nxy-YkLissrqtJYlbJ9Ggpgi0vKK6KroqDQARwBXYGmsuABtaK8iTMi4deI6hu3dol7Fdi8AXTYKgEoOLjVtR6en1QAFTCgzVWef38ldAxGOBzMwWaymcx2d6fVzNGrwhGIuD3PSGeAg8wpaKZfIANgArDgAIyYABMlAAzEgACwZfFoXE4ADsmAAHJQAJxIAAMGSJ2yRiPu6WW7VK3X2gwxUAFgrl8q8wtq9UaYpK3RO+WlAAEMgRMMU7HoQOUFXKlZq4GqrtczXb7fD7hUrHA7G6gA)
199+
[Documentation](https://sinclairzx81.github.io/typebox/#/docs/schema/overview) | [Example 1](https://www.typescriptlang.org/play/?#code/JYWwDg9gTgLgBAZQMYAsCmICGcBmUIhwDkMAnmGgEYQAeA9AM6oaZEBQokscAKuWrnyES-ajXZs6dOAFo58hYqXKVqteo0zJ0gMIEwwADZptszeYuWr8tmyQQAdg3gBVBmihwAvImZYAdHrgRmgAFHwU-gDylABWaEgwoQDebHBwwAAmAFy8-P4IMFDADgDmoQCUADRpcA6YIGi5EWgFRSXl1bUsRs35hcVlKbjQWDC5RD2GRHAAvhVs8wum1qtr61pScAAKmFDuKxtHx6q29k7wAK7unj5uHv67+2HJ6W-vH5-vW+fOcNceXKpdJZCYANgArDgAIyYABMlAAzEgACyZCFoME4ADsmAAHJQAJxIAAMmWhRCqX2pcC2IJycGcg1KNXS9UaEwBUEpNN5fO+0jZDSajPaZVZcCmnJuAAFMgRMCV-PYQDN+by6ZKsL1RczFhV1YajR8trNvHB-JagA) | [Example 2](https://www.typescriptlang.org/play/#code/JYWwDg9gTgLgBAZQMYAsCmICGcBmUIhwDkMAnmGgEYQAeA9AM6oaZEBQbddcAtH-wMFDhI0WPESenbgGECYYABs003pPUbNW-hyQQAdg3gBVBmihwAvImZYAdHPBK0ACgDebOHDIUAXMQhKACs0JBgiABpPODB8ClhgNAZ-Dy8vYAATFO9yNH8iIyhgfQBzIjgAXyi0uH1MEDy4Nxy-YkLissrqtJYlbJ9Ggpgi0sjcaCwYfN7FcoroquioNABHAFdgZay4AG1oryJMsf3iOobjmqIZ9i8AXTYKgEoOLjVtd4+P1QAFTCgzVSfIHAyS6AxGOBrMwWaymcx2X7-VzNGqotHouCvPSGeBQ8wpaKZfIANgArDgAIyYABMlAAzEgACwZUloYk4ADsmAAHJQAJxIAAMGQpYwx6Ne6W27VK3TOgzxUDF4pVqq8ktq9UaMpK3Rm+UVAAEMgRMMU7HoQOU1SqNfq4DqHo8bS7XajXhUrHA7D6gA)
200200

201-
TypeBox includes a high performance validation compiler for JSON Schema. The compiler supports both TypeBox and native JSON Schema schematics, and will convert them into optimized runtime validation routines. The compiler is designed to be a lightweight 2020-12 spec compliant alternative to Ajv for high-throughput applications.
201+
TypeBox includes a JSON Schema validation compiler. The compiler is designed for high performance JIT, but also implements automatic dynamic fallback to interpretted checking in edge environments such as Cloudflare. The compiler is designed to be a lightweight alternative to Ajv for high-throughput applications.
202202

203203
### Example
204204

task/spec/index.ts

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
/*--------------------------------------------------------------------------
2+
3+
TypeBox
4+
5+
The MIT License (MIT)
6+
7+
Copyright (c) 2017-2026 Haydn Paterson
8+
9+
Permission is hereby granted, free of charge, to any person obtaining a copy
10+
of this software and associated documentation files (the "Software"), to deal
11+
in the Software without restriction, including without limitation the rights
12+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13+
copies of the Software, and to permit persons to whom the Software is
14+
furnished to do so, subject to the following conditions:
15+
16+
The above copyright notice and this permission notice shall be included in
17+
all copies or substantial portions of the Software.
18+
19+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25+
THE SOFTWARE.
26+
27+
---------------------------------------------------------------------------*/
28+
29+
export * as Spec from './refresh.ts'

task/spec/process.ts

Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
/*--------------------------------------------------------------------------
2+
3+
TypeBox
4+
5+
The MIT License (MIT)
6+
7+
Copyright (c) 2017-2026 Haydn Paterson
8+
9+
Permission is hereby granted, free of charge, to any person obtaining a copy
10+
of this software and associated documentation files (the "Software"), to deal
11+
in the Software without restriction, including without limitation the rights
12+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13+
copies of the Software, and to permit persons to whom the Software is
14+
furnished to do so, subject to the following conditions:
15+
16+
The above copyright notice and this permission notice shall be included in
17+
all copies or substantial portions of the Software.
18+
19+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25+
THE SOFTWARE.
26+
27+
---------------------------------------------------------------------------*/
28+
29+
import type { JSONSchemaTestFile, JSONSchemaTestGroup, JSONSchemaTestSuite } from './types.ts'
30+
31+
export type ProcessCallback = (draft: string, schema: Record<string, unknown> | boolean, value: unknown) => boolean | null
32+
33+
// ------------------------------------------------------------------
34+
// JSONTestSource: A loaded test file before segmentation
35+
// ------------------------------------------------------------------
36+
interface JSONTestSource {
37+
sourcePath: string
38+
draft: string
39+
keyword: string
40+
groups: JSONSchemaTestGroup[]
41+
}
42+
43+
// ------------------------------------------------------------------
44+
// CollectJsonPaths: Load all test files from disk into memory
45+
// ------------------------------------------------------------------
46+
function collectJsonPaths(directory: string): string[] {
47+
const results: string[] = []
48+
for (const entry of Deno.readDirSync(directory)) {
49+
const full = `${directory}/${entry.name}`
50+
if (entry.isDirectory) results.push(...collectJsonPaths(full))
51+
else if (entry.isFile && entry.name.endsWith('.json')) results.push(full)
52+
}
53+
return results
54+
}
55+
56+
function resolveDraftAndKeyword(sourcePath: string, rootDirectory: string): { draft: string; keyword: string } | null {
57+
const root = rootDirectory.replace(/\\/g, '/').replace(/\/$/, '')
58+
const normalized = sourcePath.replace(/\\/g, '/')
59+
if (!normalized.startsWith(root + '/')) return null
60+
const relative = normalized.slice(root.length + 1)
61+
const slashIndex = relative.indexOf('/')
62+
if (slashIndex === -1) return null
63+
const draft = relative.slice(0, slashIndex)
64+
const keyword = relative.slice(slashIndex + 1).replace(/\.json$/, '')
65+
return { draft, keyword }
66+
}
67+
68+
function collectJSONTests(directory: string): JSONTestSource[] {
69+
const results: JSONTestSource[] = []
70+
for (const sourcePath of collectJsonPaths(directory)) {
71+
const resolved = resolveDraftAndKeyword(sourcePath, directory)
72+
if (resolved === null) continue
73+
const { draft, keyword } = resolved
74+
const groups = JSON.parse(Deno.readTextFileSync(sourcePath)) as JSONSchemaTestGroup[]
75+
results.push({ sourcePath, draft, keyword, groups })
76+
}
77+
return results
78+
}
79+
80+
// ------------------------------------------------------------------
81+
// RunTest
82+
// ------------------------------------------------------------------
83+
function runTest(callback: ProcessCallback, draft: string, schema: Record<string, unknown> | boolean, data: unknown): boolean | null {
84+
try {
85+
return callback(draft, schema, data)
86+
} catch {
87+
return null
88+
}
89+
}
90+
91+
function createAccumulator(input: JSONSchemaTestGroup[]): JSONSchemaTestGroup[] {
92+
return input.map((group) => ({ ...group, tests: [] }))
93+
}
94+
95+
function resolveFailingPath(relativePath: string): string {
96+
return relativePath.replace(/\\/g, '/').split('/').map((s, i, a) => i === a.length - 1 ? '_' + s : s).join('/')
97+
}
98+
99+
// ------------------------------------------------------------------
100+
// AssertCounts
101+
// ------------------------------------------------------------------
102+
function assertCounts(sources: JSONTestSource[], suite: JSONSchemaTestSuite): void {
103+
const sourceTotal = sources.reduce((n, s) => n + s.groups.reduce((m, g) => m + g.tests.length, 0), 0)
104+
const segmentedTotal = Object.values(suite.report).reduce((n, s) => n + s.total, 0)
105+
const passed = Object.values(suite.report).reduce((n, s) => n + s.passed, 0)
106+
const failed = Object.values(suite.report).reduce((n, s) => n + s.failed, 0)
107+
console.log(`spec: loaded ${sourceTotal}, passed ${passed}, failed ${failed}, total ${segmentedTotal}`)
108+
if (sourceTotal !== segmentedTotal) {
109+
throw new Error(`Test count mismatch: loaded ${sourceTotal} tests from disk but segmented ${segmentedTotal}`)
110+
}
111+
}
112+
113+
// ------------------------------------------------------------------
114+
// Process: Run all tests and split into passing/failing files
115+
// ------------------------------------------------------------------
116+
export function process(directory: string, callback: ProcessCallback = () => true): JSONSchemaTestSuite {
117+
const sources = collectJSONTests(directory)
118+
const files: JSONSchemaTestFile[] = []
119+
const report: JSONSchemaTestSuite['report'] = {}
120+
const root = directory.replace(/\\/g, '/').replace(/\/$/, '')
121+
for (const { sourcePath, draft, keyword, groups } of sources) {
122+
const passed = createAccumulator(groups)
123+
const failed = createAccumulator(groups)
124+
for (let i = 0; i < groups.length; i++) {
125+
const schema = groups[i].schema
126+
for (const test of groups[i].tests) {
127+
const actual = runTest(callback, draft, schema, test.data)
128+
if (actual !== null && test.valid === actual) {
129+
passed[i].tests.push(test)
130+
} else {
131+
failed[i].tests.push(test)
132+
}
133+
}
134+
}
135+
const passedGroups = passed.filter((group) => group.tests.length > 0)
136+
const failedGroups = failed.filter((group) => group.tests.length > 0)
137+
const passedCount = passedGroups.reduce((n, g) => n + g.tests.length, 0)
138+
const failedCount = failedGroups.reduce((n, g) => n + g.tests.length, 0)
139+
const relativePath = sourcePath.replace(/\\/g, '/').slice(root.length + 1)
140+
if (passedGroups.length > 0) {
141+
files.push({ path: relativePath, draft, keyword, failing: false, groups: passedGroups })
142+
}
143+
if (failedGroups.length > 0) {
144+
files.push({ path: resolveFailingPath(relativePath), draft, keyword, failing: true, groups: failedGroups })
145+
}
146+
147+
report[`${draft}/${keyword}`] = {
148+
passed: passedCount,
149+
failed: failedCount,
150+
total: passedCount + failedCount
151+
}
152+
}
153+
files.sort((a, b) => a.path.localeCompare(b.path))
154+
const suite = { files, report }
155+
assertCounts(sources, suite)
156+
return suite
157+
}

task/spec/refresh.ts

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
/*--------------------------------------------------------------------------
2+
3+
TypeBox
4+
5+
The MIT License (MIT)
6+
7+
Copyright (c) 2017-2026 Haydn Paterson
8+
9+
Permission is hereby granted, free of charge, to any person obtaining a copy
10+
of this software and associated documentation files (the "Software"), to deal
11+
in the Software without restriction, including without limitation the rights
12+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13+
copies of the Software, and to permit persons to whom the Software is
14+
furnished to do so, subject to the following conditions:
15+
16+
The above copyright notice and this permission notice shall be included in
17+
all copies or substantial portions of the Software.
18+
19+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25+
THE SOFTWARE.
26+
27+
---------------------------------------------------------------------------*/
28+
29+
// deno-fmt-ignore-file
30+
31+
import { Task } from 'tasksmith'
32+
import * as Schema from 'typebox/schema'
33+
import * as Process from './process.ts'
34+
import * as Report from './report.ts'
35+
import type { JSONSchemaTestSuite } from './types.ts'
36+
import { Folder } from 'https://raw.githubusercontent.com/sinclairzx81/tasksmith/0.9.9/src/build/dual/folder.ts'
37+
38+
// ------------------------------------------------------------------
39+
// Clone
40+
// ------------------------------------------------------------------
41+
const CLONE_DIRECTORY = 'spec-clone-directory'
42+
43+
// ------------------------------------------------------------------
44+
// Clone
45+
// ------------------------------------------------------------------
46+
async function clone() {
47+
await Task.folder(CLONE_DIRECTORY).delete()
48+
await Task.folder(CLONE_DIRECTORY).create()
49+
await Task.shell(`cd ${CLONE_DIRECTORY} && git clone [email protected]:json-schema-org/JSON-Schema-Test-Suite.git`)
50+
}
51+
// ------------------------------------------------------------------
52+
// Process
53+
// ------------------------------------------------------------------
54+
function process(): JSONSchemaTestSuite {
55+
return Process.process(`${CLONE_DIRECTORY}/JSON-Schema-Test-Suite/tests`, (_draft, schema, value) => {
56+
const build = Schema.Compile(schema).Check(value)
57+
const check = Schema.Check(schema, value)
58+
const error = Schema.Errors(schema, value)[0]
59+
const consistent = (check === build) && (check === error)
60+
if(!consistent) return null
61+
return check
62+
})
63+
}
64+
// ------------------------------------------------------------------
65+
// Report
66+
// ------------------------------------------------------------------
67+
function report(suite: JSONSchemaTestSuite): void {
68+
const requiredTable = Report.reportRequired(suite, {
69+
ignore: ['defs', 'definitions', 'divisibleBy', 'disallow', 'dynamicRef', 'extends', 'refRemote', 'vocabulary']
70+
})
71+
const optionalTable = Report.reportOptional(suite, {
72+
ignore: []
73+
})
74+
console.log('--------------------------------------------------------')
75+
console.log('OPTIONAL')
76+
console.log('--------------------------------------------------------')
77+
console.log()
78+
console.log(optionalTable)
79+
console.log('--------------------------------------------------------')
80+
console.log('REQUIRED')
81+
console.log('--------------------------------------------------------')
82+
console.log()
83+
console.log(requiredTable)
84+
}
85+
// ------------------------------------------------------------------
86+
// Write
87+
// ------------------------------------------------------------------
88+
async function write(directory: string, suite: JSONSchemaTestSuite): Promise<void> {
89+
await Task.folder(directory).delete()
90+
for(const file of suite.files) {
91+
const path = `${directory}/${file.path}`
92+
const content = JSON.stringify(file.groups, null, 2)
93+
await Task.file(path).write(content)
94+
}
95+
}
96+
async function cleanup(): Promise<void> {
97+
await Task.folder(CLONE_DIRECTORY).delete()
98+
}
99+
// ------------------------------------------------------------------
100+
// Refresh
101+
// ------------------------------------------------------------------
102+
/** Refresh the test suite with the latest cases */
103+
export async function refresh(directory: string): Promise<void> {
104+
await clone()
105+
const suite = process()
106+
await report(suite)
107+
await write(directory, suite)
108+
await cleanup()
109+
}
110+
111+
112+
113+
114+

0 commit comments

Comments
 (0)