-
Notifications
You must be signed in to change notification settings - Fork 2
/
fetch.js
executable file
·123 lines (102 loc) · 3.27 KB
/
fetch.js
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
'use strict';
const Azure = require('Azure-storage');
const EmberCliDeployError = require('./errors/ember-cli-deploy-error');
const Memoize = require('memoizee');
const Promise = require('bluebird');
const _defaultsDeep = require('lodash/defaultsDeep');
// default options
const _defaultOpts = {
azureTableName: 'emberdeploy',
revisionQueryParam: 'index_key',
memoize: false,
memoizeOpts: {
maxAge: 5000, // ms
preFetch: true,
max: 4, // a sane default (current pointer, current html and two indexkeys in cache)
}
};
let opts;
/**
* Merges user-supplied options with defaults.
*/
const _getOpts = (opts) => {
opts = opts || {};
return _defaultsDeep({}, opts, _defaultOpts);
};
let initialized = false;
let azureTableService;
/**
* Initialize connection to Azure Storage and apply
* Memoization options, if applicable.
*/
const _initialize = (connectionInfo, passedOpts) => {
opts = _getOpts(passedOpts);
if (connectionInfo.accountName && connectionInfo.accessKey) {
azureTableService = Azure.createTableService(connectionInfo.accountName, connectionInfo.accessKey);
if (opts.memoize === true) {
let memoizeOpts = opts.memoizeOpts;
memoizeOpts.primitive = true;
memoizeOpts.async = true;
memoizeOpts.length = 3;
azureTableService.retrieveEntity = Memoize(azureTableService.retrieveEntity, memoizeOpts);
}
initialized = true;
} else {
throw new EmberCliDeployError('No connection info specified. accountName and accessKey must be defined.', true);
}
};
/**
* Retrieves the HTML from Azure Table Storage.
*/
const fetchIndex = (req, appName, connectionInfo, passedOpts) => {
if (!initialized) {
_initialize(connectionInfo, passedOpts);
}
let rowKey;
if (req.query[opts.revisionQueryParam]) {
const queryKey = req.query[opts.revisionQueryParam].replace(/[^A-Za-z0-9]/g, '');
rowKey = appName + ':' + queryKey;
}
/**
* Retrieves the row key of the active revision.
*/
function retrieveRowKey() {
if (rowKey) {
return Promise.resolve(rowKey);
} else {
return queryAzure(opts.azureTableName, 'manifest', appName + ':current')
.then((result) => result)
.catch((err) => {
throw err;
});
}
}
/**
* Returns the active revision based on the row key
* returned by `retrieveRowKey()`
*/
function queryAzure(table, partitionKey, rowKey) {
return new Promise((resolve, reject) => {
azureTableService.retrieveEntity(table, partitionKey, rowKey, (error, result, response) => {
if (!result) {
reject(new EmberCliDeployError("There's no " + rowKey + ' revision.', true));
} else if (error) {
reject(new Error(error));
} else {
// Azure tables returns a goofy result with a content object containing another object
// with a key of '-', so need to grab the result from that
const key = Object.keys(result.content)[0];
resolve(result.content[key]);
}
});
});
}
/**
* Retrieve the row key for the active revision and
* return the active revision's content.
*/
return retrieveRowKey()
.then((rowKey) => queryAzure(opts.azureTableName, 'manifest', rowKey))
.then((html) => html);
};
module.exports = fetchIndex;