UNPKG

3.15 kBJavaScriptView Raw
1const hash = require('object-hash');
2
3/** Helper class with high-level operations for condition-management. */
4class Conditions {
5 constructor(fastly) {
6 this._fastly = fastly;
7 }
8
9 /**
10 * Creates functions for multi-step creation of missing and deletion of
11 * superflous conditions.
12 *
13 * @param {number} version - Service config version.
14 * @param {string} type - Condition type, can be `REQUEST`, `RESPONSE`, or `CACHE`.
15 * @param {string} commentprefix - The prefix to be used for comments.
16 * @param {string} nameprefix - - The prefix to be used for names.
17 * @returns {Function[]} A pair of a create and cleanup function.
18 */
19 multistepupdate(version, type, commentprefix, nameprefix) {
20 const conditions = (statements) => statements.map((statement) => {
21 const hashable = {
22 type,
23 statement,
24 };
25
26 const name = `${nameprefix}-${hash(hashable)}`;
27 const comment = `${commentprefix} (${hash(hashable)})`;
28
29 return {
30 name,
31 comment,
32 priority: '10',
33 ...hashable,
34 };
35 });
36
37 const create = async (...statements) => {
38 const existing = (await this._fastly.readConditions(version)).data;
39 // keep a list of known names in the remote service
40 const existingnames = new Set(existing.map(({ name }) => name));
41
42 const tocreate = conditions(statements)
43 // only consider conditions that don't exist in the remote service
44 .filter(({ name }) => !existingnames.has(name))
45 // schedule each condition that does not yet exist on Fastly
46 // but was passed as an argument to be created
47 .map((condition) => this._fastly.createCondition(version, condition));
48
49 await Promise.all(tocreate);
50
51 // create a lookup map that takes the statement as key and returns the condition
52 // as value
53
54 return conditions(statements).reduce((p, condition) => {
55 const q = {};
56 q[condition.statement] = condition;
57 return Object.assign(p, q);
58 }, {});
59 };
60
61 const cleanup = async (...statements) => {
62 const existing = (await this._fastly.readConditions(version)).data;
63 // generate a set of known names
64 const conditionnames = new Set(conditions(statements).map(({ name }) => name));
65
66 const todelete = existing
67 // only look at conditions that start with 'our' prefix
68 .filter(({ name }) => name.startsWith(`${nameprefix}-`))
69 // only keep those that are *not* in the list of generated names
70 .filter(({ name }) => !conditionnames.has(name))
71 // schedule each condition that exists on Fastly, but wasn't passed as
72 // an argument for deletion
73 .map(({ name }) => this._fastly.deleteCondition(version, name));
74
75 await Promise.all(todelete);
76 };
77
78 return [create, cleanup];
79 }
80
81 update(version, type, commentprefix, nameprefix) {
82 return async (...statements) => {
83 const [create, cleanup] = this.multistepupdate(version, type, commentprefix, nameprefix);
84 await cleanup(...statements);
85 return create(...statements);
86 };
87 }
88}
89
90module.exports = Conditions;