blob: 482553323cf3e25476b22d813bf2d18177853d01 [file] [log] [blame]
Chinthakayala, Sheshashailavas (sc2914)d1569972017-08-28 05:25:46 -09001/**
2 * Copyright 2013, 2014 IBM Corp.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 **/
16
17var fs = require('fs');
18var when = require('when');
19var nodeFn = require('when/node/function');
20var keys = require('when/keys');
21var util = require('util');
22var fspath = require("path");
23var mkdirp = require("mkdirp");
24
25var promiseDir = nodeFn.lift(mkdirp);
26
27var settings;
28var flowsFile;
29var flowsFullPath;
30var flowsPrev;
31var credentialsFile;
32var oldCredentialsFile;
33var userDir;
34var libDir;
35var libFlowsDir;
36var globalSettingsFile;
37
38function listFiles(dir) {
39 var dirs = {};
40 var files = [];
41 var dirCount = 0;
42 return nodeFn.call(fs.readdir, dir).then(function (contents) {
43 contents.sort().forEach(function(fn) {
44 var stats = fs.lstatSync(dir+"/"+fn);
45 if (stats.isDirectory()) {
46 dirCount += 1;
47 dirs[fn] = listFiles(dir+"/"+fn)
48 } else {
49 files.push(fn.split(".")[0]);
50 }
51 })
52 var result = {};
53 if (dirCount > 0) { result.d = keys.all(dirs); }
54 if (files.length > 0) { result.f = when.resolve(files); }
55 return keys.all(result);
56 })
57}
58
59function getFileMeta(root,path) {
60 var fn = fspath.join(root,path);
61 var fd = fs.openSync(fn,"r");
62 var size = fs.fstatSync(fd).size;
63 var meta = {};
64 var read = 0;
65 var length = 10;
66 var remaining = "";
67 var buffer = Buffer(length);
68 while(read < size) {
69 read+=fs.readSync(fd,buffer,0,length);
70 var data = remaining+buffer.toString();
71 var parts = data.split("\n");
72 remaining = parts.splice(-1);
73 for (var i=0;i<parts.length;i+=1) {
74 var match = /^\/\/ (\w+): (.*)/.exec(parts[i]);
75 if (match) {
76 meta[match[1]] = match[2];
77 } else {
78 read = size;
79 break;
80 }
81 }
82 }
83 fs.closeSync(fd);
84 return meta;
85}
86
87function getFileBody(root,path) {
88 var body = "";
89 var fn = fspath.join(root,path);
90 var fd = fs.openSync(fn,"r");
91 var size = fs.fstatSync(fd).size;
92 var scanning = true;
93 var read = 0;
94 var length = 50;
95 var remaining = "";
96 var buffer = Buffer(length);
97 while(read < size) {
98 var thisRead = fs.readSync(fd,buffer,0,length);
99 read += thisRead;
100 if (scanning) {
101 var data = remaining+buffer.slice(0,thisRead).toString();
102 var parts = data.split("\n");
103 remaining = parts.splice(-1)[0];
104 for (var i=0;i<parts.length;i+=1) {
105 if (! /^\/\/ \w+: /.test(parts[i])) {
106 scanning = false;
107 body += parts[i]+"\n";
108 }
109 }
110 if (! /^\/\/ \w+: /.test(remaining)) {
111 scanning = false;
112 }
113 if (!scanning) {
114 body += remaining;
115 }
116 } else {
117 body += buffer.slice(0,thisRead).toString();
118 }
119 }
120 fs.closeSync(fd);
121 return body;
122}
123
124var localfilesystem = {
125 init: function(_settings) {
126 settings = _settings;
127 userDir = settings.userDir || process.env.NODE_RED_HOME;
128
129 if (settings.flowFile) {
130 flowsFile = settings.flowFile;
131 flowsFullPath = flowsFile;
132 } else {
133 flowsFile = 'flows_'+require('os').hostname()+'.json';
134 flowsFullPath = fspath.join(userDir,flowsFile);
135 }
136 var fsext = fspath.extname(flowsFile);
137 credentialsFile = fspath.join(userDir,fspath.basename(flowsFile,fsext)+"_cred"+fsext);
138 oldCredentialsFile = fspath.join(userDir,"credentials.json");
139 flowsPrev = fspath.join(userDir,"flows.backup");
140
141 libDir = fspath.join(userDir,"lib");
142 libFlowsDir = fspath.join(libDir,"flows");
143
144
145 globalSettingsFile = fspath.join(userDir,".config.json");
146
147 return promiseDir(libFlowsDir);
148 },
149
150 getFlows: function() {
151 var defer = when.defer();
152 fs.exists(flowsFullPath, function(exists) {
153 if (exists) {
154 util.log("[red] Loading flows : "+flowsFile);
155 defer.resolve(nodeFn.call(fs.readFile,flowsFullPath,'utf8').then(function(data) {
156 return JSON.parse(data);
157 }));
158 } else {
159 util.log("[red] Flows file not found : "+flowsFile );
160 defer.resolve([]);
161 }
162 });
163 return defer.promise;
164 },
165
166 saveFlows: function(flows) {
167 if (fs.existsSync(flowsFullPath)) {
168 fs.renameSync(flowsFullPath,flowsPrev);
169 }
170
171 var flowData;
172
173 if (settings.flowFilePretty) {
174 flowData = JSON.stringify(flows,null,4);
175 } else {
176 flowData = JSON.stringify(flows);
177 }
178 console.log("Writing to file:" + flowsFullPath);
179 return nodeFn.call(fs.writeFile, flowsFullPath, flowData);
180 },
181
182 getCredentials: function() {
183 var defer = when.defer();
184 fs.exists(credentialsFile, function(exists) {
185 if (exists) {
186 defer.resolve(nodeFn.call(fs.readFile, credentialsFile, 'utf8').then(function(data) {
187 return JSON.parse(data)
188 }));
189 } else {
190 fs.exists(oldCredentialsFile, function(exists) {
191 if (exists) {
192 defer.resolve(nodeFn.call(fs.readFile, oldCredentialsFile, 'utf8').then(function(data) {
193 return JSON.parse(data)
194 }));
195 } else {
196 defer.resolve({});
197 }
198 });
199 }
200 });
201 return defer.promise;
202 },
203
204 saveCredentials: function(credentials) {
205 var credentialData;
206 if (settings.flowFilePretty) {
207 credentialData = JSON.stringify(credentials,null,4);
208 } else {
209 credentialData = JSON.stringify(credentials);
210 }
211
212 return nodeFn.call(fs.writeFile, credentialsFile, credentialData)
213 },
214
215 getSettings: function() {
216 if (fs.existsSync(globalSettingsFile)) {
217 return nodeFn.call(fs.readFile,globalSettingsFile,'utf8').then(function(data) {
218 if (data) {
219 try {
220 return JSON.parse(data);
221 } catch(err) {
222 util.log("[red] Corrupted config detected - resetting");
223 return {};
224 }
225 } else {
226 return {};
227 }
228 });
229 }
230 return when.resolve({});
231 },
232 saveSettings: function(settings) {
233 return nodeFn.call(fs.writeFile,globalSettingsFile,JSON.stringify(settings,null,1),'utf8');
234 },
235
236
237 getAllFlows: function() {
238 return listFiles(libFlowsDir);
239 },
240
241 getFlow: function(fn) {
242 var defer = when.defer();
243 var file = fspath.join(libFlowsDir,fn+".json");
244 fs.exists(file, function(exists) {
245 if (exists) {
246 defer.resolve(nodeFn.call(fs.readFile,file,'utf8'));
247 } else {
248 defer.reject();
249 }
250 });
251 return defer.promise;
252 },
253
254 saveFlow: function(fn,data) {
255 var file = fspath.join(libFlowsDir,fn+".json");
256 return promiseDir(fspath.dirname(file)).then(function () {
257 return nodeFn.call(fs.writeFile, file, data);
258 });
259 },
260
261 getLibraryEntry: function(type,path) {
262 var root = fspath.join(libDir,type);
263 var rootPath = fspath.join(libDir,type,path);
264 return promiseDir(root).then(function () {
265 return nodeFn.call(fs.lstat, rootPath).then(function(stats) {
266 if (stats.isFile()) {
267 return getFileBody(root,path);
268 }
269 if (path.substr(-1) == '/') {
270 path = path.substr(0,path.length-1);
271 }
272 return nodeFn.call(fs.readdir, rootPath).then(function(fns) {
273 var dirs = [];
274 var files = [];
275 fns.sort().filter(function(fn) {
276 var fullPath = fspath.join(path,fn);
277 var absoluteFullPath = fspath.join(root,fullPath);
278 if (fn[0] != ".") {
279 var stats = fs.lstatSync(absoluteFullPath);
280 if (stats.isDirectory()) {
281 dirs.push(fn);
282 } else {
283 var meta = getFileMeta(root,fullPath);
284 meta.fn = fn;
285 files.push(meta);
286 }
287 }
288 });
289 return dirs.concat(files);
290 });
291 });
292 });
293 },
294
295 saveLibraryEntry: function(type,path,meta,body) {
296 var fn = fspath.join(libDir, type, path);
297 var headers = "";
298 for (var i in meta) {
299 if (meta.hasOwnProperty(i)) {
300 headers += "// "+i+": "+meta[i]+"\n";
301 }
302 }
303 return promiseDir(fspath.dirname(fn)).then(function () {
304 nodeFn.call(fs.writeFile, fn, headers+body);
305 });
306 }
307};
308
309module.exports = localfilesystem;