|
1 | 1 | var AWS = require('aws-sdk');
|
2 | 2 | var CoreObject = require('core-object');
|
3 | 3 | var Promise = require('ember-cli/lib/ext/promise');
|
| 4 | +var fs = require('fs'); |
| 5 | +var path = require('path'); |
| 6 | +var readFile = Promise.denodeify(fs.readFile); |
| 7 | + |
| 8 | +var headObject = function(client, params) { |
| 9 | + return new Promise(function(resolve, reject) { |
| 10 | + client.headObject(params, function(err, data) { |
| 11 | + if (err && err.code === 'NotFound') { |
| 12 | + return resolve(); |
| 13 | + } |
| 14 | + else if (err) { |
| 15 | + return reject(err); |
| 16 | + } |
| 17 | + else { |
| 18 | + return resolve(data); |
| 19 | + } |
| 20 | + }); |
| 21 | + }); |
| 22 | +} |
4 | 23 |
|
5 | 24 | module.exports = CoreObject.extend({
|
6 | 25 | init: function(options) {
|
7 | 26 | var plugin = options.plugin;
|
8 | 27 | var config = plugin.pluginConfig;
|
9 |
| - var readConfig = plugin.readConfig; |
10 | 28 |
|
11 |
| - this._client = plugin.readConfig('s3Client') || new AWS.S3(config); |
12 |
| - this._bucket = plugin.readConfig('bucket'); |
13 |
| - this._keyPrefix = plugin.readConfig('keyPrefix'); |
14 |
| - this._filePattern = plugin.readConfig('filePattern'); |
15 |
| - this._currentRevisionIdentifier = plugin.readConfig('currentRevisionIdentifier'); |
| 29 | + this._plugin = plugin; |
| 30 | + this._client = plugin.readConfig('s3Client') || new AWS.S3(config); |
16 | 31 | },
|
17 | 32 |
|
18 |
| - fetchRevisions: function() { |
19 |
| - return Promise.hash({ |
20 |
| - revisions: this._getBucketContents(), |
21 |
| - current: this._getCurrentData() |
22 |
| - }) |
23 |
| - .then(this._createRevisionDataFromList.bind(this)); |
24 |
| - }, |
25 |
| - |
26 |
| - upload: function(key, fileContent) { |
27 |
| - var client = this._client; |
| 33 | + upload: function(options) { |
| 34 | + var client = this._client; |
| 35 | + var plugin = this._plugin; |
| 36 | + var bucket = options.bucket; |
| 37 | + var acl = options.acl || 'public-read'; |
| 38 | + var key = path.join(options.prefix, options.filePattern + ":" + options.revisionKey); |
| 39 | + var putObject = Promise.denodeify(client.putObject.bind(client)); |
28 | 40 |
|
29 | 41 | var params = {
|
30 |
| - Bucket: this._bucket, |
| 42 | + Bucket: bucket, |
31 | 43 | Key: key,
|
32 |
| - Body: fileContent, |
| 44 | + ACL: acl, |
33 | 45 | ContentType: 'text/html',
|
34 | 46 | CacheControl: 'max-age=0, no-cache'
|
35 | 47 | }
|
36 | 48 |
|
37 |
| - return new Promise(function(resolve, reject) { |
38 |
| - client.putObject(params, function(err, data) { |
39 |
| - if (err) { |
40 |
| - return reject(err); |
41 |
| - } else { |
42 |
| - return resolve(data); |
43 |
| - } |
44 |
| - }); |
| 49 | + return readFile(options.filePath).then(function(fileContents) { |
| 50 | + params.Body = fileContents; |
| 51 | + return putObject(params).then(function() { |
| 52 | + plugin.log('✔ ' + key); |
| 53 | + }) |
45 | 54 | });
|
46 | 55 | },
|
47 | 56 |
|
48 |
| - overwriteCurrentIndex: function(newRevisionKey) { |
49 |
| - var client = this._client; |
50 |
| - var bucket = this._bucket; |
51 |
| - var copySource = encodeURIComponent(bucket+'/'+newRevisionKey); |
| 57 | + activate: function(options) { |
| 58 | + var plugin = this._plugin; |
| 59 | + var client = this._client; |
| 60 | + var bucket = options.bucket; |
| 61 | + var acl = options.acl || 'public-read'; |
| 62 | + var revisionKey = path.join(options.prefix, options.filePattern + ":" + options.revisionKey); |
| 63 | + var indexKey = path.join(options.prefix, options.filePattern); |
| 64 | + var copySource = encodeURIComponent(path.join(bucket, revisionKey)); |
| 65 | + var copyObject = Promise.denodeify(client.copyObject.bind(client)); |
52 | 66 |
|
53 | 67 | var params = {
|
54 | 68 | Bucket: bucket,
|
55 | 69 | CopySource: copySource,
|
56 |
| - Key: this._filePattern |
| 70 | + Key: indexKey, |
| 71 | + ACL: acl, |
57 | 72 | };
|
58 | 73 |
|
59 |
| - return new Promise(function(resolve, reject) { |
60 |
| - client.copyObject(params, function(err, data) { |
61 |
| - if (err) { |
62 |
| - return reject(err); |
63 |
| - } else { |
64 |
| - return resolve(data); |
65 |
| - } |
66 |
| - }); |
67 |
| - }); |
68 |
| - }, |
69 |
| - |
70 |
| - _createRevisionDataFromList: function(data) { |
71 |
| - const revisionsData = this._sortBucketContents(data.revisions).Contents; |
72 |
| - const currentRevision = data.current; |
73 |
| - |
74 |
| - return revisionsData.map(function(d) { |
75 |
| - var revision = d.Key; |
76 |
| - |
77 |
| - return { revision: revision, active: revision === currentRevision }; |
| 74 | + return this.fetchRevisions(options).then(function(revisions) { |
| 75 | + var found = revisions.map(function(element) { return element.revision; }).indexOf(options.revisionKey); |
| 76 | + if (found >= 0) { |
| 77 | + return copyObject(params).then(function() { |
| 78 | + plugin.log('✔ ' + revisionKey + " => " + indexKey); |
| 79 | + }) |
| 80 | + } else { |
| 81 | + return Promise.reject("REVISION NOT FOUND!"); // see how we should handle a pipeline failure |
| 82 | + } |
78 | 83 | });
|
79 | 84 | },
|
80 | 85 |
|
81 |
| - _sortBucketContents: function(data) { |
82 |
| - data.Contents = data.Contents.sort(function(a, b) { |
83 |
| - return new Date(b.LastModified) - new Date(a.LastModified); |
84 |
| - }); |
85 |
| - return data; |
86 |
| - }, |
87 |
| - |
88 |
| - _getBucketContents: function() { |
89 |
| - var client = this._client; |
90 |
| - var keyPrefix = this._keyPrefix; |
91 |
| - var bucket = this._bucket; |
| 86 | + fetchRevisions: function(options) { |
| 87 | + var client = this._client; |
| 88 | + var bucket = options.bucket; |
| 89 | + var revisionPrefix = path.join(options.prefix, options.filePattern + ":"); |
| 90 | + var indexKey = path.join(options.prefix, options.filePattern); |
| 91 | + var listObjects = Promise.denodeify(client.listObjects.bind(client)); |
92 | 92 |
|
93 |
| - return new Promise(function(resolve, reject) { |
94 |
| - var params = { Bucket: bucket, Prefix: keyPrefix }; |
95 |
| - |
96 |
| - client.listObjects(params, function(err, data) { |
97 |
| - if (err) { |
98 |
| - return reject(err); |
99 |
| - } else { |
100 |
| - return resolve(data); |
101 |
| - } |
| 93 | + return Promise.hash({ |
| 94 | + revisions: listObjects({ Bucket: bucket, Prefix: revisionPrefix }), |
| 95 | + current: headObject(client, { Bucket: bucket, Key: indexKey }), |
| 96 | + }) |
| 97 | + .then(function(data) { |
| 98 | + return data.revisions.Contents.sort(function(a, b) { |
| 99 | + return new Date(b.LastModified) - new Date(a.LastModified); |
| 100 | + }).map(function(d) { |
| 101 | + var revision = d.Key.substr(revisionPrefix.length); |
| 102 | + var active = data.current && d.ETag === data.current.ETag; |
| 103 | + return { revision: revision, timestamp: d.LastModified, active: active }; |
102 | 104 | });
|
103 | 105 | });
|
104 | 106 | },
|
105 |
| - |
106 |
| - _getCurrentData: function() { |
107 |
| - var client = this._client; |
108 |
| - var bucket = this._bucket; |
109 |
| - var currentRevisionIdentifier = this._currentRevisionIdentifier; |
110 |
| - |
111 |
| - return new Promise(function(resolve, reject) { |
112 |
| - var params = { Bucket: bucket, Key: currentRevisionIdentifier }; |
113 |
| - |
114 |
| - client.getObject(params, function(err, data) { |
115 |
| - if (err && err.code === 'NoSuchKey') { |
116 |
| - return resolve(); |
117 |
| - } |
118 |
| - else if (err) { |
119 |
| - return reject(err); |
120 |
| - } |
121 |
| - else { |
122 |
| - var json = JSON.parse(data.Body.toString('utf8')); |
123 |
| - |
124 |
| - return resolve(json.revision); |
125 |
| - } |
126 |
| - }); |
127 |
| - }); |
128 |
| - } |
129 | 107 | });
|
0 commit comments