-
-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathbuild.js
executable file
·142 lines (122 loc) · 4.35 KB
/
build.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
#!/usr/bin/env node
import { execSync } from 'node:child_process'
import { mkdir, readFile, rm, writeFile } from 'node:fs/promises'
import { basename } from 'node:path'
import { isDeepStrictEqual } from 'node:util'
import braces from 'braces'
import semver from 'semver'
/**
* @typedef JSONValidation
* @property {string | string[]} fileMatch
* The file pattern (or an array of patterns) to match, for example "package.json" or "*.launch".
* Exclusion patterns start with '!'
* @property {string} url
* A schema URL ('http:', 'https:') or relative path to the extension folder ('./').
*/
const response = await fetch('https://www.schemastore.org/api/json/catalog.json')
if (!response.ok) {
throw new Error(await response.text())
}
/** @type {import('@schemastore/schema-catalog').JSONSchemaForSchemaStoreOrgCatalogFiles} */
const catalog = await response.json()
const excludePattern = /.\.(cff|cjs|js|mjs|toml|yaml|yml)$/
/** @type {JSONValidation[]} */
const jsonValidation = []
const schemasDir = new URL('schemas/', import.meta.url)
await rm(schemasDir, { force: true, recursive: true })
await mkdir(schemasDir)
/** @type {Map<string, Set<string>>} */
const schemasByMatch = new Map()
// Collect a map where each match is mapped to a corresponding URL.
// Some matches may match multiple schemas.
for (const { fileMatch, url, versions } of catalog.schemas) {
if (!fileMatch) {
continue
}
for (let match of fileMatch) {
// For VS Code schema matching, `**/rest/of/glob` is equivalent to `rest/of/glob`.
match = match.replace(/^\*\*?\//, '')
for (const m of braces(match, { expand: true })) {
if (excludePattern.test(m)) {
continue
}
const set = schemasByMatch.get(m) || new Set()
schemasByMatch.set(m, set)
if (url) {
set.add(url)
}
if (versions) {
for (const versionUrl of Object.values(versions)) {
set.add(versionUrl)
}
}
}
}
}
/** @type {Map<Set<string>, Set<string>>} */
const schemasByUrls = new Map()
// Group all URLs together that share the same match.
collectSchemas: for (const [match, urls] of schemasByMatch) {
for (const [possibleDuplicate, allMatches] of schemasByUrls) {
if (isDeepStrictEqual(urls, possibleDuplicate)) {
allMatches.add(match)
continue collectSchemas
}
}
schemasByUrls.set(urls, new Set([match]))
}
// Generate the actual JSON schema validation array used by the extension.
for (const [urls, matches] of schemasByUrls) {
let [url] = urls
// If there is only one matching URL, point there directly.
// Otherwise, generate a schema that references all matching schemas using `anyOf` and `$ref`.
if (urls.size > 1) {
const [match] = matches
const name = match
.replaceAll(/\b(json|schema)\b/g, '')
.replaceAll('*', '')
.replaceAll(/[\W_]+/g, '-')
.replaceAll(/(^-|-$)/g, '')
url = `./schemas/${name}.schema.json`
await writeFile(
url,
`${JSON.stringify({ anyOf: [...urls].sort().map((ref) => ({ $ref: ref })) }, undefined, 2)}\n`
)
}
/** @type {string[]} */
const fileMatch = []
for (const match of matches) {
const base = basename(match)
// If the match is the same as the base name, it’s always ok.
if (base === match) {
fileMatch.push(match)
}
// VS Code will detect it already if the base name is matched.
// There’s no need to include a specific glob additionally.
if (!matches.has(base)) {
fileMatch.push(match)
}
}
jsonValidation.push({
url,
fileMatch: fileMatch.length === 1 ? fileMatch[0] : fileMatch.sort()
})
}
jsonValidation.sort((a, b) => a.url.localeCompare(b.url))
const path = new URL('package.json', import.meta.url)
const pkg = JSON.parse(await readFile(path, 'utf8'))
if (isDeepStrictEqual(pkg.contributes.jsonValidation, jsonValidation)) {
console.log('No changes were found in the JSON Schema Store catalog')
} else {
pkg.version = semver.inc(pkg.version, 'patch')
pkg.contributes.jsonValidation = jsonValidation
await writeFile(path, `${JSON.stringify(pkg, undefined, 2)}\n`)
console.log('Updated package.json')
if (process.argv.includes('--commit')) {
execSync('git add .')
execSync(`git commit --message v${pkg.version}`)
execSync(`git tag --no-sign v${pkg.version}`)
execSync('git push origin HEAD --tags')
console.log('Committed and pushed changes')
}
}