@sitecore-jss/sitecore-jss-dev-tools 22.4.0-canary.2 → 22.4.0-canary.21
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/dist/cjs/package-deploy.js +161 -131
- package/dist/esm/package-deploy.js +159 -107
- package/package.json +3 -4
- package/types/package-deploy.d.ts +18 -24
|
@@ -1,27 +1,4 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
-
if (k2 === undefined) k2 = k;
|
|
4
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
-
}
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
-
}) : function(o, v) {
|
|
16
|
-
o["default"] = v;
|
|
17
|
-
});
|
|
18
|
-
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
-
if (mod && mod.__esModule) return mod;
|
|
20
|
-
var result = {};
|
|
21
|
-
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
-
__setModuleDefault(result, mod);
|
|
23
|
-
return result;
|
|
24
|
-
};
|
|
25
2
|
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
26
3
|
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
27
4
|
return new (P || (P = Promise))(function (resolve, reject) {
|
|
@@ -40,15 +17,16 @@ exports.normalizeFingerprint = normalizeFingerprint;
|
|
|
40
17
|
exports.doFingerprintsMatch = doFingerprintsMatch;
|
|
41
18
|
exports.finishWatchJobStatusTask = finishWatchJobStatusTask;
|
|
42
19
|
exports.logJobStatus = logJobStatus;
|
|
20
|
+
exports.watchJobStatus = watchJobStatus;
|
|
43
21
|
exports.packageDeploy = packageDeploy;
|
|
44
|
-
exports.
|
|
45
|
-
exports.
|
|
22
|
+
exports.setProxy = setProxy;
|
|
23
|
+
exports.attachFormDataHandlers = attachFormDataHandlers;
|
|
46
24
|
const chalk_1 = __importDefault(require("chalk"));
|
|
47
25
|
const fs_1 = __importDefault(require("fs"));
|
|
48
|
-
const https_1 =
|
|
26
|
+
const https_1 = __importDefault(require("https"));
|
|
27
|
+
const http_1 = __importDefault(require("http"));
|
|
49
28
|
const path_1 = __importDefault(require("path"));
|
|
50
29
|
const form_data_1 = __importDefault(require("form-data"));
|
|
51
|
-
const axios_1 = __importDefault(require("axios"));
|
|
52
30
|
const digest_1 = require("./digest");
|
|
53
31
|
// Node does not use system level trusted CAs. This causes issues because SIF likes to install
|
|
54
32
|
// using a Windows trusted CA - so SSL connections to Sitecore will fail from Node.
|
|
@@ -161,18 +139,21 @@ function watchJobStatus(options, taskName) {
|
|
|
161
139
|
const warnings = [];
|
|
162
140
|
const factors = [options.appName, taskName, `${options.importServiceUrl}/status`];
|
|
163
141
|
const mac = (0, digest_1.hmac)(factors, options.secret);
|
|
142
|
+
const url = new URL(`${options.importServiceUrl}/status?appName=${options.appName}&jobName=${taskName}&after=${logOffset}`);
|
|
164
143
|
const isHttps = options.importServiceUrl.startsWith('https');
|
|
165
|
-
const
|
|
166
|
-
|
|
144
|
+
const client = isHttps ? https_1.default : http_1.default;
|
|
145
|
+
const reqOptions = {
|
|
167
146
|
headers: {
|
|
168
147
|
'User-Agent': 'Sitecore/JSS-Import',
|
|
169
148
|
'Cache-Control': 'no-cache',
|
|
170
149
|
'X-JSS-Auth': mac,
|
|
171
150
|
},
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
151
|
+
method: 'GET',
|
|
152
|
+
hostname: url.hostname,
|
|
153
|
+
protocol: url.protocol,
|
|
154
|
+
path: url.pathname + url.search,
|
|
155
|
+
agent: isHttps
|
|
156
|
+
? new https_1.default.Agent({
|
|
176
157
|
// we turn off normal CA cert validation when we are whitelisting a single cert thumbprint
|
|
177
158
|
rejectUnauthorized: options.acceptCertificate ? false : true,
|
|
178
159
|
// needed to allow whitelisting a cert thumbprint if a connection is reused
|
|
@@ -184,60 +165,76 @@ function watchJobStatus(options, taskName) {
|
|
|
184
165
|
console.log(`Deployment status security factors: ${factors}`);
|
|
185
166
|
console.log(`Deployment status HMAC: ${mac}`);
|
|
186
167
|
}
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
let message = entry;
|
|
203
|
-
if (entryBits && entryBits[2]) {
|
|
204
|
-
entryLevel = entryBits[2];
|
|
205
|
-
// 3 = '[] ' in say [INFO] My log message
|
|
206
|
-
// we're not using the capture group as the message might be multi-line
|
|
207
|
-
message = entry.substring(entryLevel.length + 3);
|
|
208
|
-
}
|
|
209
|
-
if (message.startsWith('[JSS] - ')) {
|
|
210
|
-
message = message.substring(8);
|
|
211
|
-
}
|
|
212
|
-
logJobStatus({ message, entryLevel, warnings, errors });
|
|
213
|
-
});
|
|
214
|
-
if (state === 'Finished') {
|
|
215
|
-
finishWatchJobStatusTask({ warnings, errors, resolve, reject });
|
|
216
|
-
return;
|
|
217
|
-
}
|
|
218
|
-
setTimeout(sendJobStatusRequest, 1000);
|
|
219
|
-
}
|
|
220
|
-
catch (error) {
|
|
221
|
-
console.error(chalk_1.default.red(`Unexpected error processing reply from import status service: ${error}`));
|
|
222
|
-
console.error(chalk_1.default.red(`Response: ${body}`));
|
|
223
|
-
console.error(chalk_1.default.red('Consult the Sitecore logs for details.'));
|
|
224
|
-
reject(error);
|
|
225
|
-
}
|
|
226
|
-
})
|
|
227
|
-
.catch((error) => {
|
|
168
|
+
if (options.proxy) {
|
|
169
|
+
setProxy(reqOptions, options.proxy, options.importServiceUrl);
|
|
170
|
+
}
|
|
171
|
+
const req = client.request(reqOptions);
|
|
172
|
+
if (isHttps) {
|
|
173
|
+
applyCertPinning(req, options);
|
|
174
|
+
}
|
|
175
|
+
let responseData = '';
|
|
176
|
+
req.on('response', (res) => {
|
|
177
|
+
if (res.statusCode !== 200) {
|
|
178
|
+
let errorData = '';
|
|
179
|
+
res.on('data', (chunk) => {
|
|
180
|
+
errorData += chunk;
|
|
181
|
+
});
|
|
182
|
+
res.on('end', () => {
|
|
228
183
|
console.error(chalk_1.default.red('Unexpected response from import status service. The import task is probably still running; check the Sitecore logs for details.'));
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
}
|
|
233
|
-
else {
|
|
234
|
-
console.error(chalk_1.default.red(error.message));
|
|
235
|
-
}
|
|
236
|
-
reject();
|
|
184
|
+
console.error(chalk_1.default.red(`Status message: ${res.statusMessage}`));
|
|
185
|
+
console.error(chalk_1.default.red(`Status: ${res.statusCode}`));
|
|
186
|
+
process.exit(1);
|
|
237
187
|
});
|
|
188
|
+
return;
|
|
238
189
|
}
|
|
239
|
-
|
|
190
|
+
res.on('error', (err) => {
|
|
191
|
+
console.error(chalk_1.default.red('Unexpected response from import status service. The import task is probably still running; check the Sitecore logs for details.'));
|
|
192
|
+
console.error(chalk_1.default.red(`Status message: ${err.message}`));
|
|
193
|
+
console.error(chalk_1.default.red(`Status: ${res.statusCode}`));
|
|
194
|
+
process.exit(1);
|
|
195
|
+
});
|
|
196
|
+
res.on('data', (chunk) => {
|
|
197
|
+
responseData += chunk;
|
|
198
|
+
});
|
|
199
|
+
res.on('end', () => {
|
|
200
|
+
try {
|
|
201
|
+
const body = JSON.parse(responseData);
|
|
202
|
+
const { state, messages } = body;
|
|
203
|
+
messages.forEach((entry) => {
|
|
204
|
+
logOffset++;
|
|
205
|
+
const entryBits = /^(\[([A-Z]+)\] )?(.+)/.exec(entry);
|
|
206
|
+
let entryLevel = 'INFO';
|
|
207
|
+
let message = entry;
|
|
208
|
+
if (entryBits && entryBits[2]) {
|
|
209
|
+
entryLevel = entryBits[2];
|
|
210
|
+
// 3 = '[] ' in say [INFO] My log message
|
|
211
|
+
// we're not using the capture group as the message might be multi-line
|
|
212
|
+
message = entry.substring(entryLevel.length + 3);
|
|
213
|
+
}
|
|
214
|
+
if (message.startsWith('[JSS] - ')) {
|
|
215
|
+
message = message.substring(8);
|
|
216
|
+
}
|
|
217
|
+
logJobStatus({ message, entryLevel, warnings, errors });
|
|
218
|
+
});
|
|
219
|
+
if (state === 'Finished') {
|
|
220
|
+
finishWatchJobStatusTask({ warnings, errors, resolve: () => { }, reject: () => { } });
|
|
221
|
+
return;
|
|
222
|
+
}
|
|
223
|
+
setTimeout(() => watchJobStatus(options, taskName), 1000);
|
|
224
|
+
}
|
|
225
|
+
catch (error) {
|
|
226
|
+
console.error(chalk_1.default.red(`Unexpected error processing reply from import status service: ${error}`));
|
|
227
|
+
console.error(chalk_1.default.red(`Response: ${responseData}`));
|
|
228
|
+
console.error(chalk_1.default.red('Consult the Sitecore logs for details.'));
|
|
229
|
+
process.exit(1);
|
|
230
|
+
}
|
|
231
|
+
});
|
|
240
232
|
});
|
|
233
|
+
req.on('error', (err) => {
|
|
234
|
+
console.error(chalk_1.default.red(`Request error: ${err.message}`));
|
|
235
|
+
process.exit(1);
|
|
236
|
+
});
|
|
237
|
+
req.end();
|
|
241
238
|
});
|
|
242
239
|
}
|
|
243
240
|
/**
|
|
@@ -251,7 +248,7 @@ function packageDeploy(options) {
|
|
|
251
248
|
if (options.secret.length < 32) {
|
|
252
249
|
throw new Error('Deployment secret was too short. Use a RANDOM (not words or phrases) secret at least 32 characters long.');
|
|
253
250
|
}
|
|
254
|
-
let packageFile =
|
|
251
|
+
let packageFile = '';
|
|
255
252
|
fs_1.default.readdirSync(options.packagePath).forEach((file) => {
|
|
256
253
|
if (file.startsWith(options.appName) && file.endsWith('.manifest.zip')) {
|
|
257
254
|
packageFile = path_1.default.join(options.packagePath, file);
|
|
@@ -268,60 +265,84 @@ function packageDeploy(options) {
|
|
|
268
265
|
console.log(`Deployment HMAC: ${(0, digest_1.hmac)(factors, options.secret)}`);
|
|
269
266
|
}
|
|
270
267
|
const formData = new form_data_1.default();
|
|
271
|
-
|
|
268
|
+
const fileStream = fs_1.default.createReadStream(packageFile);
|
|
269
|
+
const url = new URL(options.importServiceUrl);
|
|
272
270
|
formData.append('appName', options.appName);
|
|
271
|
+
formData.append('path', fileStream);
|
|
273
272
|
const isHttps = options.importServiceUrl.startsWith('https');
|
|
274
|
-
const
|
|
275
|
-
|
|
273
|
+
const client = isHttps ? https_1.default : http_1.default;
|
|
274
|
+
const reqOptions = {
|
|
276
275
|
headers: Object.assign({ 'User-Agent': 'Sitecore/JSS-Import', 'Cache-Control': 'no-cache', 'X-JSS-Auth': (0, digest_1.hmac)(factors, options.secret) }, formData.getHeaders()),
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
276
|
+
method: 'POST',
|
|
277
|
+
hostname: url.hostname,
|
|
278
|
+
protocol: url.protocol,
|
|
279
|
+
path: url.pathname,
|
|
280
|
+
agent: isHttps
|
|
281
|
+
? new https_1.default.Agent({
|
|
280
282
|
// we turn off normal CA cert validation when we are whitelisting a single cert thumbprint
|
|
281
283
|
rejectUnauthorized: options.acceptCertificate ? false : true,
|
|
282
284
|
// needed to allow whitelisting a cert thumbprint if a connection is reused
|
|
283
285
|
maxCachedSessions: options.acceptCertificate ? 0 : undefined,
|
|
284
286
|
})
|
|
285
287
|
: undefined,
|
|
286
|
-
maxRedirects: 0,
|
|
287
288
|
};
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
}
|
|
303
|
-
|
|
304
|
-
console.error(chalk_1.default.red(
|
|
305
|
-
|
|
306
|
-
|
|
289
|
+
if (options.proxy) {
|
|
290
|
+
setProxy(reqOptions, options.proxy, options.importServiceUrl);
|
|
291
|
+
}
|
|
292
|
+
const req = client.request(reqOptions);
|
|
293
|
+
if (https_1.default) {
|
|
294
|
+
applyCertPinning(req, options);
|
|
295
|
+
}
|
|
296
|
+
attachFormDataHandlers(req, formData);
|
|
297
|
+
formData.pipe(req);
|
|
298
|
+
req.on('response', (res) => {
|
|
299
|
+
if (res.statusCode !== 200) {
|
|
300
|
+
let errorData = '';
|
|
301
|
+
res.on('data', (chunk) => {
|
|
302
|
+
errorData += chunk;
|
|
303
|
+
});
|
|
304
|
+
res.on('end', () => {
|
|
305
|
+
console.error(chalk_1.default.red(`Error while uploading package: ${res.statusCode} ${res.statusMessage}`));
|
|
306
|
+
console.error(chalk_1.default.red(errorData));
|
|
307
|
+
process.exit(1);
|
|
308
|
+
});
|
|
309
|
+
return;
|
|
310
|
+
}
|
|
311
|
+
let responseData = '';
|
|
312
|
+
res.on('error', (err) => {
|
|
313
|
+
console.error(chalk_1.default.red(`Response error when uploading package: ${err.message}`));
|
|
314
|
+
process.exit(1);
|
|
315
|
+
});
|
|
316
|
+
res.on('data', (chunk) => {
|
|
317
|
+
responseData += chunk;
|
|
307
318
|
});
|
|
308
|
-
|
|
319
|
+
res.on('end', () => {
|
|
320
|
+
const taskName = responseData;
|
|
321
|
+
console.log('we are in packageDeploy', responseData);
|
|
322
|
+
console.log(chalk_1.default.green(`Package uploaded. Import task name: ${taskName}`));
|
|
323
|
+
watchJobStatus(options, taskName);
|
|
324
|
+
});
|
|
325
|
+
});
|
|
326
|
+
req.on('error', (err) => {
|
|
327
|
+
console.error(chalk_1.default.red(`Error while uploading package: ${err.message}`));
|
|
328
|
+
process.exit(1);
|
|
329
|
+
});
|
|
309
330
|
});
|
|
310
331
|
}
|
|
311
332
|
/**
|
|
312
|
-
* Creates valid proxy object
|
|
313
|
-
* @param {
|
|
333
|
+
* Creates valid proxy object
|
|
334
|
+
* @param {RequestOptions} reqOptions
|
|
335
|
+
* @param {string} proxy proxy url
|
|
336
|
+
* @param {string} targetUrl target url
|
|
314
337
|
*/
|
|
315
|
-
function
|
|
316
|
-
if (!proxy)
|
|
317
|
-
return undefined;
|
|
338
|
+
function setProxy(reqOptions, proxy, targetUrl) {
|
|
318
339
|
try {
|
|
319
340
|
const proxyUrl = new URL(proxy);
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
};
|
|
341
|
+
reqOptions.hostname = proxyUrl.hostname;
|
|
342
|
+
reqOptions.port = proxyUrl.port || (proxyUrl.protocol === 'https:' ? '443' : '80');
|
|
343
|
+
reqOptions.protocol = proxyUrl.protocol;
|
|
344
|
+
reqOptions.path = targetUrl;
|
|
345
|
+
reqOptions.headers = Object.assign(Object.assign({}, reqOptions.headers), { Host: new URL(targetUrl).hostname });
|
|
325
346
|
}
|
|
326
347
|
catch (error) {
|
|
327
348
|
console.error(chalk_1.default.red(`Invalid proxy url provided ${proxy}`));
|
|
@@ -329,15 +350,24 @@ function extractProxy(proxy) {
|
|
|
329
350
|
}
|
|
330
351
|
}
|
|
331
352
|
/**
|
|
332
|
-
*
|
|
333
|
-
*
|
|
334
|
-
*
|
|
335
|
-
* @param {PackageDeployOptions} options
|
|
353
|
+
* Attach form data handlers to handle errors and close events
|
|
354
|
+
* @param {ClientRequest} req request object
|
|
355
|
+
* @param {FormData} formData FormData object
|
|
336
356
|
*/
|
|
337
|
-
function
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
357
|
+
function attachFormDataHandlers(req, formData) {
|
|
358
|
+
let ended = false;
|
|
359
|
+
let errored = false;
|
|
360
|
+
formData.on('end', () => {
|
|
361
|
+
ended = true;
|
|
362
|
+
});
|
|
363
|
+
formData.once('error', (err) => {
|
|
364
|
+
errored = true;
|
|
365
|
+
console.log('Error when uploading package:', err);
|
|
366
|
+
req.destroy(err);
|
|
367
|
+
});
|
|
368
|
+
formData.on('close', () => {
|
|
369
|
+
if (!ended && !errored) {
|
|
370
|
+
new Error('Request stream has been aborted');
|
|
371
|
+
}
|
|
372
|
+
});
|
|
343
373
|
}
|
|
@@ -9,10 +9,10 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
9
9
|
};
|
|
10
10
|
import chalk from 'chalk';
|
|
11
11
|
import fs from 'fs';
|
|
12
|
-
import https
|
|
12
|
+
import https from 'https';
|
|
13
|
+
import http from 'http';
|
|
13
14
|
import path from 'path';
|
|
14
15
|
import FormData from 'form-data';
|
|
15
|
-
import axios from 'axios';
|
|
16
16
|
import { digest, hmac } from './digest';
|
|
17
17
|
// Node does not use system level trusted CAs. This causes issues because SIF likes to install
|
|
18
18
|
// using a Windows trusted CA - so SSL connections to Sitecore will fail from Node.
|
|
@@ -118,25 +118,28 @@ export function logJobStatus({ message, entryLevel, warnings, errors, }) {
|
|
|
118
118
|
* @param {PackageDeployOptions} options
|
|
119
119
|
* @param {string} taskName
|
|
120
120
|
*/
|
|
121
|
-
function watchJobStatus(options, taskName) {
|
|
121
|
+
export function watchJobStatus(options, taskName) {
|
|
122
122
|
return __awaiter(this, void 0, void 0, function* () {
|
|
123
123
|
let logOffset = 0;
|
|
124
124
|
const errors = [];
|
|
125
125
|
const warnings = [];
|
|
126
126
|
const factors = [options.appName, taskName, `${options.importServiceUrl}/status`];
|
|
127
127
|
const mac = hmac(factors, options.secret);
|
|
128
|
+
const url = new URL(`${options.importServiceUrl}/status?appName=${options.appName}&jobName=${taskName}&after=${logOffset}`);
|
|
128
129
|
const isHttps = options.importServiceUrl.startsWith('https');
|
|
129
|
-
const
|
|
130
|
-
|
|
130
|
+
const client = isHttps ? https : http;
|
|
131
|
+
const reqOptions = {
|
|
131
132
|
headers: {
|
|
132
133
|
'User-Agent': 'Sitecore/JSS-Import',
|
|
133
134
|
'Cache-Control': 'no-cache',
|
|
134
135
|
'X-JSS-Auth': mac,
|
|
135
136
|
},
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
137
|
+
method: 'GET',
|
|
138
|
+
hostname: url.hostname,
|
|
139
|
+
protocol: url.protocol,
|
|
140
|
+
path: url.pathname + url.search,
|
|
141
|
+
agent: isHttps
|
|
142
|
+
? new https.Agent({
|
|
140
143
|
// we turn off normal CA cert validation when we are whitelisting a single cert thumbprint
|
|
141
144
|
rejectUnauthorized: options.acceptCertificate ? false : true,
|
|
142
145
|
// needed to allow whitelisting a cert thumbprint if a connection is reused
|
|
@@ -148,60 +151,76 @@ function watchJobStatus(options, taskName) {
|
|
|
148
151
|
console.log(`Deployment status security factors: ${factors}`);
|
|
149
152
|
console.log(`Deployment status HMAC: ${mac}`);
|
|
150
153
|
}
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
let message = entry;
|
|
167
|
-
if (entryBits && entryBits[2]) {
|
|
168
|
-
entryLevel = entryBits[2];
|
|
169
|
-
// 3 = '[] ' in say [INFO] My log message
|
|
170
|
-
// we're not using the capture group as the message might be multi-line
|
|
171
|
-
message = entry.substring(entryLevel.length + 3);
|
|
172
|
-
}
|
|
173
|
-
if (message.startsWith('[JSS] - ')) {
|
|
174
|
-
message = message.substring(8);
|
|
175
|
-
}
|
|
176
|
-
logJobStatus({ message, entryLevel, warnings, errors });
|
|
177
|
-
});
|
|
178
|
-
if (state === 'Finished') {
|
|
179
|
-
finishWatchJobStatusTask({ warnings, errors, resolve, reject });
|
|
180
|
-
return;
|
|
181
|
-
}
|
|
182
|
-
setTimeout(sendJobStatusRequest, 1000);
|
|
183
|
-
}
|
|
184
|
-
catch (error) {
|
|
185
|
-
console.error(chalk.red(`Unexpected error processing reply from import status service: ${error}`));
|
|
186
|
-
console.error(chalk.red(`Response: ${body}`));
|
|
187
|
-
console.error(chalk.red('Consult the Sitecore logs for details.'));
|
|
188
|
-
reject(error);
|
|
189
|
-
}
|
|
190
|
-
})
|
|
191
|
-
.catch((error) => {
|
|
154
|
+
if (options.proxy) {
|
|
155
|
+
setProxy(reqOptions, options.proxy, options.importServiceUrl);
|
|
156
|
+
}
|
|
157
|
+
const req = client.request(reqOptions);
|
|
158
|
+
if (isHttps) {
|
|
159
|
+
applyCertPinning(req, options);
|
|
160
|
+
}
|
|
161
|
+
let responseData = '';
|
|
162
|
+
req.on('response', (res) => {
|
|
163
|
+
if (res.statusCode !== 200) {
|
|
164
|
+
let errorData = '';
|
|
165
|
+
res.on('data', (chunk) => {
|
|
166
|
+
errorData += chunk;
|
|
167
|
+
});
|
|
168
|
+
res.on('end', () => {
|
|
192
169
|
console.error(chalk.red('Unexpected response from import status service. The import task is probably still running; check the Sitecore logs for details.'));
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
}
|
|
197
|
-
else {
|
|
198
|
-
console.error(chalk.red(error.message));
|
|
199
|
-
}
|
|
200
|
-
reject();
|
|
170
|
+
console.error(chalk.red(`Status message: ${res.statusMessage}`));
|
|
171
|
+
console.error(chalk.red(`Status: ${res.statusCode}`));
|
|
172
|
+
process.exit(1);
|
|
201
173
|
});
|
|
174
|
+
return;
|
|
202
175
|
}
|
|
203
|
-
|
|
176
|
+
res.on('error', (err) => {
|
|
177
|
+
console.error(chalk.red('Unexpected response from import status service. The import task is probably still running; check the Sitecore logs for details.'));
|
|
178
|
+
console.error(chalk.red(`Status message: ${err.message}`));
|
|
179
|
+
console.error(chalk.red(`Status: ${res.statusCode}`));
|
|
180
|
+
process.exit(1);
|
|
181
|
+
});
|
|
182
|
+
res.on('data', (chunk) => {
|
|
183
|
+
responseData += chunk;
|
|
184
|
+
});
|
|
185
|
+
res.on('end', () => {
|
|
186
|
+
try {
|
|
187
|
+
const body = JSON.parse(responseData);
|
|
188
|
+
const { state, messages } = body;
|
|
189
|
+
messages.forEach((entry) => {
|
|
190
|
+
logOffset++;
|
|
191
|
+
const entryBits = /^(\[([A-Z]+)\] )?(.+)/.exec(entry);
|
|
192
|
+
let entryLevel = 'INFO';
|
|
193
|
+
let message = entry;
|
|
194
|
+
if (entryBits && entryBits[2]) {
|
|
195
|
+
entryLevel = entryBits[2];
|
|
196
|
+
// 3 = '[] ' in say [INFO] My log message
|
|
197
|
+
// we're not using the capture group as the message might be multi-line
|
|
198
|
+
message = entry.substring(entryLevel.length + 3);
|
|
199
|
+
}
|
|
200
|
+
if (message.startsWith('[JSS] - ')) {
|
|
201
|
+
message = message.substring(8);
|
|
202
|
+
}
|
|
203
|
+
logJobStatus({ message, entryLevel, warnings, errors });
|
|
204
|
+
});
|
|
205
|
+
if (state === 'Finished') {
|
|
206
|
+
finishWatchJobStatusTask({ warnings, errors, resolve: () => { }, reject: () => { } });
|
|
207
|
+
return;
|
|
208
|
+
}
|
|
209
|
+
setTimeout(() => watchJobStatus(options, taskName), 1000);
|
|
210
|
+
}
|
|
211
|
+
catch (error) {
|
|
212
|
+
console.error(chalk.red(`Unexpected error processing reply from import status service: ${error}`));
|
|
213
|
+
console.error(chalk.red(`Response: ${responseData}`));
|
|
214
|
+
console.error(chalk.red('Consult the Sitecore logs for details.'));
|
|
215
|
+
process.exit(1);
|
|
216
|
+
}
|
|
217
|
+
});
|
|
218
|
+
});
|
|
219
|
+
req.on('error', (err) => {
|
|
220
|
+
console.error(chalk.red(`Request error: ${err.message}`));
|
|
221
|
+
process.exit(1);
|
|
204
222
|
});
|
|
223
|
+
req.end();
|
|
205
224
|
});
|
|
206
225
|
}
|
|
207
226
|
/**
|
|
@@ -215,7 +234,7 @@ export function packageDeploy(options) {
|
|
|
215
234
|
if (options.secret.length < 32) {
|
|
216
235
|
throw new Error('Deployment secret was too short. Use a RANDOM (not words or phrases) secret at least 32 characters long.');
|
|
217
236
|
}
|
|
218
|
-
let packageFile =
|
|
237
|
+
let packageFile = '';
|
|
219
238
|
fs.readdirSync(options.packagePath).forEach((file) => {
|
|
220
239
|
if (file.startsWith(options.appName) && file.endsWith('.manifest.zip')) {
|
|
221
240
|
packageFile = path.join(options.packagePath, file);
|
|
@@ -232,60 +251,84 @@ export function packageDeploy(options) {
|
|
|
232
251
|
console.log(`Deployment HMAC: ${hmac(factors, options.secret)}`);
|
|
233
252
|
}
|
|
234
253
|
const formData = new FormData();
|
|
235
|
-
|
|
254
|
+
const fileStream = fs.createReadStream(packageFile);
|
|
255
|
+
const url = new URL(options.importServiceUrl);
|
|
236
256
|
formData.append('appName', options.appName);
|
|
257
|
+
formData.append('path', fileStream);
|
|
237
258
|
const isHttps = options.importServiceUrl.startsWith('https');
|
|
238
|
-
const
|
|
239
|
-
|
|
259
|
+
const client = isHttps ? https : http;
|
|
260
|
+
const reqOptions = {
|
|
240
261
|
headers: Object.assign({ 'User-Agent': 'Sitecore/JSS-Import', 'Cache-Control': 'no-cache', 'X-JSS-Auth': hmac(factors, options.secret) }, formData.getHeaders()),
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
262
|
+
method: 'POST',
|
|
263
|
+
hostname: url.hostname,
|
|
264
|
+
protocol: url.protocol,
|
|
265
|
+
path: url.pathname,
|
|
266
|
+
agent: isHttps
|
|
267
|
+
? new https.Agent({
|
|
244
268
|
// we turn off normal CA cert validation when we are whitelisting a single cert thumbprint
|
|
245
269
|
rejectUnauthorized: options.acceptCertificate ? false : true,
|
|
246
270
|
// needed to allow whitelisting a cert thumbprint if a connection is reused
|
|
247
271
|
maxCachedSessions: options.acceptCertificate ? 0 : undefined,
|
|
248
272
|
})
|
|
249
273
|
: undefined,
|
|
250
|
-
maxRedirects: 0,
|
|
251
274
|
};
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
}
|
|
267
|
-
|
|
268
|
-
console.error(chalk.red(
|
|
269
|
-
|
|
270
|
-
|
|
275
|
+
if (options.proxy) {
|
|
276
|
+
setProxy(reqOptions, options.proxy, options.importServiceUrl);
|
|
277
|
+
}
|
|
278
|
+
const req = client.request(reqOptions);
|
|
279
|
+
if (https) {
|
|
280
|
+
applyCertPinning(req, options);
|
|
281
|
+
}
|
|
282
|
+
attachFormDataHandlers(req, formData);
|
|
283
|
+
formData.pipe(req);
|
|
284
|
+
req.on('response', (res) => {
|
|
285
|
+
if (res.statusCode !== 200) {
|
|
286
|
+
let errorData = '';
|
|
287
|
+
res.on('data', (chunk) => {
|
|
288
|
+
errorData += chunk;
|
|
289
|
+
});
|
|
290
|
+
res.on('end', () => {
|
|
291
|
+
console.error(chalk.red(`Error while uploading package: ${res.statusCode} ${res.statusMessage}`));
|
|
292
|
+
console.error(chalk.red(errorData));
|
|
293
|
+
process.exit(1);
|
|
294
|
+
});
|
|
295
|
+
return;
|
|
296
|
+
}
|
|
297
|
+
let responseData = '';
|
|
298
|
+
res.on('error', (err) => {
|
|
299
|
+
console.error(chalk.red(`Response error when uploading package: ${err.message}`));
|
|
300
|
+
process.exit(1);
|
|
301
|
+
});
|
|
302
|
+
res.on('data', (chunk) => {
|
|
303
|
+
responseData += chunk;
|
|
304
|
+
});
|
|
305
|
+
res.on('end', () => {
|
|
306
|
+
const taskName = responseData;
|
|
307
|
+
console.log('we are in packageDeploy', responseData);
|
|
308
|
+
console.log(chalk.green(`Package uploaded. Import task name: ${taskName}`));
|
|
309
|
+
watchJobStatus(options, taskName);
|
|
271
310
|
});
|
|
272
|
-
})
|
|
311
|
+
});
|
|
312
|
+
req.on('error', (err) => {
|
|
313
|
+
console.error(chalk.red(`Error while uploading package: ${err.message}`));
|
|
314
|
+
process.exit(1);
|
|
315
|
+
});
|
|
273
316
|
});
|
|
274
317
|
}
|
|
275
318
|
/**
|
|
276
|
-
* Creates valid proxy object
|
|
277
|
-
* @param {
|
|
319
|
+
* Creates valid proxy object
|
|
320
|
+
* @param {RequestOptions} reqOptions
|
|
321
|
+
* @param {string} proxy proxy url
|
|
322
|
+
* @param {string} targetUrl target url
|
|
278
323
|
*/
|
|
279
|
-
export function
|
|
280
|
-
if (!proxy)
|
|
281
|
-
return undefined;
|
|
324
|
+
export function setProxy(reqOptions, proxy, targetUrl) {
|
|
282
325
|
try {
|
|
283
326
|
const proxyUrl = new URL(proxy);
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
};
|
|
327
|
+
reqOptions.hostname = proxyUrl.hostname;
|
|
328
|
+
reqOptions.port = proxyUrl.port || (proxyUrl.protocol === 'https:' ? '443' : '80');
|
|
329
|
+
reqOptions.protocol = proxyUrl.protocol;
|
|
330
|
+
reqOptions.path = targetUrl;
|
|
331
|
+
reqOptions.headers = Object.assign(Object.assign({}, reqOptions.headers), { Host: new URL(targetUrl).hostname });
|
|
289
332
|
}
|
|
290
333
|
catch (error) {
|
|
291
334
|
console.error(chalk.red(`Invalid proxy url provided ${proxy}`));
|
|
@@ -293,15 +336,24 @@ export function extractProxy(proxy) {
|
|
|
293
336
|
}
|
|
294
337
|
}
|
|
295
338
|
/**
|
|
296
|
-
*
|
|
297
|
-
*
|
|
298
|
-
*
|
|
299
|
-
* @param {PackageDeployOptions} options
|
|
339
|
+
* Attach form data handlers to handle errors and close events
|
|
340
|
+
* @param {ClientRequest} req request object
|
|
341
|
+
* @param {FormData} formData FormData object
|
|
300
342
|
*/
|
|
301
|
-
export function
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
343
|
+
export function attachFormDataHandlers(req, formData) {
|
|
344
|
+
let ended = false;
|
|
345
|
+
let errored = false;
|
|
346
|
+
formData.on('end', () => {
|
|
347
|
+
ended = true;
|
|
348
|
+
});
|
|
349
|
+
formData.once('error', (err) => {
|
|
350
|
+
errored = true;
|
|
351
|
+
console.log('Error when uploading package:', err);
|
|
352
|
+
req.destroy(err);
|
|
353
|
+
});
|
|
354
|
+
formData.on('close', () => {
|
|
355
|
+
if (!ended && !errored) {
|
|
356
|
+
new Error('Request stream has been aborted');
|
|
357
|
+
}
|
|
358
|
+
});
|
|
307
359
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sitecore-jss/sitecore-jss-dev-tools",
|
|
3
|
-
"version": "22.4.0-canary.
|
|
3
|
+
"version": "22.4.0-canary.21",
|
|
4
4
|
"description": "Utilities to assist in the development and deployment of Sitecore JSS apps.",
|
|
5
5
|
"main": "dist/cjs/index.js",
|
|
6
6
|
"module": "dist/esm/index.js",
|
|
@@ -33,8 +33,7 @@
|
|
|
33
33
|
},
|
|
34
34
|
"dependencies": {
|
|
35
35
|
"@babel/parser": "^7.24.0",
|
|
36
|
-
"@sitecore-jss/sitecore-jss": "^22.4.0-canary.
|
|
37
|
-
"axios": "^1.3.2",
|
|
36
|
+
"@sitecore-jss/sitecore-jss": "^22.4.0-canary.21",
|
|
38
37
|
"chalk": "^4.1.2",
|
|
39
38
|
"chokidar": "^3.6.0",
|
|
40
39
|
"del": "^6.0.0",
|
|
@@ -86,7 +85,7 @@
|
|
|
86
85
|
"typescript": "~5.6.3"
|
|
87
86
|
},
|
|
88
87
|
"types": "types/index.d.ts",
|
|
89
|
-
"gitHead": "
|
|
88
|
+
"gitHead": "f0cf339eadfbdd0f56e58b1c4c83c0b1ccd7d8a6",
|
|
90
89
|
"files": [
|
|
91
90
|
"dist",
|
|
92
91
|
"types",
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
1
|
+
import { RequestOptions } from 'https';
|
|
2
|
+
import FormData from 'form-data';
|
|
3
|
+
import { ClientRequest } from 'http';
|
|
3
4
|
export interface PackageDeployOptions {
|
|
4
5
|
packagePath: string;
|
|
5
6
|
appName: string;
|
|
@@ -51,30 +52,23 @@ export declare function logJobStatus({ message, entryLevel, warnings, errors, }:
|
|
|
51
52
|
}): void;
|
|
52
53
|
/**
|
|
53
54
|
* @param {PackageDeployOptions} options
|
|
55
|
+
* @param {string} taskName
|
|
54
56
|
*/
|
|
55
|
-
export declare function
|
|
57
|
+
export declare function watchJobStatus(options: PackageDeployOptions, taskName: string): Promise<void>;
|
|
56
58
|
/**
|
|
57
|
-
*
|
|
58
|
-
* @param {string} [proxy] proxy url
|
|
59
|
+
* @param {PackageDeployOptions} options
|
|
59
60
|
*/
|
|
60
|
-
export declare function
|
|
61
|
-
protocol: string;
|
|
62
|
-
host: string;
|
|
63
|
-
port: number;
|
|
64
|
-
} | undefined;
|
|
61
|
+
export declare function packageDeploy(options: PackageDeployOptions): Promise<void>;
|
|
65
62
|
/**
|
|
66
|
-
*
|
|
67
|
-
*
|
|
68
|
-
*
|
|
69
|
-
* @param {
|
|
63
|
+
* Creates valid proxy object
|
|
64
|
+
* @param {RequestOptions} reqOptions
|
|
65
|
+
* @param {string} proxy proxy url
|
|
66
|
+
* @param {string} targetUrl target url
|
|
67
|
+
*/
|
|
68
|
+
export declare function setProxy(reqOptions: RequestOptions, proxy: string, targetUrl: string): void;
|
|
69
|
+
/**
|
|
70
|
+
* Attach form data handlers to handle errors and close events
|
|
71
|
+
* @param {ClientRequest} req request object
|
|
72
|
+
* @param {FormData} formData FormData object
|
|
70
73
|
*/
|
|
71
|
-
export declare function
|
|
72
|
-
request: (reqOptions: https.RequestOptions, callback: (res: IncomingMessage) => void) => ClientRequest;
|
|
73
|
-
createServer<Request extends typeof IncomingMessage = typeof IncomingMessage, Response extends typeof import("http").ServerResponse = typeof import("http").ServerResponse>(requestListener?: import("http").RequestListener<Request, Response>): https.Server<Request, Response>;
|
|
74
|
-
createServer<Request extends typeof IncomingMessage = typeof IncomingMessage, Response extends typeof import("http").ServerResponse = typeof import("http").ServerResponse>(options: https.ServerOptions<Request, Response>, requestListener?: import("http").RequestListener<Request, Response>): https.Server<Request, Response>;
|
|
75
|
-
get(options: https.RequestOptions | string | import("url").URL, callback?: (res: IncomingMessage) => void): ClientRequest;
|
|
76
|
-
get(url: string | import("url").URL, options: https.RequestOptions, callback?: (res: IncomingMessage) => void): ClientRequest;
|
|
77
|
-
Agent: typeof https.Agent;
|
|
78
|
-
Server: typeof https.Server;
|
|
79
|
-
globalAgent: https.Agent;
|
|
80
|
-
};
|
|
74
|
+
export declare function attachFormDataHandlers(req: ClientRequest, formData: FormData): void;
|