forked from octet-stream/node-yaml
-
-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.coffee
250 lines (202 loc) · 5.46 KB
/
main.coffee
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
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
{dirname, basename, extname, isAbsolute, join, resolve} = require "path"
{readFileSync, writeFileSync, readdirSync} = require "fs"
co = require "co"
junk = require "junk"
{parse, load, dump} = yaml = require "js-yaml"
{readFile, writeFile, readdir} = require "promise-fs"
PARSER_SCHEMA =
defaultSafe: yaml.DEFAULT_SAFE_SCHEMA
defaultFull: yaml.DEFAULT_FULL_SCHEMA
failsafe: yaml.FAILSAFE_SCHEMA
json: yaml.JSON_SCHEMA
core: yaml.CORE_SCHEMA
YAML_EXT = [".yaml", ".yml"]
isString = (val) -> typeof val is "string"
isNumber = (val) -> typeof val is "nubmber"
if module.parent? and isString module.parent.filename
PARENT_DIRNAME = dirname module.parent.filename
delete require.cache[__filename]
else
PARENT_DIRNAME = do process.cwd
###
# Fulfill a promised function as callback-style function if it given
# or return a promise
#
# @param {function} cb
# @param {fn} – promised function, wrapped into clojure (see yaml.read method)
#
# @return {void | Promise<any>}
*
* @api private
###
fulfill = (cb, fn) ->
return do fn unless typeof cb is "function"
onFulfilled = (res) -> cb null, res
onRejected = (err) -> cb err
promise = do fn
promise.then onFulfilled, onRejected
return
###
# Normalize path to YAML file
#
# @param {string} filename – Path to YAML file
#
# @return {Promise<string>}
#
# @api private
###
normalizePath = (filename) ->
unless isAbsolute filename
filename = resolve PARENT_DIRNAME, filename
base = basename filename
dir = dirname filename
files = yield readdir dir
for file in files when junk.not file
__ext = extname file
__base = basename file, __ext
if base is __base and __ext in YAML_EXT
return join dir, file
return filename
###
# Normalize path to YAML file (Synchronously)
#
# @param {string} filename - path to YAML file
#
# @return {string}
#
# @api private
###
normalizePathSync = (filename) ->
unless isAbsolute filename
filename = resolve PARENT_DIRNAME, filename
base = basename filename
dir = dirname filename
files = readdirSync dir
for file in files when junk.not file
__ext = extname file
__base = basename file, __ext
if base is __base and __ext in YAML_EXT
return join dir, file
return filename
###
# Normalize options
#
# @param {string | object} [options = {null}]
#
# @return {object}
#
# @api private
###
normalizeOptions = (options = {}) ->
unless options?
return encoding: "utf8", schema: PARSER_SCHEMA.defaultSafe
options = switch typeof options
when "string"
encoding: options
schema: PARSER_SCHEMA.defaultSafe
when "object"
options.encoding or= "utf8"
options.schema or= PARSER_SCHEMA.defaultSafe
options
return options
###
# Read YAML file with Promise
#
# @param {number | string} filename - path or file descriptor
# @param {object} [options = null]
#
# @return {Promise<object>}
#
# @api private
###
readYamlFile = co.wrap (filename, options = {}) ->
filename = yield normalizePath filename unless isNumber filename
options = normalizeOptions options
content = yield readFile filename, options.encoding
return load content, options
###
# Read and parse YAML file
# Note: Returns an instance of Promise unless callback given
#
# @param {number | string} filename - path or file descriptor
# @param {object} [options = null]
# @param {function} [cb = null]
#
# @return {void | Promise<object>}
###
read = (filename, options = {}, cb = null) ->
if typeof options is "function"
[cb, options] = [options, {}]
return fulfill cb, -> readYamlFile filename, options
###
# Synchronous version of yaml.read
#
# @param {string | number} filename – path or file descriptor
# @param {string | object} [options = {}]
#
# @return {object}
###
readSync = (filename, options = {}) ->
options = normalizeOptions options
filename = normalizePathSync filename unless isNumber filename
content = readFileSync filename, options.encoding
content = load content, options
return content
###
# Write some content to YAML file with Promise
#
# @param {string | number} – path or file descriptor
# @paeam {any} content – a file contents
# @param {string | object} [options = {}]
#
# @return {void | Promise<void>}
#
# @api private
###
writeYamlFile = co.wrap (filename, content, options = {}) ->
filename = yield normalizePath filename unless isNumber filename
options = normalizeOptions options
content = dump content, options
yield writeFile filename, content, options
return
###
# Write some content to YAML file
# Note: Returns an instance of Promise unless callback given
#
# @param int|string filename - path or file descriptor
# @param object content - File content
# @param object options
# @param function cb
#
# @return {void | Promise<void>}
###
write = (filename, content, options = {}, cb = null) ->
if typeof options is "function"
[cb, options] = [options, {}]
return fulfill cb, -> writeYamlFile filename, content, options
###
# Synchronous version of yaml.write
#
# @param {string | number} filename – path or file descriptor
# @param {any} content – a file contents
#
# @return {void}
###
writeSync = (filename, content, options = {}) ->
filename = normalizePathSync filename
options = normalizeOptions options
content = dump content
writeFileSync filename, content, options.encoding or null
return
module.exports = {
parser: yaml
Type: yaml.Type
createSchema: yaml.Schema.create
schema: PARSER_SCHEMA
parse: load
dump
read
readSync
write
writeSync
}