Team Ai
Datasetpublic

codekingpro/portable-devtools

sourceHugging Faceupdated 5mo agoView on Hugging Face
1likes14kdownloads
dev-engines.js146 linesDownload Raw Back to lib
1const satisfies = require('semver/functions/satisfies')
2const validRange = require('semver/ranges/valid')
3
4const recognizedOnFail = [
5  'ignore',
6  'warn',
7  'error',
8  'download',
9]
10
11const recognizedProperties = [
12  'name',
13  'version',
14  'onFail',
15]
16
17const recognizedEngines = [
18  'packageManager',
19  'runtime',
20  'cpu',
21  'libc',
22  'os',
23]
24
25/** checks a devEngine dependency */
26function checkDependency (wanted, current, opts) {
27  const { engine } = opts
28
29  if ((typeof wanted !== 'object' || wanted === null) || Array.isArray(wanted)) {
30    throw new Error(`Invalid non-object value for "${engine}"`)
31  }
32
33  const properties = Object.keys(wanted)
34
35  for (const prop of properties) {
36    if (!recognizedProperties.includes(prop)) {
37      throw new Error(`Invalid property "${prop}" for "${engine}"`)
38    }
39  }
40
41  if (!properties.includes('name')) {
42    throw new Error(`Missing "name" property for "${engine}"`)
43  }
44
45  if (typeof wanted.name !== 'string') {
46    throw new Error(`Invalid non-string value for "name" within "${engine}"`)
47  }
48
49  if (typeof current.name !== 'string' || current.name === '') {
50    throw new Error(`Unable to determine "name" for "${engine}"`)
51  }
52
53  if (properties.includes('onFail')) {
54    if (typeof wanted.onFail !== 'string') {
55      throw new Error(`Invalid non-string value for "onFail" within "${engine}"`)
56    }
57    if (!recognizedOnFail.includes(wanted.onFail)) {
58      throw new Error(`Invalid onFail value "${wanted.onFail}" for "${engine}"`)
59    }
60  }
61
62  if (wanted.name !== current.name) {
63    return new Error(
64      `Invalid name "${wanted.name}" does not match "${current.name}" for "${engine}"`
65    )
66  }
67
68  if (properties.includes('version')) {
69    if (typeof wanted.version !== 'string') {
70      throw new Error(`Invalid non-string value for "version" within "${engine}"`)
71    }
72    if (typeof current.version !== 'string' || current.version === '') {
73      throw new Error(`Unable to determine "version" for "${engine}" "${wanted.name}"`)
74    }
75    if (validRange(wanted.version)) {
76      if (!satisfies(current.version, wanted.version, opts.semver)) {
77        return new Error(
78          // eslint-disable-next-line max-len
79          `Invalid semver version "${wanted.version}" does not match "${current.version}" for "${engine}"`
80        )
81      }
82    } else if (wanted.version !== current.version) {
83      return new Error(
84        `Invalid version "${wanted.version}" does not match "${current.version}" for "${engine}"`
85      )
86    }
87  }
88}
89
90/** checks devEngines package property and returns array of warnings / errors */
91function checkDevEngines (wanted, current = {}, opts = {}) {
92  if ((typeof wanted !== 'object' || wanted === null) || Array.isArray(wanted)) {
93    throw new Error(`Invalid non-object value for "devEngines"`)
94  }
95
96  const errors = []
97
98  for (const engine of Object.keys(wanted)) {
99    if (!recognizedEngines.includes(engine)) {
100      throw new Error(`Invalid property "devEngines.${engine}"`)
101    }
102    const dependencyAsAuthored = wanted[engine]
103    const dependencies = [dependencyAsAuthored].flat()
104    const currentEngine = current[engine] || {}
105
106    // this accounts for empty array eg { runtime: [] } and ignores it
107    if (dependencies.length === 0) {
108      continue
109    }
110
111    const depErrors = []
112    for (const dep of dependencies) {
113      const result = checkDependency(dep, currentEngine, { ...opts, engine })
114      if (result) {
115        depErrors.push(result)
116      }
117    }
118
119    const invalid = depErrors.length === dependencies.length
120
121    if (invalid) {
122      const lastDependency = dependencies[dependencies.length - 1]
123      let onFail = lastDependency.onFail || 'error'
124      if (onFail === 'download') {
125        onFail = 'error'
126      }
127
128      const err = Object.assign(new Error(`Invalid devEngines.${engine}`), {
129        errors: depErrors,
130        engine,
131        isWarn: onFail === 'warn',
132        isError: onFail === 'error',
133        current: currentEngine,
134        required: dependencyAsAuthored,
135      })
136
137      errors.push(err)
138    }
139  }
140  return errors
141}
142
143module.exports = {
144  checkDevEngines,
145}
146 
codekingpro/portable-devtools · Team Ai