@squiz/dxp-cli-next 5.9.0-develop.44 → 5.9.0-develop.46

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.
@@ -16,7 +16,7 @@ const nock_1 = __importDefault(require("nock"));
16
16
  const add_1 = __importDefault(require("./add"));
17
17
  const utils_1 = require("../../utils");
18
18
  const logSpy = jest.spyOn(global.console, 'log');
19
- describe('listJobContexts', () => {
19
+ describe('datastoreBlueprintAdd', () => {
20
20
  process.env.ENABLE_OVERRIDE_DATASTORE_URL = 'true';
21
21
  it('correctly adds a blueprint', () => __awaiter(void 0, void 0, void 0, function* () {
22
22
  (0, nock_1.default)('http://localhost:9999')
@@ -15,7 +15,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
15
15
  const nock_1 = __importDefault(require("nock"));
16
16
  const list_1 = __importDefault(require("./list"));
17
17
  const logSpy = jest.spyOn(global.console, 'log');
18
- describe('listJobContexts', () => {
18
+ describe('datastoreBlueprintList', () => {
19
19
  process.env.ENABLE_OVERRIDE_DATASTORE_URL = 'true';
20
20
  it('correctly lists all the blueprint', () => __awaiter(void 0, void 0, void 0, function* () {
21
21
  (0, nock_1.default)('http://localhost:9999')
@@ -16,7 +16,7 @@ const nock_1 = __importDefault(require("nock"));
16
16
  const rename_1 = __importDefault(require("./rename"));
17
17
  const utils_1 = require("../../utils");
18
18
  const logSpy = jest.spyOn(global.console, 'log');
19
- describe('renameJobContexts', () => {
19
+ describe('datastoreBlueprintRename', () => {
20
20
  process.env.ENABLE_OVERRIDE_DATASTORE_URL = 'true';
21
21
  it('correctly renames a blueprint', () => __awaiter(void 0, void 0, void 0, function* () {
22
22
  (0, nock_1.default)('http://localhost:9999')
@@ -16,7 +16,7 @@ const nock_1 = __importDefault(require("nock"));
16
16
  const update_1 = __importDefault(require("./update"));
17
17
  const utils_1 = require("../../utils");
18
18
  const logSpy = jest.spyOn(global.console, 'log');
19
- describe('listJobContexts', () => {
19
+ describe('datastoreBlueprintUpdate', () => {
20
20
  process.env.ENABLE_OVERRIDE_DATASTORE_URL = 'true';
21
21
  it('correctly adds a blueprint', () => __awaiter(void 0, void 0, void 0, function* () {
22
22
  (0, nock_1.default)('http://localhost:9999')
@@ -6,9 +6,11 @@ Object.defineProperty(exports, "__esModule", { value: true });
6
6
  const commander_1 = require("commander");
7
7
  const blueprintCommand_1 = __importDefault(require("./blueprint/blueprintCommand"));
8
8
  const bundle_1 = __importDefault(require("./bundle/bundle"));
9
+ const simulatorCommand_1 = __importDefault(require("./simulator/simulatorCommand"));
9
10
  const datastoreCommand = new commander_1.Command('datastore');
10
11
  datastoreCommand
11
12
  .description('Datastore Commands')
12
13
  .addCommand((0, blueprintCommand_1.default)())
13
- .addCommand((0, bundle_1.default)());
14
+ .addCommand((0, bundle_1.default)())
15
+ .addCommand((0, simulatorCommand_1.default)());
14
16
  exports.default = datastoreCommand;
@@ -0,0 +1,3 @@
1
+ import { Command } from 'commander';
2
+ declare const createAddCommand: () => Command;
3
+ export default createAddCommand;
@@ -0,0 +1,138 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ var __importDefault = (this && this.__importDefault) || function (mod) {
12
+ return (mod && mod.__esModule) ? mod : { "default": mod };
13
+ };
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ const commander_1 = require("commander");
16
+ const chalk_1 = __importDefault(require("chalk"));
17
+ const ora_1 = __importDefault(require("ora"));
18
+ const utils_1 = require("../../utils");
19
+ const utils_2 = require("../utils");
20
+ const path_1 = require("path");
21
+ const fs_1 = __importDefault(require("fs"));
22
+ const createAddCommand = () => {
23
+ const addCommand = new commander_1.Command('add')
24
+ .name('add')
25
+ .description('Adds a new simulator')
26
+ .addOption(new commander_1.Option('-p, --port <string>', 'Port for the Datastore simulator to run on'))
27
+ .addOption(new commander_1.Option('-b, --blueprint <string>', 'Path to your datastore API yaml file.').makeOptionMandatory())
28
+ .configureOutput({
29
+ outputError(str, write) {
30
+ write(chalk_1.default.red(str));
31
+ },
32
+ })
33
+ .action((options) => __awaiter(void 0, void 0, void 0, function* () {
34
+ console.log('');
35
+ const spinner = (0, ora_1.default)();
36
+ try {
37
+ yield (0, utils_2.checkUpdateAvailable)();
38
+ spinner.start('Creating a new simulator container.');
39
+ yield (0, utils_2.checkDockerInstalled)();
40
+ const { fullPath, dirPath, yamlFile, containerName } = (0, utils_2.getSimulatorDetails)(options.blueprint);
41
+ const fileCheck = fs_1.default.existsSync(fullPath);
42
+ let errorMsg = 'There was an error starting simulator. Ask for help in our support forums.';
43
+ if (fileCheck === false) {
44
+ throw new Error('Sorry, we could not create your simulator container. Please try again using a valid path to a blueprint.');
45
+ }
46
+ else {
47
+ let fileExt = (0, path_1.extname)(fullPath);
48
+ if (fileExt.indexOf('.') === 0) {
49
+ fileExt = fileExt.replace('.', '');
50
+ }
51
+ if (utils_2.allowedExtensions.includes(fileExt) === false) {
52
+ errorMsg = 'Sorry, we could not create your simulator container.';
53
+ errorMsg += ` Please try again using a valid path to a blueprint. Valid extensions are: ${utils_2.allowedExtensions.join(', ')}`;
54
+ throw new Error(errorMsg);
55
+ }
56
+ }
57
+ const versionDetails = {
58
+ digest: '',
59
+ version: '',
60
+ };
61
+ // Find an available port.
62
+ const usedPorts = yield (0, utils_2.executeCommand)('docker ps -a --format "~{{.Labels}}~" --filter "name=datastore-sim-*"');
63
+ let selectedPort = '';
64
+ if (options.port) {
65
+ selectedPort = options.port;
66
+ }
67
+ else {
68
+ utils_2.availablePorts.forEach(port => {
69
+ if (
70
+ // Port is stored in label, avoid using same port.
71
+ usedPorts.match(`port=${port}`) === null &&
72
+ selectedPort === '') {
73
+ selectedPort = port;
74
+ }
75
+ });
76
+ }
77
+ if (selectedPort === '') {
78
+ throw new Error('Failed to find an available Docker port. Try again with --port parameter.');
79
+ }
80
+ try {
81
+ spinner.text = 'Starting the new container.';
82
+ const startCommand = yield (0, utils_2.executeCommand)(`docker run -l "blueprint=${fullPath.replace(/(\s+)/g, '\\$1')}" -l "port=${selectedPort}" -itd --name ${containerName}\
83
+ -p ${utils_2.host}:${selectedPort}:80 \
84
+ -e MYHOST=${utils_2.host} -e MYPORT=${selectedPort} -e BLUEPRINT=${fullPath.replace(/(\s+)/g, '\\$1')} \
85
+ -v "${dirPath}":/var/www/instances \
86
+ ${utils_2.datastoreRepo}`);
87
+ }
88
+ catch (error) {
89
+ if (error.message.includes('already in use') === true) {
90
+ throw new Error('There is already a container running with this blueprint.');
91
+ }
92
+ else {
93
+ throw new Error('Failed to start Docker container. Ask for help in our support forums.');
94
+ }
95
+ }
96
+ spinner.text = 'Installing and simulating new blueprint.';
97
+ const installCommand = yield (0, utils_2.executeCommand)(`docker exec -i ${containerName} install simulator:${yamlFile} --output=json`);
98
+ const obj = JSON.parse(installCommand);
99
+ const url = obj[0].URL;
100
+ const jwtUrl = obj[0].jwtURL;
101
+ const versionDetailsCommand = yield (0, utils_2.executeCommand)(`docker image inspect ${utils_2.datastoreRepo} --format "{{ index .RepoDigests }}"`);
102
+ versionDetails.digest = versionDetailsCommand.replace(/\r?\n|\r/g, '');
103
+ versionDetails.digest = versionDetails.digest.slice(20, -1);
104
+ let simulatorVersionCmd = `docker image inspect ${utils_2.datastoreRepo}`;
105
+ simulatorVersionCmd +=
106
+ ' --format \'{{ or (index .Config.Labels "squiz.datastore.version") (printf "Unknown") }}\'';
107
+ const imageVersion = yield (0, utils_2.executeCommand)(simulatorVersionCmd);
108
+ versionDetails.version = imageVersion.replace(/\r?\n|\r/g, '');
109
+ // Store those info in a file on container, easier to fetch.
110
+ const data = {
111
+ blueprint: `${fullPath}`,
112
+ container: `${containerName}`,
113
+ imageDigest: `${versionDetails.digest}`,
114
+ imageVersion: `${versionDetails.version}`,
115
+ jwt: `${jwtUrl}`,
116
+ url: `${url}`,
117
+ };
118
+ const jsonData = JSON.stringify(data, null, 4).replace(/"/g, '\\"');
119
+ yield (0, utils_2.executeCommand)(`docker exec -i ${containerName} bash -c "echo '${jsonData}' > /var/www/data/containerData.json"`);
120
+ spinner.succeed('Done! Use these details for local querying:');
121
+ console.log('');
122
+ console.log(` URL: ${url}`);
123
+ console.log(` JWT URL: ${jwtUrl}`);
124
+ console.log('');
125
+ return;
126
+ }
127
+ catch (error) {
128
+ (0, utils_1.logDebug)(`ERROR: ${JSON.stringify(error)}`);
129
+ spinner.fail();
130
+ (0, utils_1.handleCommandError)(addCommand, error);
131
+ }
132
+ }));
133
+ if (process.env.ENABLE_OVERRIDE_DATASTORE_URL === 'true') {
134
+ addCommand.addOption(new commander_1.Option('-i, --image <string>', 'Override the docker image'));
135
+ }
136
+ return addCommand;
137
+ };
138
+ exports.default = createAddCommand;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,123 @@
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
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
26
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
27
+ return new (P || (P = Promise))(function (resolve, reject) {
28
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
29
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
30
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
31
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
32
+ });
33
+ };
34
+ var __importDefault = (this && this.__importDefault) || function (mod) {
35
+ return (mod && mod.__esModule) ? mod : { "default": mod };
36
+ };
37
+ Object.defineProperty(exports, "__esModule", { value: true });
38
+ const add_1 = __importDefault(require("./add"));
39
+ const utils = __importStar(require("../utils"));
40
+ const logSpy = jest.spyOn(global.console, 'log');
41
+ jest.mock('fs', () => {
42
+ return {
43
+ existsSync: jest.fn().mockReturnValue(true),
44
+ };
45
+ });
46
+ describe('datastoreSimulatorAdd', () => {
47
+ it('correctly adds a simulator', () => __awaiter(void 0, void 0, void 0, function* () {
48
+ const checkUpdateAvailableSpy = jest
49
+ .spyOn(utils, 'checkUpdateAvailable')
50
+ .mockImplementation(() => {
51
+ return Promise.resolve(null);
52
+ });
53
+ let executeCommandCount = 0;
54
+ const executeCommandSpy = jest
55
+ .spyOn(utils, 'executeCommand')
56
+ .mockImplementation((cmd, opt) => {
57
+ executeCommandCount++;
58
+ switch (executeCommandCount) {
59
+ case 1:
60
+ expect(cmd).toStrictEqual('docker -v');
61
+ return Promise.resolve('Docker version 20.10.23, build 7155243');
62
+ case 2:
63
+ expect(cmd).toStrictEqual('docker ps -a --format "~{{.Labels}}~" --filter "name=datastore-sim-*"');
64
+ return Promise.resolve(`\~blueprint=/Users/pnolland/Documents/Work/GitRepos/blueprints/boilerplate2/api.yaml,desktop.docker.io/binds/0/Source=/Users/pnolland/Documents/Work/GitRepos/blueprints/boilerplate2,desktop.docker.io/binds/0/SourceKind=hostFile,desktop.docker.io/binds/0/Target=/var/www/instances,port=8085,squiz.datastore.version=4.0.1~
65
+ ~desktop.docker.io/binds/0/SourceKind=hostFile,desktop.docker.io/binds/0/Target=/var/www/instances,port=7002,squiz.datastore.version=4.0.1,blueprint=/Users/pnolland/Documents/Work/GitRepos/blueprints/boilerplate/api.yaml,desktop.docker.io/binds/0/Source=/Users/pnolland/Documents/Work/GitRepos/blueprints/boilerplate~
66
+ ~desktop.docker.io/binds/0/Target=/var/www/instances,port=7001,squiz.datastore.version=4.0.1,blueprint=/Users/pnolland/Documents/Work/GitRepos/datastore/apps/js-sdk/tests/test-project/api.yaml,desktop.docker.io/binds/0/Source=/Users/pnolland/Documents/Work/GitRepos/datastore/apps/js-sdk/tests/test-project,desktop.docker.io/binds/0/SourceKind=hostFile~`);
67
+ case 3:
68
+ expect(cmd).toStrictEqual('docker run -l "blueprint=/path/to/blueprint.yaml" -l "port=9999" -itd --name datastore-sim-119726bb -p 0.0.0.0:9999:80 -e MYHOST=0.0.0.0 -e MYPORT=9999 -e BLUEPRINT=/path/to/blueprint.yaml -v "/path/to":/var/www/instances squizdxp/datastore:latest');
69
+ return Promise.resolve('');
70
+ case 4:
71
+ expect(cmd).toStrictEqual('docker exec -i datastore-sim-119726bb install simulator:blueprint.yaml --output=json');
72
+ return Promise.resolve(JSON.stringify([
73
+ {
74
+ URL: 'http://0.0.0.0:9999',
75
+ jwtURL: 'http://0.0.0.0:9999/__JWT/issueToken',
76
+ },
77
+ ]));
78
+ case 5:
79
+ expect(cmd).toStrictEqual('docker image inspect squizdxp/datastore:latest --format "{{ index .RepoDigests }}"');
80
+ return Promise.resolve('[squizdxp/datastore@sha256:bd61f8f80d9f235d81477454cf512a6edede0ae6d2d0a8c0508956db2418dbe0]');
81
+ case 6:
82
+ expect(cmd).toStrictEqual('docker image inspect squizdxp/datastore:latest --format \'{{ or (index .Config.Labels "squiz.datastore.version") (printf "Unknown") }}\'');
83
+ return Promise.resolve('4.0.1');
84
+ case 7:
85
+ expect(cmd).toStrictEqual(`docker exec -i datastore-sim-119726bb bash -c "echo '${JSON.stringify({
86
+ blueprint: '/path/to/blueprint.yaml',
87
+ container: 'datastore-sim-119726bb',
88
+ imageDigest: 'sha256:bd61f8f80d9f235d81477454cf512a6edede0ae6d2d0a8c0508956db2418dbe0',
89
+ imageVersion: '4.0.1',
90
+ jwt: 'http://0.0.0.0:9999/__JWT/issueToken',
91
+ url: 'http://0.0.0.0:9999',
92
+ }, null, 4).replace(/"/g, '\\"')}' > /var/www/data/containerData.json"`);
93
+ return Promise.resolve('');
94
+ }
95
+ return Promise.reject(false);
96
+ });
97
+ process.env.ENABLE_OVERRIDE_DATASTORE_URL = 'true';
98
+ const program = (0, add_1.default)();
99
+ yield program.parseAsync([
100
+ 'node',
101
+ 'dxp-cli',
102
+ 'datastore',
103
+ 'simulator',
104
+ 'add',
105
+ '-p',
106
+ '9999',
107
+ '-b',
108
+ '/path/to/blueprint.yaml',
109
+ '-i',
110
+ 'squizdxp/datastoreDev',
111
+ ]);
112
+ const opts = program.opts();
113
+ expect(opts.port).toEqual('9999');
114
+ expect(opts.image).toEqual('squizdxp/datastoreDev');
115
+ expect(checkUpdateAvailableSpy).toHaveBeenCalledTimes(1);
116
+ expect(logSpy).toHaveBeenCalledTimes(5);
117
+ expect(logSpy).toHaveBeenCalledWith('');
118
+ expect(logSpy).toHaveBeenCalledWith('');
119
+ expect(logSpy).toHaveBeenCalledWith(' URL: http://0.0.0.0:9999');
120
+ expect(logSpy).toHaveBeenCalledWith(' JWT URL: http://0.0.0.0:9999/__JWT/issueToken');
121
+ expect(logSpy).toHaveBeenCalledWith('');
122
+ }));
123
+ });
@@ -0,0 +1,3 @@
1
+ import { Command } from 'commander';
2
+ declare const createRemoveCommand: () => Command;
3
+ export default createRemoveCommand;
@@ -0,0 +1,68 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ var __importDefault = (this && this.__importDefault) || function (mod) {
12
+ return (mod && mod.__esModule) ? mod : { "default": mod };
13
+ };
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ const commander_1 = require("commander");
16
+ const chalk_1 = __importDefault(require("chalk"));
17
+ const ora_1 = __importDefault(require("ora"));
18
+ const utils_1 = require("../../utils");
19
+ const utils_2 = require("../utils");
20
+ const createRemoveCommand = () => {
21
+ const removeCommand = new commander_1.Command('remove')
22
+ .name('remove')
23
+ .description('Removes a datastore simulator')
24
+ .addOption(new commander_1.Option('-b, --blueprint <string>', 'Path to your datastore API yaml file.').makeOptionMandatory())
25
+ .addOption(new commander_1.Option('-f, --force', 'Force the removal of the datastore simulator'))
26
+ .configureOutput({
27
+ outputError(str, write) {
28
+ write(chalk_1.default.red(str));
29
+ },
30
+ })
31
+ .action((options) => __awaiter(void 0, void 0, void 0, function* () {
32
+ console.log('');
33
+ const spinner = (0, ora_1.default)();
34
+ try {
35
+ yield (0, utils_2.checkUpdateAvailable)();
36
+ yield (0, utils_2.checkDockerInstalled)();
37
+ const forceMessage = 'Removing a simulator can not be undone. Are you sure you want to continue? (y/N)';
38
+ if (!options.force) {
39
+ if ((yield (0, utils_2.forcePrompt)(forceMessage, false)) === false) {
40
+ const removeGuide = `To remove run:\n $ dxp-next datastore simulator remove --blueprint ${options.blueprint} --force\n`;
41
+ throw new Error(removeGuide);
42
+ }
43
+ }
44
+ spinner.start('Removing simulator blueprint.');
45
+ const { fullPath, dirPath, yamlFile, containerName } = (0, utils_2.getSimulatorDetails)(options.blueprint);
46
+ const containerCommand = yield (0, utils_2.executeCommand)(`docker ps -a --filter "name=${containerName}" --format "{{.Names}}"`);
47
+ if (containerCommand === '') {
48
+ throw new Error('Sorry, no simulator container found for that blueprint path. Please try again using a different path.');
49
+ }
50
+ try {
51
+ yield (0, utils_2.executeCommand)(`docker rm -f ${containerName}`);
52
+ }
53
+ catch (error) {
54
+ (0, utils_1.logDebug)(`ERROR: ${JSON.stringify(error)}`);
55
+ throw new Error('Unable to remove simulator.');
56
+ }
57
+ spinner.succeed(`Done! Completely removed container ID "${containerName}".`);
58
+ return;
59
+ }
60
+ catch (error) {
61
+ (0, utils_1.logDebug)(`ERROR: ${JSON.stringify(error)}`);
62
+ spinner.fail();
63
+ (0, utils_1.handleCommandError)(removeCommand, error);
64
+ }
65
+ }));
66
+ return removeCommand;
67
+ };
68
+ exports.default = createRemoveCommand;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,224 @@
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
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
26
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
27
+ return new (P || (P = Promise))(function (resolve, reject) {
28
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
29
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
30
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
31
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
32
+ });
33
+ };
34
+ var __importDefault = (this && this.__importDefault) || function (mod) {
35
+ return (mod && mod.__esModule) ? mod : { "default": mod };
36
+ };
37
+ Object.defineProperty(exports, "__esModule", { value: true });
38
+ const remove_1 = __importDefault(require("./remove"));
39
+ const utils = __importStar(require("../utils"));
40
+ const chalk_1 = __importDefault(require("chalk"));
41
+ const logSpy = jest.spyOn(global.console, 'log');
42
+ const exitSpy = jest.spyOn(process, 'exit').mockImplementation(() => {
43
+ return undefined;
44
+ }); // prevent process exit on error
45
+ beforeEach(() => {
46
+ jest.resetAllMocks();
47
+ });
48
+ describe('datastoreSimulatorRemove', () => {
49
+ it('should not remove a simulator if prompt returns false', () => __awaiter(void 0, void 0, void 0, function* () {
50
+ const checkUpdateAvailableSpy = jest
51
+ .spyOn(utils, 'checkUpdateAvailable')
52
+ .mockImplementation(() => {
53
+ return Promise.resolve(null);
54
+ });
55
+ const forcePromptSpy = jest
56
+ .spyOn(utils, 'forcePrompt')
57
+ .mockResolvedValue(false);
58
+ let executeCommandCount = 0;
59
+ const executeCommandSpy = jest
60
+ .spyOn(utils, 'executeCommand')
61
+ .mockImplementation((cmd, opt) => {
62
+ executeCommandCount++;
63
+ switch (executeCommandCount) {
64
+ case 1:
65
+ expect(cmd).toStrictEqual('docker -v');
66
+ return Promise.resolve('Docker version 20.10.23, build 7155243');
67
+ }
68
+ return Promise.reject(false);
69
+ });
70
+ const program = (0, remove_1.default)();
71
+ const commandErrorSpy = jest.spyOn(program, 'error');
72
+ yield program.parseAsync([
73
+ 'node',
74
+ 'dxp-cli',
75
+ 'datastore',
76
+ 'simulator',
77
+ 'remove',
78
+ '-b',
79
+ '/path/to/blueprint.yaml',
80
+ ]);
81
+ const opts = program.opts();
82
+ expect(opts.blueprint).toEqual('/path/to/blueprint.yaml');
83
+ expect(checkUpdateAvailableSpy).toHaveBeenCalledTimes(1);
84
+ expect(commandErrorSpy).toHaveBeenCalledWith(chalk_1.default.red(`To remove run:
85
+ $ dxp-next datastore simulator remove --blueprint /path/to/blueprint.yaml --force
86
+ `));
87
+ expect(forcePromptSpy).toHaveBeenCalledWith('Removing a simulator can not be undone. Are you sure you want to continue? (y/N)', false);
88
+ expect(logSpy).toHaveBeenCalledTimes(1);
89
+ expect(executeCommandSpy).toHaveBeenCalledTimes(1);
90
+ }));
91
+ it('should remove a simulator if prompt returns true', () => __awaiter(void 0, void 0, void 0, function* () {
92
+ const checkUpdateAvailableSpy = jest
93
+ .spyOn(utils, 'checkUpdateAvailable')
94
+ .mockImplementation(() => {
95
+ return Promise.resolve(null);
96
+ });
97
+ const forcePromptSpy = jest
98
+ .spyOn(utils, 'forcePrompt')
99
+ .mockResolvedValue(true);
100
+ let executeCommandCount = 0;
101
+ const executeCommandSpy = jest
102
+ .spyOn(utils, 'executeCommand')
103
+ .mockImplementation((cmd, opt) => {
104
+ executeCommandCount++;
105
+ switch (executeCommandCount) {
106
+ case 1:
107
+ expect(cmd).toStrictEqual('docker -v');
108
+ return Promise.resolve('Docker version 20.10.23, build 7155243');
109
+ case 2:
110
+ expect(cmd).toStrictEqual('docker ps -a --filter "name=datastore-sim-119726bb" --format "{{.Names}}"');
111
+ return Promise.resolve('datastore-sim-119726bb');
112
+ case 3:
113
+ expect(cmd).toStrictEqual('docker rm -f datastore-sim-119726bb');
114
+ return Promise.resolve('');
115
+ }
116
+ return Promise.reject(false);
117
+ });
118
+ const program = (0, remove_1.default)();
119
+ const commandErrorSpy = jest.spyOn(program, 'error');
120
+ yield program.parseAsync([
121
+ 'node',
122
+ 'dxp-cli',
123
+ 'datastore',
124
+ 'simulator',
125
+ 'remove',
126
+ '-b',
127
+ '/path/to/blueprint.yaml',
128
+ ]);
129
+ const opts = program.opts();
130
+ expect(opts.blueprint).toEqual('/path/to/blueprint.yaml');
131
+ expect(checkUpdateAvailableSpy).toHaveBeenCalledTimes(1);
132
+ expect(commandErrorSpy).not.toHaveBeenCalled();
133
+ expect(forcePromptSpy).toHaveBeenCalledWith('Removing a simulator can not be undone. Are you sure you want to continue? (y/N)', false);
134
+ expect(logSpy).toHaveBeenCalledTimes(1);
135
+ expect(executeCommandSpy).toHaveBeenCalledTimes(3);
136
+ }));
137
+ it('should remove a simulator if --force set', () => __awaiter(void 0, void 0, void 0, function* () {
138
+ const checkUpdateAvailableSpy = jest
139
+ .spyOn(utils, 'checkUpdateAvailable')
140
+ .mockImplementation(() => {
141
+ return Promise.resolve(null);
142
+ });
143
+ const forcePromptSpy = jest
144
+ .spyOn(utils, 'forcePrompt')
145
+ .mockResolvedValue(true);
146
+ let executeCommandCount = 0;
147
+ const executeCommandSpy = jest
148
+ .spyOn(utils, 'executeCommand')
149
+ .mockImplementation((cmd, opt) => {
150
+ executeCommandCount++;
151
+ switch (executeCommandCount) {
152
+ case 1:
153
+ expect(cmd).toStrictEqual('docker -v');
154
+ return Promise.resolve('Docker version 20.10.23, build 7155243');
155
+ case 2:
156
+ expect(cmd).toStrictEqual('docker ps -a --filter "name=datastore-sim-119726bb" --format "{{.Names}}"');
157
+ return Promise.resolve('datastore-sim-119726bb');
158
+ case 3:
159
+ expect(cmd).toStrictEqual('docker rm -f datastore-sim-119726bb');
160
+ return Promise.resolve('');
161
+ }
162
+ return Promise.reject(false);
163
+ });
164
+ const program = (0, remove_1.default)();
165
+ const commandErrorSpy = jest.spyOn(program, 'error');
166
+ yield program.parseAsync([
167
+ 'node',
168
+ 'dxp-cli',
169
+ 'datastore',
170
+ 'simulator',
171
+ 'remove',
172
+ '-b',
173
+ '/path/to/blueprint.yaml',
174
+ '--force',
175
+ ]);
176
+ const opts = program.opts();
177
+ expect(opts.blueprint).toEqual('/path/to/blueprint.yaml');
178
+ expect(checkUpdateAvailableSpy).toHaveBeenCalledTimes(1);
179
+ expect(commandErrorSpy).not.toHaveBeenCalled();
180
+ expect(forcePromptSpy).not.toHaveBeenCalled();
181
+ expect(logSpy).toHaveBeenCalledTimes(1);
182
+ expect(executeCommandSpy).toHaveBeenCalledTimes(3);
183
+ }));
184
+ it('should not remove a simulator if no matching simulator found', () => __awaiter(void 0, void 0, void 0, function* () {
185
+ const checkUpdateAvailableSpy = jest
186
+ .spyOn(utils, 'checkUpdateAvailable')
187
+ .mockImplementation(() => {
188
+ return Promise.resolve(null);
189
+ });
190
+ let executeCommandCount = 0;
191
+ const executeCommandSpy = jest
192
+ .spyOn(utils, 'executeCommand')
193
+ .mockImplementation((cmd, opt) => {
194
+ executeCommandCount++;
195
+ switch (executeCommandCount) {
196
+ case 1:
197
+ expect(cmd).toStrictEqual('docker -v');
198
+ return Promise.resolve('Docker version 20.10.23, build 7155243');
199
+ case 2:
200
+ expect(cmd).toStrictEqual('docker ps -a --filter "name=datastore-sim-119726bb" --format "{{.Names}}"');
201
+ return Promise.resolve('');
202
+ }
203
+ return Promise.reject(false);
204
+ });
205
+ const program = (0, remove_1.default)();
206
+ const commandErrorSpy = jest.spyOn(program, 'error');
207
+ yield program.parseAsync([
208
+ 'node',
209
+ 'dxp-cli',
210
+ 'datastore',
211
+ 'simulator',
212
+ 'remove',
213
+ '-b',
214
+ '/path/to/blueprint.yaml',
215
+ '--force',
216
+ ]);
217
+ const opts = program.opts();
218
+ expect(opts.blueprint).toEqual('/path/to/blueprint.yaml');
219
+ expect(checkUpdateAvailableSpy).toHaveBeenCalledTimes(1);
220
+ expect(commandErrorSpy).toHaveBeenCalledWith(chalk_1.default.red('Sorry, no simulator container found for that blueprint path. Please try again using a different path.'));
221
+ expect(logSpy).toHaveBeenCalledTimes(1);
222
+ expect(executeCommandSpy).toHaveBeenCalledTimes(2);
223
+ }));
224
+ });
@@ -0,0 +1,3 @@
1
+ import { Command } from 'commander';
2
+ declare const createSimulatorCommand: () => Command;
3
+ export default createSimulatorCommand;
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const commander_1 = require("commander");
7
+ const add_1 = __importDefault(require("./add/add"));
8
+ const remove_1 = __importDefault(require("./remove/remove"));
9
+ const createSimulatorCommand = () => {
10
+ const datastoreSimulatorCommand = new commander_1.Command('simulator');
11
+ datastoreSimulatorCommand
12
+ .description('Datastore Simulator Commands')
13
+ .addCommand((0, add_1.default)())
14
+ .addCommand((0, remove_1.default)());
15
+ return datastoreSimulatorCommand;
16
+ };
17
+ exports.default = createSimulatorCommand;
@@ -0,0 +1,22 @@
1
+ declare type datastoreVersionCache = {
2
+ digest: string;
3
+ updatedAt: number;
4
+ version: string;
5
+ };
6
+ export declare const datastoreRepo = "squizdxp/datastore:latest";
7
+ export declare const allowedExtensions: string[];
8
+ export declare const host = "0.0.0.0";
9
+ export declare const availablePorts: string[];
10
+ export declare const executeCommand: (cmd: string, opts?: any) => Promise<unknown>;
11
+ export declare function stringHashShort(value: string): string;
12
+ export declare const promptForContinue: (versionCache: datastoreVersionCache, currentVersion: string) => Promise<boolean>;
13
+ export declare const forcePrompt: (message: string, def?: boolean) => Promise<boolean>;
14
+ export declare function checkDockerInstalled(): Promise<void>;
15
+ export declare const checkUpdateAvailable: () => Promise<null>;
16
+ export declare function getSimulatorDetails(blueprint: string): {
17
+ fullPath: string;
18
+ dirPath: string;
19
+ yamlFile: string;
20
+ containerName: string;
21
+ };
22
+ export {};
@@ -0,0 +1,197 @@
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
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
26
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
27
+ return new (P || (P = Promise))(function (resolve, reject) {
28
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
29
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
30
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
31
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
32
+ });
33
+ };
34
+ Object.defineProperty(exports, "__esModule", { value: true });
35
+ exports.getSimulatorDetails = exports.checkUpdateAvailable = exports.checkDockerInstalled = exports.forcePrompt = exports.promptForContinue = exports.stringHashShort = exports.executeCommand = exports.availablePorts = exports.host = exports.allowedExtensions = exports.datastoreRepo = void 0;
36
+ const child_process_1 = require("child_process");
37
+ const ApplicationStore_1 = require("../../ApplicationStore");
38
+ const ApiService_1 = require("../../ApiService");
39
+ const utils_1 = require("../utils");
40
+ const path_1 = require("path");
41
+ const datastoreSimulatorCache = {
42
+ name: 'datastore-simulator',
43
+ type: 'data',
44
+ };
45
+ exports.datastoreRepo = 'squizdxp/datastore:latest';
46
+ exports.allowedExtensions = ['yaml', 'yml'];
47
+ exports.host = '0.0.0.0';
48
+ exports.availablePorts = [
49
+ '7001',
50
+ '7002',
51
+ '7003',
52
+ '7004',
53
+ '7005',
54
+ '7006',
55
+ '7007',
56
+ '7008',
57
+ '7009',
58
+ '7010',
59
+ ];
60
+ const dockerAPI = 'https://registry.hub.docker.com/v2/repositories/squizdxp/datastore/tags?page_size=3';
61
+ const executeCommand = (cmd, opts = {}) => __awaiter(void 0, void 0, void 0, function* () {
62
+ return new Promise(function (resolve, reject) {
63
+ (0, child_process_1.exec)(cmd, opts, (err, stdout, stderr) => {
64
+ if (err) {
65
+ reject(err);
66
+ }
67
+ else {
68
+ resolve(stdout);
69
+ }
70
+ });
71
+ });
72
+ });
73
+ exports.executeCommand = executeCommand;
74
+ function stringHashShort(value) {
75
+ return value
76
+ .split('')
77
+ .reduce((prevHash, currVal) => ((prevHash << 5) - prevHash + currVal.charCodeAt(0)) | 0, 0)
78
+ .toString(16)
79
+ .replace('-', '');
80
+ }
81
+ exports.stringHashShort = stringHashShort;
82
+ const promptForContinue = (versionCache, currentVersion) => __awaiter(void 0, void 0, void 0, function* () {
83
+ const inquirer = yield Promise.resolve().then(() => __importStar(require('inquirer')));
84
+ const confirm = yield inquirer.default.prompt([
85
+ {
86
+ default: false,
87
+ message: 'A new version of the Datastore simulator is available ' +
88
+ `(${currentVersion} -> ${versionCache.version}). ` +
89
+ 'Would you like to upgrade now? (y/N)',
90
+ name: 'skip',
91
+ type: 'confirm',
92
+ },
93
+ ]);
94
+ return confirm.skip;
95
+ });
96
+ exports.promptForContinue = promptForContinue;
97
+ const forcePrompt = (message, def = false) => __awaiter(void 0, void 0, void 0, function* () {
98
+ console.info('WHY!!!!!');
99
+ const inquirer = yield Promise.resolve().then(() => __importStar(require('inquirer')));
100
+ const confirm = yield inquirer.default.prompt([
101
+ {
102
+ default: def,
103
+ message,
104
+ name: 'skip',
105
+ type: 'confirm',
106
+ },
107
+ ]);
108
+ return confirm.skip;
109
+ });
110
+ exports.forcePrompt = forcePrompt;
111
+ function checkDockerInstalled() {
112
+ return __awaiter(this, void 0, void 0, function* () {
113
+ try {
114
+ yield (0, exports.executeCommand)('docker -v');
115
+ }
116
+ catch (error) {
117
+ throw new Error('Docker not installed. Please install latest version.');
118
+ }
119
+ });
120
+ }
121
+ exports.checkDockerInstalled = checkDockerInstalled;
122
+ const checkUpdateAvailable = () => __awaiter(void 0, void 0, void 0, function* () {
123
+ let simulatorVersionCmd = `docker image inspect ${exports.datastoreRepo}`;
124
+ simulatorVersionCmd +=
125
+ ' --format \'{{ or (index .Config.Labels "squiz.datastore.version") (printf "Unknown") }}\'';
126
+ // Default updatedAt to over 1 hour ago to force a check
127
+ const versionCache = JSON.parse((yield (0, ApplicationStore_1.getApplicationFile)(datastoreSimulatorCache)) ||
128
+ `{"updatedAt": ${Math.floor(Date.now() / 1000 - 7200)}}`);
129
+ let refreshVersionCache = false;
130
+ let versionInfo = versionCache;
131
+ let latestImage;
132
+ let taggedImage;
133
+ if (typeof process.env.DXP_DATASTORE_SIMULATOR_SKIP_VERSION_CHECK ===
134
+ 'string' &&
135
+ process.env.DXP_DATASTORE_SIMULATOR_SKIP_VERSION_CHECK) {
136
+ return null;
137
+ }
138
+ else {
139
+ const nowAt = Math.floor(Date.now() / 1000);
140
+ if (nowAt - versionCache.updatedAt > 3600) {
141
+ refreshVersionCache = true;
142
+ }
143
+ if (refreshVersionCache === true) {
144
+ const apiService = new ApiService_1.ApiService(utils_1.validateAxiosStatus);
145
+ apiService.client.interceptors.request.clear();
146
+ apiService.client.interceptors.response.clear();
147
+ const dockerFetch = yield apiService.client.get(dockerAPI);
148
+ const dockerResponse = dockerFetch.data;
149
+ latestImage = dockerResponse.results.filter((image) => {
150
+ return image.name === 'latest';
151
+ })[0];
152
+ taggedImage = dockerResponse.results[1];
153
+ versionInfo = {
154
+ digest: latestImage.images[0].digest || '',
155
+ updatedAt: Date.now() / 1000,
156
+ version: taggedImage.name || '',
157
+ };
158
+ yield (0, ApplicationStore_1.saveApplicationFile)(datastoreSimulatorCache, JSON.stringify(versionInfo));
159
+ }
160
+ let result;
161
+ try {
162
+ result = yield (0, exports.executeCommand)(`docker image inspect ${exports.datastoreRepo} --format "{{ index .RepoDigests }}"`);
163
+ if (versionInfo.digest !== '' &&
164
+ result.slice(20).startsWith(versionInfo.digest) === false) {
165
+ const version = yield (0, exports.executeCommand)(simulatorVersionCmd);
166
+ const currentVersion = version.replace(/\r?\n|\r/g, '');
167
+ const upgradeGuide = 'To upgrade run:\n $ dxp-next datastore simulator upgrade\n';
168
+ if ((yield (0, exports.promptForContinue)(versionInfo, currentVersion)) === true) {
169
+ throw new Error(upgradeGuide);
170
+ }
171
+ }
172
+ }
173
+ catch (error) {
174
+ if (error.message.includes('No such image')) {
175
+ result = '';
176
+ }
177
+ else {
178
+ throw new Error(error.message);
179
+ }
180
+ }
181
+ }
182
+ return null;
183
+ });
184
+ exports.checkUpdateAvailable = checkUpdateAvailable;
185
+ function getSimulatorDetails(blueprint) {
186
+ const fullPath = (0, path_1.resolve)(blueprint);
187
+ const dirPath = (0, path_1.dirname)(fullPath);
188
+ const yamlFile = (0, path_1.basename)(fullPath);
189
+ const containerName = `datastore-sim-${stringHashShort(fullPath)}`;
190
+ return {
191
+ fullPath,
192
+ dirPath,
193
+ yamlFile,
194
+ containerName,
195
+ };
196
+ }
197
+ exports.getSimulatorDetails = getSimulatorDetails;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,165 @@
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
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
26
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
27
+ return new (P || (P = Promise))(function (resolve, reject) {
28
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
29
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
30
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
31
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
32
+ });
33
+ };
34
+ var __importDefault = (this && this.__importDefault) || function (mod) {
35
+ return (mod && mod.__esModule) ? mod : { "default": mod };
36
+ };
37
+ Object.defineProperty(exports, "__esModule", { value: true });
38
+ const utils = __importStar(require("./utils"));
39
+ const nock_1 = __importDefault(require("nock"));
40
+ const exitSpy = jest.spyOn(process, 'exit').mockImplementation(() => {
41
+ return undefined;
42
+ }); // prevent process exit on error
43
+ const stderrSpy = jest.spyOn(process.stderr, 'write');
44
+ // const logSpy = jest.spyOn(global.console, 'log');
45
+ beforeEach(() => {
46
+ jest.resetAllMocks();
47
+ });
48
+ describe('stringHashShort', () => {
49
+ it('should correctly hash the path for a simulated blueprint', () => __awaiter(void 0, void 0, void 0, function* () {
50
+ const path = '/path/to/my/blueprint.yaml';
51
+ const expectedHash = '4a3d07ac';
52
+ const hash = utils.stringHashShort(path);
53
+ expect(hash).toStrictEqual(expectedHash);
54
+ }));
55
+ });
56
+ describe('checkDockerInstalled', () => {
57
+ it('should throw error when docker -v fails', () => __awaiter(void 0, void 0, void 0, function* () {
58
+ const executeCommandSpy = jest
59
+ .spyOn(utils, 'executeCommand')
60
+ .mockImplementation((cmd, opts) => {
61
+ expect(cmd).toStrictEqual('docker -v');
62
+ return Promise.reject(false);
63
+ });
64
+ yield expect(utils.checkDockerInstalled()).rejects.toThrowError(new Error('Docker not installed. Please install latest version.'));
65
+ }));
66
+ it('should not throw an error when docker -v works', () => __awaiter(void 0, void 0, void 0, function* () {
67
+ const executeCommandSpy = jest
68
+ .spyOn(utils, 'executeCommand')
69
+ .mockImplementation((cmd, opts) => {
70
+ expect(cmd).toStrictEqual('docker -v');
71
+ return Promise.resolve(true);
72
+ });
73
+ yield expect(utils.checkDockerInstalled()).resolves.not.toThrowError(new Error('Docker not installed. Please install latest version.'));
74
+ }));
75
+ });
76
+ describe('checkUpdateAvailable', () => {
77
+ it('should skip checking for an update if the DXP_DATASTORE_SIMULATOR_SKIP_VERSION_CHECK is set', () => __awaiter(void 0, void 0, void 0, function* () {
78
+ process.env.DXP_DATASTORE_SIMULATOR_SKIP_VERSION_CHECK = 'true';
79
+ yield expect(utils.checkUpdateAvailable()).resolves.toStrictEqual(null);
80
+ delete process.env.DXP_DATASTORE_SIMULATOR_SKIP_VERSION_CHECK;
81
+ }));
82
+ it('should not prompt when no update needed', () => __awaiter(void 0, void 0, void 0, function* () {
83
+ (0, nock_1.default)('https://registry.hub.docker.com')
84
+ .get('/v2/repositories/squizdxp/datastore/tags?page_size=3')
85
+ .reply(200, {
86
+ results: [
87
+ {
88
+ images: [
89
+ {
90
+ digest: 'sha256:bd61f8f80d9f235d81477454cf512a6edede0ae6d2d0a8c0508956db2418dbe0',
91
+ },
92
+ ],
93
+ name: 'latest',
94
+ },
95
+ {
96
+ images: [
97
+ {
98
+ digest: 'sha256:bd61f8f80d9f235d81477454cf512a6edede0ae6d2d0a8c0508956db2418dbe0',
99
+ },
100
+ ],
101
+ name: '4.0.1',
102
+ },
103
+ {
104
+ images: [
105
+ {
106
+ digest: 'sha256:bd61f8f80d9f235d81477454cf512a6edede0ae6d2d0a8c0508956db2418dbe0',
107
+ },
108
+ ],
109
+ name: 'c4f40b0d',
110
+ },
111
+ ],
112
+ });
113
+ const promptSpy = jest
114
+ .spyOn(utils, 'promptForContinue')
115
+ .mockResolvedValue(false);
116
+ const executeCommandSpy = jest
117
+ .spyOn(utils, 'executeCommand')
118
+ .mockResolvedValue('[squizdxp/datastore@sha256:bd61f8f80d9f235d81477454cf512a6edede0ae6d2d0a8c0508956db2418dbe0]');
119
+ yield expect(utils.checkUpdateAvailable()).resolves.toStrictEqual(null);
120
+ expect(executeCommandSpy).toHaveBeenCalledWith('docker image inspect squizdxp/datastore:latest --format "{{ index .RepoDigests }}"');
121
+ expect(promptSpy).not.toHaveBeenCalled();
122
+ }));
123
+ it('should prompt when update needed', () => __awaiter(void 0, void 0, void 0, function* () {
124
+ (0, nock_1.default)('https://registry.hub.docker.com')
125
+ .get('/v2/repositories/squizdxp/datastore/tags?page_size=3')
126
+ .reply(200, {
127
+ results: [
128
+ {
129
+ images: [
130
+ {
131
+ digest: 'sha256:bd61f8f80d9f235d81477454cf512a6edede0ae6d2d0a8c0508956db2418dbe0',
132
+ },
133
+ ],
134
+ name: 'latest',
135
+ },
136
+ {
137
+ images: [
138
+ {
139
+ digest: 'sha256:bd61f8f80d9f235d81477454cf512a6edede0ae6d2d0a8c0508956db2418dbe0',
140
+ },
141
+ ],
142
+ name: '4.0.1',
143
+ },
144
+ {
145
+ images: [
146
+ {
147
+ digest: 'sha256:bd61f8f80d9f235d81477454cf512a6edede0ae6d2d0a8c0508956db2418dbe0',
148
+ },
149
+ ],
150
+ name: 'c4f40b0d',
151
+ },
152
+ ],
153
+ });
154
+ const promptSpy = jest
155
+ .spyOn(utils, 'promptForContinue')
156
+ .mockResolvedValue(false);
157
+ const executeCommandSpy = jest
158
+ .spyOn(utils, 'executeCommand')
159
+ .mockResolvedValue('[squizdxp/datastore@sha256:bd61f8f80d9f235d81477454cf512a6edede0ae6d2d0a8c0508956db2418dbe1]');
160
+ yield expect(utils.checkUpdateAvailable()).resolves.toStrictEqual(null);
161
+ expect(executeCommandSpy).toHaveBeenNthCalledWith(1, 'docker image inspect squizdxp/datastore:latest --format "{{ index .RepoDigests }}"');
162
+ expect(executeCommandSpy).toHaveBeenNthCalledWith(2, 'docker image inspect squizdxp/datastore:latest --format \'{{ or (index .Config.Labels "squiz.datastore.version") (printf "Unknown") }}\'');
163
+ expect(promptSpy).toHaveBeenCalled();
164
+ }));
165
+ });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@squiz/dxp-cli-next",
3
- "version": "5.9.0-develop.44",
3
+ "version": "5.9.0-develop.46",
4
4
  "repository": {
5
5
  "url": "https://gitlab.squiz.net/dxp/dxp-cli-next"
6
6
  },
@@ -39,7 +39,7 @@
39
39
  "codecov"
40
40
  ],
41
41
  "dependencies": {
42
- "@squiz/component-cli-lib": "1.63.1-alpha.0",
42
+ "@squiz/component-cli-lib": "1.63.1-alpha.3",
43
43
  "@apidevtools/swagger-parser": "10.1.0",
44
44
  "axios": "1.1.3",
45
45
  "cli-color": "2.0.3",