UNPKG

3.2 kBJavaScriptView Raw
1'use strict'
2
3const fs = require('fs')
4const path = require('path')
5const mkdirp = require('mkdirp')
6const assert = require('assert')
7const yaml = require('js-yaml')
8const dirname = require('path').dirname
9
10exports.exists = exists
11exports.existsSync = existsSync
12exports.mkdir = mkdir
13exports.readFile = readFile
14exports.writeFile = writeFile
15exports.writeFileSync = writeFileSync
16exports.renameFile = renameFile
17exports.readDir = readDir
18exports.parseFileContents = parseFileContents
19exports.resolveSchemaRefs = resolveSchemaRefs
20exports.isFunc = isFunc
21exports.isObj = isObj
22
23function exists(filePath) {
24 return new Promise((res, rej) =>
25 fs.lstat(filePath, (err, stats) =>
26 err ? rej(err) : res(stats)))
27}
28
29function existsSync(filePath) {
30 try {
31 return fs.lstatSync(filePath)
32 } catch (e) {
33 return false
34 }
35}
36
37function mkdir(dirPath) {
38 return new Promise((res, rej) =>
39 mkdirp(dirPath, err =>
40 err && err.code !== 'EEXIST' ? rej(err) : res()))
41}
42
43function readFile(filePath) {
44 return new Promise((res, rej) =>
45 fs.readFile(filePath, 'utf8', (err, contents) =>
46 err ? rej(err) : res(contents)))
47}
48
49function writeFile(filePath, contents) {
50 return new Promise((res, rej) =>
51 mkdir(dirname(filePath)).then(() =>
52 fs.writeFile(filePath, contents, err =>
53 err ? rej(err) : res())))
54}
55
56function writeFileSync(filePath, contents) {
57 mkdirp.sync(dirname(filePath))
58 fs.writeFileSync(filePath, contents)
59}
60
61function renameFile(oldPath, newPath) {
62 return new Promise((res, rej) =>
63 fs.rename(oldPath, newPath, err =>
64 err ? rej(err) : res()))
65}
66
67function readDir(dirPath) {
68 return new Promise((res, rej) =>
69 fs.readdir(dirPath, (err, files) =>
70 err ? rej(err) : res(files)))
71}
72
73function parseFileContents(contents, path) {
74 return isYamlFile(path) ?
75 yaml.safeLoad(contents) :
76 JSON.parse(contents)
77}
78
79function isYamlFile(filePath) {
80 return path.extname(filePath).match(/^\.ya?ml$/)
81}
82
83const dataCache = new Set()
84
85/**
86 * Recursively resolves references in the form `#/path/to/object`.
87 *
88 * @param {object} data the object to search for and update refs
89 * @param {object} lookup the object to clone refs from
90 * @returns {*} the resolved data object
91 */
92function resolveSchemaRefs(data, lookup) {
93 if (!data || dataCache.has(data)) return data
94
95 if (Array.isArray(data)) {
96 return data.map(item => resolveSchemaRefs(item, lookup))
97 } else if (typeof data === 'object') {
98 if (data.$ref) {
99 const resolved = resolveSchemaRef(data.$ref, lookup)
100 delete data.$ref
101 data = Object.assign({}, resolved, data)
102 }
103 dataCache.add(data)
104
105 for (let name in data) {
106 data[name] = resolveSchemaRefs(data[name], lookup)
107 }
108 }
109 return data
110}
111
112function resolveSchemaRef(ref, lookup) {
113 const parts = ref.split('/')
114
115 assert.ok(parts.shift() === '#', `Only support JSON Schema $refs in format '#/path/to/ref'`)
116
117 let value = lookup
118 while (parts.length) {
119 value = value[parts.shift()]
120 assert.ok(value, `Invalid schema reference: ${ref}`)
121 }
122 return value
123}
124
125function isFunc(f) {
126 return !!f && typeof f === 'function'
127}
128
129function isObj(o) {
130 return !!o && typeof o === 'object'
131}