netlify
Version:
Netlify API client
247 lines (206 loc) • 6.88 kB
JavaScript
var path = require("path"),
when = require("when"),
nodefn = require("when/node"),
glob = require("glob"),
crypto = require("crypto"),
fs = require("graceful-fs");
model = require("./model"),
Form = require("./form").Form,
Submission = require("./submission").Submission,
File = require("./file").File,
Snippet = require("./snippet").Snippet,
Deploy = require("./deploy").Deploy;
var Site = model.constructor();
Site.path = "/sites";
function globFiles(dir) {
return nodefn.call(glob, "**/*", {cwd: dir}).then(function(files) {
var filtered = files.filter(function(file) {
return file.match(/(\/__MACOSX|\/\.)/) ? false : true;
}).map(function(file) { return {rel: file, abs: path.resolve(dir, file)}; });
return filterFiles(filtered);
})
};
function filterFiles(filesAndDirs) {
var lstats = filesAndDirs.map(function(fileOrDir) {
return nodefn.call(fs.lstat, fileOrDir.abs)
});
return when.all(lstats).then(function(fileData) {
var result = [];
for (var i=0,len=fileData.length; i<len; i++) {
var file = filesAndDirs[i],
data = fileData[i];
if (data.isFile()) {
result.push(file);
}
}
return result;
});
};
function calculateShas(files) {
var shas = files.map(function(file) {
return nodefn.call(fs.readFile, file.abs).then(function(data) {
var shasum = crypto.createHash('sha1');
shasum.update(data);
file.sha = shasum.digest('hex');
return true;
});
});
return when.all(shas).then(function() {
var result = {};
files.forEach(function(file) {
result[file.rel] = file.sha;
});
return {files: files, shas: result};
});
};
function deployFromDir(site, dir, draft, progress) {
var fullDir = path.resolve(dir);
return nodefn.call(fs.stat, fullDir).then(function(stat) {
if (stat.isFile()) {
throw("No such dir " + dir + " (" + fullDir + ")");
}
return globFiles(fullDir).then(calculateShas).then(function(filesWithShas) {
return site.client.request({
url: site.apiPath + "/deploys",
type: "post",
body: JSON.stringify({
files: filesWithShas.shas,
draft: draft
})
}).then(function(response) {
var deploy = new Deploy(site.client, response.data);
var shas = {};
response.data.required.forEach(function(sha) { shas[sha] = true; });
var filtered = filesWithShas.files.filter(function(file) { return shas[file.sha]; });
return deploy.uploadFiles(filtered,progress);
});
});
}).catch(function(err) {
return when.reject(err);
});
};
function deployFromZip(site, zip, draft) {
var fullPath = zip.match(/^\//) ? zip : process.cwd() + "/" + zip;
return nodefn.call(fs.readFile, fullPath).then(function(zipData) {
var path = site.apiPath + "/deploys";
if (draft) { path += "?draft=true"; }
return site.client.request({
url: path,
type: "post",
body: zipData,
contentType: "application/zip"
}).then(function(response) {
return new Deploy(site.client, response.data);
});
});
};
var attributesForUpdate = function(attributes) {
var mapping = {
name: "name",
customDomain: "custom_domain",
notificationEmail: "notification_email",
password: "password",
github: "github",
repo: "repo",
domainAliases: "domain_aliases"
},
result = {};
for (var key in attributes) {
if (mapping[key]) result[mapping[key]] = attributes[key];
}
return result;
};
Site.createFromDir = function(client, dir, progress) {
return Site.create(client, {}).then(function(site) {
return site.createDeploy({dir: dir, progress: progress}).then(function(deploy) {
site.deploy_id = deploy.id;
return site;
});
});
};
Site.createFromZip = function(client, zip) {
return Site.create(client, {}).then(function(site) {
return site.createDeploy({zip: zip}).then(function(deploy) {
site.deploy_id = deploy.id;
return site;
});
});
};
Site.create = function(client, attributes) {
return client.create({model: Site, attributes: attributesForUpdate(attributes)});
};
Site.prototype = {
isReady: function() {
return this.state == "current";
},
refresh: function() {
var self = this;
return this.client.request({
url: "/sites/" + this.id
}).then(function(response) {
Site.call(self, response.client, response.data);
return self;
});
},
update: function(attributes) {
attributes = attributes || {};
var self = this;
if (attributes.dir) {
return createFromDir(this.client, attributes.dir, this.id);
} else if (attributes.zip) {
return createFromZip(this.client, attributes.zip, this.id);
} else {
return this.client.update({model: Site, element: this, attributes: attributesForUpdate(attributes)});
}
},
destroy: function() {
return this.client.destroy({element: this});
},
createDeploy: function(attributes) {
if (attributes.dir) {
return deployFromDir(this, attributes.dir, attributes.draft || false, attributes.progress);
} else if (attributes.zip) {
return deployFromZip(this, attributes.zip, attributes.draft || false);
} else {
return when.reject("You must specify a 'dir' or a 'zip' to deploy");
}
},
createDraftDeploy: function(attributes) {
attributes.draft = true;
return this.createDeploy(attributes);
},
waitForReady: function() {
if (this.isReady()) {
return when.resolve(this);
}
return when.resolve().delay(1000).then(this.refresh.bind(this)).then(this.waitForReady.bind(this));
},
forms: function(options) {
return this.client.collection({prefix: this.apiPath, model: Form}, options);
},
submissions: function(options) {
return this.client.collection({prefix: this.apiPath, model: Submission}, options);
},
files: function() {
return this.client.collection({prefix: this.apiPath, model: File});
},
file: function(path) {
return this.client.element({prefix: this.apiPath, model: File, id: path});
},
snippets: function() {
return this.client.collection({prefix: this.apiPath, model: Snippet});
},
snippet: function(id) {
return this.client.element({prefix: this.apiPath, model: Snippet, id: id});
},
createSnippet: function(attributes) {
return this.client.create({prefix: this.apiPath, model: Snippet, attributes: attributes});
},
deploys: function(options) {
return this.client.collection({prefix: this.apiPath, model: Deploy}, options);
},
deploy: function(id) {
return this.client.element({prefix: this.apiPath, model: Deploy, id: id});
}
};
exports.Site = Site;