@speedkit/cli 2.27.0 → 2.28.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,3 +1,10 @@
1
+ # [2.28.0](https://gitlab.orestes.info/baqend/speed-kit-cli/compare/v2.27.0...v2.28.0) (2024-05-22)
2
+
3
+
4
+ ### Features
5
+
6
+ * **customer-config:** remove old deployment detection ([a3661c7](https://gitlab.orestes.info/baqend/speed-kit-cli/commit/a3661c7db68ade9907b15caaa1edf370e51783ca))
7
+
1
8
  # [2.27.0](https://gitlab.orestes.info/baqend/speed-kit-cli/compare/v2.26.0...v2.27.0) (2024-05-03)
2
9
 
3
10
 
package/README.md CHANGED
@@ -21,7 +21,7 @@ $ npm install -g @speedkit/cli
21
21
  $ sk COMMAND
22
22
  running command...
23
23
  $ sk (--version)
24
- @speedkit/cli/2.27.0 linux-x64 node-v20.12.2
24
+ @speedkit/cli/2.28.0 linux-x64 node-v20.13.1
25
25
  $ sk --help [COMMAND]
26
26
  USAGE
27
27
  $ sk COMMAND
@@ -264,9 +264,6 @@ class CustomerConfigService {
264
264
  async generateConfig() {
265
265
  this.cli.write("\nLet's generate a config...\n");
266
266
  const configSettings = await this.getConfigSettings();
267
- if (configSettings.isSalesforce) {
268
- this.templates.push("deploymentDetection.es6.hbs");
269
- }
270
267
  const addDowntimeDetection = await this.cli.confirm("Add Downtime Detection?", false);
271
268
  if (addDowntimeDetection) {
272
269
  this.templates.push("downtimeDetection.js.hbs");
@@ -87,11 +87,7 @@ const config = {
87
87
  {{else}}
88
88
  delayScriptPath: "/speed-kit-dom-ready.js",
89
89
  {{/if}}
90
- {{#if isSalesforce}}
91
- executeDeploymentDetection: false, // Salesforce specific => deploymentDetection.es6 is being used instead
92
- {{else}}
93
90
  executeDeploymentDetection: true,
94
- {{/if}}
95
91
  {{#unless addPreRendering}}
96
92
  {{#if removeLazyLoading}}
97
93
  lazyLoadList,
@@ -667,5 +667,5 @@
667
667
  ]
668
668
  }
669
669
  },
670
- "version": "2.27.0"
670
+ "version": "2.28.0"
671
671
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@speedkit/cli",
3
3
  "description": "Speed Kit CLI",
4
- "version": "2.27.0",
4
+ "version": "2.28.0",
5
5
  "author": {
6
6
  "name": "Baqend.com",
7
7
  "email": "info@baqend.com"
@@ -1,303 +0,0 @@
1
- // Salesforce specific:
2
-
3
- const { run: executeRefresh } = require('./speedKit.CronJob');
4
- const fetch = require('node-fetch');
5
-
6
- const minutesToMilliseconds = (minutes) => {
7
- return minutes * 60000;
8
- }
9
-
10
- const LOCALES_BY_LAYOUT = [
11
- // TODO: adjust/replace this exemplary list
12
- ExampleLayoutA: ["de_DE", "en_DE"],
13
- ExampleLayoutB: ["en_US"],
14
- ];
15
- const ASSET_SUB_PATHS = [
16
- // These assets are expected to be found via the following base URL:
17
- // https://<ORIGIN>/on/demandware.static/Sites-<LAYOUT>-Site/-/<LOCALE>/v<VERSION>/...
18
-
19
- // TODO: adjust/replace this exemplary list
20
-
21
- // JS:
22
- "js/main.js",
23
- "internal/jscript/dwanalytics-(.*).js",
24
-
25
- // CSS:
26
- "css/style.css",
27
- ];
28
-
29
- function getAssetList() {
30
- return Object.entries(LOCALES_BY_LAYOUT).flatMap(([layout, locales]) =>
31
- locales.flatMap((locale) =>
32
- ASSET_SUB_PATHS.map(
33
- (subPath) =>
34
- {{#if staging.host}}
35
- `^https://(?:{{production.host}}|{{staging.host}})/on/demandware.static/Sites-${layout}-Site/-/${locale}/v(\\d{13})/${subPath}`,
36
- {{else}}
37
- `^https://{{production.host}}/on/demandware.static/Sites-${layout}-Site/-/${locale}/v(\\d{13})/${subPath}`,
38
- {{/if}}
39
- ),
40
- );
41
- }
42
-
43
- const deploymentConfig = {
44
- slack: "<1Password deployment token>",
45
- origins: [
46
- // Production:
47
- "https://{{production.host}}",
48
- {{#if staging.host}}
49
-
50
- // Staging:
51
- "https://{{staging.host}}",
52
- {{/if}}
53
-
54
- // TODO: also check for other origins like e.g. https://*.my.salesforce.com
55
- ],
56
- jobType: "deployment", // "instant" | "deployment"
57
-
58
- // configure how long the origin deployment takes in milliseconds:
59
- deploymentDelay: minutesToMilliseconds(15),
60
-
61
- // throttling the HTML refresh:
62
- revalidationDelay: minutesToMilliseconds(0),
63
-
64
- compareVersionStrings: false, // Compares version strings of the new and previous assets and only triggers deployment, when the current is newer. The version must be the first group in the regex
65
- compareContentHashes: true,
66
-
67
- assetList: [
68
- ...getAssetList(),
69
-
70
- // TODO: add additional non-demandware asset urls as needed
71
- ],
72
- }
73
-
74
- function getQuery(assetRegex, origin) {
75
- const query = getBaseQuery(origin);
76
- query.url = { "$regex": assetRegex };
77
- return query;
78
- }
79
-
80
- function getBaseQuery(...origins) {
81
- return {
82
- "contentType": { "$in": ["script", "style"] },
83
- "variation": "DEFAULT",
84
- "origin": { "$in": origins },
85
- };
86
- }
87
-
88
- const DEPLOYMENT_REFRESH_JOB_ID_TEMPLATE = '/db/jobs.Definition/deployment-refresh'
89
- const DEPLOYMENT_CHECKER_JOB_ID = '/db/jobs.Definition/deployment-check'
90
- const MINUTE = 60 * 1000;
91
-
92
- exports.get = async function(db, req, res) {
93
- if (!db.User.me || db.User.me.key !== '1') {
94
- throw new Abort("Unauthorized");
95
- }
96
-
97
- const assetsByOrigin = {};
98
-
99
- for (const origin of deploymentConfig.origins) {
100
- assetsByOrigin[origin] = await Promise.all(deploymentConfig.assetList.map(async asset => {
101
- const { url } = await findAsset(db, asset, origin) || { url: null };
102
- return url;
103
- }))
104
- }
105
-
106
- res.json(assetsByOrigin);
107
- }
108
-
109
-
110
- exports.post = async function(db, req, res) {
111
- if (!db.User.me || db.User.me.key !== '1') {
112
- throw new Abort("Unauthorized");
113
- }
114
-
115
- const deploymentJobs = await Promise.all(deploymentConfig.origins.map(
116
- origin => createDeploymentJob(db, deploymentConfig, origin)));
117
-
118
- const deploymentChecker = await (new db['jobs.Definition']({
119
- id: DEPLOYMENT_CHECKER_JOB_ID,
120
- module: 'deploymentDetection',
121
- cronpattern: '42 */10 * * * *',
122
- startsAt: new Date(),
123
- }).save().catch(e => e.message));
124
-
125
- res.json({ deploymentChecker, deploymentJobs });
126
- }
127
-
128
- function getDeploymentJobId(origin) {
129
- const originWithoutSlashes = origin.replace(/https:/g, '').replace(/\//g, '');
130
- return `${DEPLOYMENT_REFRESH_JOB_ID_TEMPLATE}-${originWithoutSlashes}`;
131
- }
132
-
133
- function getDeploymentJobName(origin) {
134
- const originWithoutSlashes = origin.replace(/https:/g, '').replace(/\//g, '');
135
- return `Deployment ${originWithoutSlashes}`
136
- }
137
-
138
- function createDeploymentJob(db, deploymentConfig, origin) {
139
- return (new db['jobs.Definition']({
140
- id: getDeploymentJobId(origin),
141
- module: 'speedKit.CronJob',
142
- cronpattern: '*/60 */24 */30 */12 *',
143
- startsAt: new Date(),
144
- expiresAt: new Date(1970,0, 1),
145
- data: {
146
- "name": getDeploymentJobName(origin),
147
- "jobType": deploymentConfig.jobType || "deployment",
148
- "filter": {
149
- "contentTypes": [ "document" ],
150
- "origin": [ origin ],
151
- },
152
- "scheduleIn": deploymentConfig.deploymentDelay,
153
- "revalidationDelay": deploymentConfig.revalidationDelay,
154
- },
155
- }).save({ force: true }).catch(e => e.message));
156
- }
157
-
158
- exports.run = async function triggerRefreshAfterDeployment(db, status) {
159
- const interval = new Date(Date.now() - 10 * MINUTE - 10);
160
- const origins = await findNewAsset(db, interval, deploymentConfig.origins);
161
- const app = db.connection.host;
162
-
163
- if (origins.size === 0) {
164
- status.data = {refreshing: false, reason: "no new asset" };
165
- return;
166
- }
167
-
168
- const data = status.data = {};
169
- for (const origin of origins) {
170
- try {
171
- const changedAsset = await getChangedAssets(db, origin);
172
- if (!changedAsset) {
173
- data[origin] = {
174
- refreshing: false, origin, reason: "asset hash not changed",
175
- };
176
- continue;
177
- }
178
-
179
- const reason = `Asset changed: ${changedAsset}`;
180
- fetch(deploymentConfig.slack, {
181
- username: 'Deployment Detection',
182
- method: 'post',
183
- body: JSON.stringify({text: `Deployment on ${app} on ${origin} detected. Starting HTML ${deploymentConfig.jobType || "deployment"} Refresh. ${reason}`}),
184
- }).catch(db.log.warn);
185
-
186
- await runDeploymentJob(db, origin, reason);
187
-
188
- data[origin] = {
189
- refreshing: true, origin, latestAsset: changedAsset,
190
- };
191
- } catch (e) {
192
- fetch(deploymentConfig.slack, {
193
- username: 'Deployment Detection',
194
- method: 'post',
195
- body: JSON.stringify({text: `Deployment detection on ${app} and ${origin} failed. ${e.message}`}),
196
- }).catch(db.log.warn);
197
- data[origin] = {
198
- refreshing: false, origin, reason: e.stack,
199
- };
200
- }
201
- }
202
- return data;
203
- };
204
-
205
- async function getChangedAssets(db, origin) {
206
- for (const urlRegex of deploymentConfig.assetList) {
207
- const interval = new Date(Date.now() - 10 * MINUTE - 10);
208
- const current = await findAsset(db, urlRegex, origin, interval);
209
- const previous = await findAsset(db, urlRegex, origin, null, interval);
210
-
211
- if (!current) {
212
- continue;
213
- }
214
-
215
- // trigger deployment since we see a new matching asset
216
- if (!previous) {
217
- return current.url;
218
- }
219
-
220
- if (deploymentConfig.compareContentHashes) {
221
- if (current.contentHash === previous.contentHash) {
222
- continue;
223
- }
224
-
225
- if (await hasCachedAsset(db, current, urlRegex, interval)) {
226
- db.log.info('contentHash already known', {current, previous});
227
- continue;
228
- }
229
- }
230
-
231
- if (deploymentConfig.compareVersionStrings) {
232
- const prevVersion = previous.url.match(urlRegex)[1];
233
- const currentVersion = current.url.match(urlRegex)[1];
234
- if (currentVersion < prevVersion) {
235
- db.log.info('content version has not increased', {current, previous});
236
- continue;
237
- }
238
- }
239
-
240
- return current.url;
241
- }
242
-
243
- return false;
244
- }
245
-
246
- async function findAsset(db, urlRegex, origin, from, to) {
247
- return await db["speedKit.Asset"].find()
248
- .where(getQuery(urlRegex, origin))
249
- .le('createdAt', to || new Date(Date.now() + MINUTE))
250
- .gt('createdAt', from || new Date(1970, 0, 1))
251
- .descending('createdAt')
252
- .singleResult();
253
- }
254
-
255
- async function findNewAsset(db, from, origins) {
256
- const result = await db["speedKit.Asset"].find()
257
- .where(getBaseQuery(...origins))
258
- .gt('createdAt', from || new Date(1970, 0, 1))
259
- .resultList();
260
-
261
- return new Set(result.map(asset => asset.origin));
262
- }
263
-
264
- async function hasAssetChanged(asset1, asset2) {
265
- const res1 = await fetch(asset1.url);
266
- const text1 = await res1.text();
267
-
268
- const res2 = await fetch(asset2.url);
269
- const text2 = await res2.text();
270
-
271
- return text1 !== text2;
272
- }
273
-
274
- /**
275
- * Check whether we have seen the hash before
276
- */
277
- async function hasCachedAsset(db, asset, urlRegex, to) {
278
- return (await db["speedKit.Asset"].find()
279
- .where(getQuery(urlRegex, asset.origin))
280
- .equal('contentType', asset.contentType)
281
- .equal('variation', asset.variation)
282
- .equal('contentHash', asset.contentHash)
283
- .le('createdAt', to || new Date(Date.now() + MINUTE))
284
- .count()
285
- ) > 0;
286
- }
287
-
288
- async function runDeploymentJob(db, origin, reason) {
289
- const status = new db['jobs.Status']();
290
- const jobId = getDeploymentJobId(origin);
291
- const cronjob = await db['jobs.Definition'].load(jobId);
292
- // TODO: quite hacky right now we may need a way to pass additional parameters to the run job code
293
- cronjob.data.reason = reason;
294
- status.cronjob = cronjob;
295
-
296
- try {
297
- await executeRefresh(db, status, cronjob);
298
- } catch(error) {
299
- status.status = 'failed';
300
- status.error = error;
301
- await status.save();
302
- }
303
- }