@squiz/dxp-cli-next 5.24.0-develop.4 → 5.25.0-develop.1

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.
@@ -32,10 +32,6 @@ const createActivateCommand = () => {
32
32
  const activateCommand = new commander_1.Command('deploy')
33
33
  .name('activate')
34
34
  .description('Activate a CDP instance')
35
- .addOption(new commander_1.Option('-t, --tenant <string>', 'Tenant ID to run against. If not provided will use configured tenant from login'))
36
- .addOption(new commander_1.Option('-r, --region <string>', 'Region for your instance to be activated e.g. au')
37
- .choices(['au', 'uk', 'us'])
38
- .makeOptionMandatory())
39
35
  .configureOutput({
40
36
  outputError(str, write) {
41
37
  write(chalk_1.default.red(str));
@@ -51,7 +47,7 @@ const createActivateCommand = () => {
51
47
  return status < 400 || status === 404;
52
48
  },
53
49
  });
54
- const scvDeployBaseUrl = yield (0, utils_1.buildDXPUrl)(constants_1.SCV_DEPLOY_SERVICE_NAME, options.tenant, options.overrideUrl, options.region);
50
+ const scvDeployBaseUrl = yield (0, utils_1.buildDXPUrl)(constants_1.SCV_DEPLOY_SERVICE_NAME, undefined, options.overrideUrl, undefined);
55
51
  const apiUrl = `${scvDeployBaseUrl.dxpUrl}/${scvDeployBaseUrl.tenant}`;
56
52
  const getDeployResponse = (yield apiService.client
57
53
  .get(apiUrl)
@@ -66,11 +62,7 @@ const createActivateCommand = () => {
66
62
  }
67
63
  (0, utils_1.logDebug)(`PUT ${apiUrl}`);
68
64
  const activateInstanceAndDeploySchemaResponse = (yield apiService.client
69
- .put(apiUrl, null, {
70
- headers: {
71
- 'Content-Type': 'application/json',
72
- },
73
- })
65
+ .put(apiUrl)
74
66
  .catch((err) => {
75
67
  (0, utils_1.logDebug)(`RAW ERROR: ${JSON.stringify(err)}`);
76
68
  if (err.response) {
@@ -40,21 +40,10 @@ const activate_1 = __importStar(require("./activate"));
40
40
  const deploy_const_1 = require("../../schema/deploy/deploy.const");
41
41
  const utils_1 = require("../../utils");
42
42
  const activate = __importStar(require("./activate"));
43
+ const utils = __importStar(require("../../utils"));
43
44
  const mockDomainWithPath = 'http://localhost:9999/__dxp/us/scv-deploy/myTenant';
44
- function createMockArgs(region, tenantID, filePath, mockDomain) {
45
- return [
46
- 'node',
47
- 'dxp-cli',
48
- 'cdp',
49
- 'instance',
50
- 'activate',
51
- '-t',
52
- tenantID,
53
- '-r',
54
- region,
55
- '-ou',
56
- 'http://localhost:9999',
57
- ];
45
+ function createMockArgs() {
46
+ return ['node', 'dxp-cli', 'cdp', 'instance', 'activate'];
58
47
  }
59
48
  describe('cdpInstanceCommand', () => {
60
49
  let mockTenant;
@@ -86,16 +75,24 @@ describe('cdpInstanceCommand', () => {
86
75
  nock_1.default.cleanAll(); // Clear all HTTP mocks
87
76
  });
88
77
  it('should throw error when tenant exists', () => __awaiter(void 0, void 0, void 0, function* () {
78
+ jest.spyOn(utils, 'buildDXPUrl').mockResolvedValue({
79
+ dxpUrl: `${mockDomain}/__dxp/us/scv-deploy`,
80
+ tenant: mockTenant,
81
+ });
89
82
  const mockPath = (0, utils_1.createMockUrl)(mockRegion, mockTenant);
90
83
  expect(`${mockDomain}${mockPath}`).toEqual(mockDomainWithPath);
91
84
  (0, nock_1.default)(mockDomain)
92
85
  .get(mockPath)
93
86
  .reply(200, { status: deploy_const_1.CDP_DEPLOY_STATUS_ERROR });
94
87
  const program = (0, activate_1.default)();
95
- yield program.parseAsync(createMockArgs(mockRegion, mockTenant, mockFilePath, mockDomain));
88
+ yield program.parseAsync(createMockArgs());
96
89
  expect(errorSpy).toHaveBeenCalledWith(expect.stringContaining(activate_1.errorMessage));
97
90
  }));
98
91
  it('should throw error when get tenant returns 403', () => __awaiter(void 0, void 0, void 0, function* () {
92
+ jest.spyOn(utils, 'buildDXPUrl').mockResolvedValue({
93
+ dxpUrl: `${mockDomain}/__dxp/us/scv-deploy`,
94
+ tenant: mockTenant,
95
+ });
99
96
  const mockPath = (0, utils_1.createMockUrl)(mockRegion, mockTenant);
100
97
  expect(`${mockDomain}${mockPath}`).toEqual(mockDomainWithPath);
101
98
  (0, nock_1.default)(mockDomain).get(mockPath).reply(403, {
@@ -103,13 +100,17 @@ describe('cdpInstanceCommand', () => {
103
100
  status: 403,
104
101
  });
105
102
  const program = (0, activate_1.default)();
106
- yield program.parseAsync(createMockArgs(mockRegion, mockTenant, mockFilePath, mockDomain));
103
+ yield program.parseAsync(createMockArgs());
107
104
  expect(activateErrorSpy).toHaveBeenCalledWith(403, {
108
105
  status: 403,
109
106
  title: 'Forbidden',
110
107
  });
111
108
  }));
112
109
  it('deploys a default schema and activate an instance', () => __awaiter(void 0, void 0, void 0, function* () {
110
+ jest.spyOn(utils, 'buildDXPUrl').mockResolvedValue({
111
+ dxpUrl: `${mockDomain}/__dxp/us/scv-deploy`,
112
+ tenant: mockTenant,
113
+ });
113
114
  const mockPath = (0, utils_1.createMockUrl)(mockRegion, mockTenant);
114
115
  expect(`${mockDomain}${mockPath}`).toEqual(mockDomainWithPath);
115
116
  (0, nock_1.default)(mockDomain)
@@ -129,7 +130,7 @@ describe('cdpInstanceCommand', () => {
129
130
  status: deploy_const_1.CDP_DEPLOY_STATUS_DEPLOYED,
130
131
  });
131
132
  const program = (0, activate_1.default)();
132
- yield program.parseAsync(createMockArgs(mockRegion, mockTenant, mockFilePath, mockDomain));
133
+ yield program.parseAsync(createMockArgs());
133
134
  // Note the output from the spinner doesn't seem to appear here but this still tests that it
134
135
  // ran without displaying an error.
135
136
  expect(logSpy).toHaveBeenNthCalledWith(1, '');
@@ -0,0 +1,5 @@
1
+ import { Command } from 'commander';
2
+ import { Logger } from '@squiz/dx-logger-lib';
3
+ export declare const logger: Logger;
4
+ declare const createDevCommand: () => Command;
5
+ export default createDevCommand;
@@ -0,0 +1,70 @@
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
+ exports.logger = void 0;
16
+ const commander_1 = require("commander");
17
+ const dx_logger_lib_1 = require("@squiz/dx-logger-lib");
18
+ const definitions_1 = require("../../utils/definitions");
19
+ const path_1 = __importDefault(require("path"));
20
+ const server_1 = require("../../utils/server");
21
+ const parse_args_1 = require("../../utils/parse-args");
22
+ exports.logger = (0, dx_logger_lib_1.getLogger)({
23
+ name: 'layout-dev',
24
+ format: 'human',
25
+ });
26
+ const createDevCommand = () => {
27
+ const devCommand = new commander_1.Command()
28
+ .name('dev')
29
+ .description('Start a development server for page layouts')
30
+ .option('--config <string>', 'File path to the page layout config file', './page-layout.yaml')
31
+ .option('--port <number>', 'Port to run the development server on', '4040')
32
+ .option('--no-open', 'Do not automatically open browser')
33
+ .option('--stylesheet <path>', 'Path to CSS file to include')
34
+ .option('--zones <items>', 'Zone content mappings', parse_args_1.parseZonesList, {})
35
+ .option('--options <items>', 'Layout options', parse_args_1.parseOptionsList, {})
36
+ .allowUnknownOption(true)
37
+ .allowExcessArguments(true)
38
+ .action((options) => __awaiter(void 0, void 0, void 0, function* () {
39
+ try {
40
+ // Load layout definition
41
+ exports.logger.info(`Loading layout definition from ${options.config}`);
42
+ const rawLayoutDefinition = yield (0, definitions_1.loadLayoutDefinition)(options.config);
43
+ if (!rawLayoutDefinition) {
44
+ throw new Error(`Failed to load layout definition from ${options.config}`);
45
+ }
46
+ // Confirm for entry property
47
+ const layoutDefinition = Object.assign({}, rawLayoutDefinition);
48
+ exports.logger.info('Starting development server...');
49
+ yield (0, server_1.startDevServer)({
50
+ configPath: path_1.default.resolve(options.config),
51
+ layoutDefinition,
52
+ zoneContent: options.zones,
53
+ layoutOptions: options.options,
54
+ stylesheet: options.stylesheet
55
+ ? path_1.default.resolve(options.stylesheet)
56
+ : undefined,
57
+ port: parseInt(options.port) || 4040,
58
+ openBrowser: options.open !== false,
59
+ });
60
+ }
61
+ catch (error) {
62
+ if (error.stack && process.env.DEBUG) {
63
+ console.error(error.stack);
64
+ }
65
+ exports.logger.error(error.message || 'An unknown error occurred');
66
+ }
67
+ }));
68
+ return devCommand;
69
+ };
70
+ exports.default = createDevCommand;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,162 @@
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
+ jest.mock('../../utils/definitions');
16
+ jest.mock('../../utils/server');
17
+ jest.mock('@squiz/dx-logger-lib', () => ({
18
+ getLogger: () => {
19
+ return {
20
+ info: mockLoggerInfoFn,
21
+ error: mockLoggerErrorFn,
22
+ warn: jest.fn(),
23
+ };
24
+ },
25
+ }));
26
+ const mockLoggerInfoFn = jest.fn();
27
+ const mockLoggerErrorFn = jest.fn();
28
+ const dev_1 = __importDefault(require("./dev"));
29
+ const definitions_1 = require("../../utils/definitions");
30
+ const server_1 = require("../../utils/server");
31
+ const path_1 = __importDefault(require("path"));
32
+ const originalProcessArgv = process.argv;
33
+ function createMockArgs(opts) {
34
+ const args = ['node', 'dxp-cli', 'dev'];
35
+ if (opts.config)
36
+ args.push('--config', opts.config);
37
+ if (opts.port)
38
+ args.push('--port', opts.port.toString());
39
+ if (opts.open === false)
40
+ args.push('--no-open');
41
+ if (opts.stylesheet)
42
+ args.push('--stylesheet', opts.stylesheet);
43
+ if (opts.zoneContent) {
44
+ Object.entries(opts.zoneContent).forEach(([zoneName, filePaths]) => {
45
+ filePaths.forEach(filePath => {
46
+ args.push(`--zones=${zoneName}=${filePath}`);
47
+ });
48
+ });
49
+ }
50
+ if (opts.layoutOptions) {
51
+ Object.entries(opts.layoutOptions).forEach(([optionName, value]) => {
52
+ args.push(`--options=${optionName}=${value}`);
53
+ });
54
+ }
55
+ return args;
56
+ }
57
+ describe('devCommand', () => {
58
+ beforeEach(() => {
59
+ jest.clearAllMocks();
60
+ process.argv = originalProcessArgv;
61
+ });
62
+ it('correctly handles command option defaults', () => __awaiter(void 0, void 0, void 0, function* () {
63
+ const program = (0, dev_1.default)();
64
+ const args = createMockArgs({});
65
+ process.argv = args;
66
+ yield program.parseAsync(args);
67
+ const opts = program.opts();
68
+ expect(opts.config).toEqual('./page-layout.yaml');
69
+ expect(opts.port).toEqual('4040');
70
+ expect(opts.open).toEqual(true);
71
+ expect(opts.stylesheet).toBeUndefined();
72
+ }));
73
+ it('correctly handles command arguments', () => __awaiter(void 0, void 0, void 0, function* () {
74
+ const config = './src/__tests__/layout.yaml';
75
+ const port = '3000';
76
+ const open = false;
77
+ const stylesheet = './src/__tests__/styles.css';
78
+ const program = (0, dev_1.default)();
79
+ const args = createMockArgs({
80
+ config,
81
+ port,
82
+ open,
83
+ stylesheet,
84
+ });
85
+ process.argv = args;
86
+ yield program.parseAsync(args);
87
+ const opts = program.opts();
88
+ expect(opts.config).toEqual(config);
89
+ expect(opts.port).toEqual(port);
90
+ expect(opts.open).toEqual(open);
91
+ expect(opts.stylesheet).toEqual(stylesheet);
92
+ }));
93
+ it('loads the layout definition and starts the server', () => __awaiter(void 0, void 0, void 0, function* () {
94
+ const config = './src/__tests__/layout.yaml';
95
+ const mockLayout = { name: 'Test Layout' };
96
+ definitions_1.loadLayoutDefinition.mockResolvedValue(mockLayout);
97
+ const program = (0, dev_1.default)();
98
+ const args = createMockArgs({ config });
99
+ process.argv = args;
100
+ yield program.parseAsync(args);
101
+ expect(definitions_1.loadLayoutDefinition).toHaveBeenCalledWith(config);
102
+ expect(mockLoggerInfoFn).toHaveBeenNthCalledWith(1, `Loading layout definition from ${config}`);
103
+ expect(mockLoggerInfoFn).toHaveBeenNthCalledWith(2, 'Starting development server...');
104
+ expect(server_1.startDevServer).toHaveBeenCalledWith(expect.objectContaining({
105
+ configPath: path_1.default.resolve(config),
106
+ layoutDefinition: mockLayout,
107
+ }));
108
+ }));
109
+ it('parses and passes zone content to the server', () => __awaiter(void 0, void 0, void 0, function* () {
110
+ const mockLayout = { name: 'Test Layout' };
111
+ definitions_1.loadLayoutDefinition.mockResolvedValue(mockLayout);
112
+ const zoneContent = {
113
+ main: ['./example.main.0.html', './example.main.1.html'],
114
+ aside: ['./example.aside.html'],
115
+ };
116
+ const program = (0, dev_1.default)();
117
+ const args = createMockArgs({ zoneContent });
118
+ process.argv = args;
119
+ yield program.parseAsync(args);
120
+ expect(server_1.startDevServer).toHaveBeenCalledWith(expect.objectContaining({
121
+ zoneContent,
122
+ }));
123
+ }));
124
+ it('parses and passes layout options to the server', () => __awaiter(void 0, void 0, void 0, function* () {
125
+ const mockLayout = { name: 'Test Layout' };
126
+ definitions_1.loadLayoutDefinition.mockResolvedValue(mockLayout);
127
+ const layoutOptions = {
128
+ sizing: 'large',
129
+ theme: 'dark',
130
+ };
131
+ const program = (0, dev_1.default)();
132
+ const args = createMockArgs({ layoutOptions });
133
+ process.argv = args;
134
+ yield program.parseAsync(args);
135
+ expect(server_1.startDevServer).toHaveBeenCalledWith(expect.objectContaining({
136
+ layoutOptions,
137
+ }));
138
+ }));
139
+ it('handles failure to load layout definition', () => __awaiter(void 0, void 0, void 0, function* () {
140
+ const config = './src/__tests__/layout.yaml';
141
+ definitions_1.loadLayoutDefinition.mockResolvedValue(undefined);
142
+ const originalError = mockLoggerErrorFn;
143
+ mockLoggerErrorFn.mockClear();
144
+ const program = (0, dev_1.default)();
145
+ const args = createMockArgs({ config });
146
+ process.argv = args;
147
+ yield program.parseAsync(args);
148
+ expect(mockLoggerErrorFn).toHaveBeenCalledWith(expect.stringContaining(`Failed to load layout definition from ${config}`));
149
+ }));
150
+ it('handles server startup error', () => __awaiter(void 0, void 0, void 0, function* () {
151
+ const mockLayout = { name: 'Test Layout' };
152
+ definitions_1.loadLayoutDefinition.mockResolvedValue(mockLayout);
153
+ server_1.startDevServer.mockRejectedValue(new Error('Server start failed'));
154
+ const originalError = mockLoggerErrorFn;
155
+ mockLoggerErrorFn.mockClear();
156
+ const program = (0, dev_1.default)();
157
+ const args = createMockArgs({});
158
+ process.argv = args;
159
+ yield program.parseAsync(args);
160
+ expect(mockLoggerErrorFn).toHaveBeenCalledWith(expect.stringContaining('Server start failed'));
161
+ }));
162
+ });
@@ -5,11 +5,13 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  const commander_1 = require("commander");
7
7
  const deploy_1 = __importDefault(require("./deploy/deploy"));
8
+ const dev_1 = __importDefault(require("./dev/dev"));
8
9
  const createLayoutsCommand = () => {
9
10
  const layoutsCommand = new commander_1.Command('layouts');
10
11
  layoutsCommand
11
12
  .description('Page Contents Layouts Commands')
12
- .addCommand((0, deploy_1.default)());
13
+ .addCommand((0, deploy_1.default)())
14
+ .addCommand((0, dev_1.default)());
13
15
  return layoutsCommand;
14
16
  };
15
17
  exports.default = createLayoutsCommand;
@@ -6,10 +6,15 @@ Object.defineProperty(exports, "__esModule", { value: true });
6
6
  const commander_1 = require("commander");
7
7
  const layouts_1 = __importDefault(require("./layouts"));
8
8
  const deploy_1 = __importDefault(require("./deploy/deploy"));
9
+ const dev_1 = __importDefault(require("./dev/dev"));
9
10
  jest.mock('./deploy/deploy');
10
11
  deploy_1.default.mockImplementation(() => {
11
12
  return new commander_1.Command('mock-deploy');
12
13
  });
14
+ jest.mock('./dev/dev');
15
+ dev_1.default.mockImplementation(() => {
16
+ return new commander_1.Command('mock-dev');
17
+ });
13
18
  describe('createLayoutsCommand', () => {
14
19
  it('should create a layouts command with deploy subcommand', () => {
15
20
  const layoutsCommand = (0, layouts_1.default)();
@@ -18,5 +23,7 @@ describe('createLayoutsCommand', () => {
18
23
  expect(layoutsCommand.description()).toBe('Page Contents Layouts Commands');
19
24
  expect(deploy_1.default).toHaveBeenCalled();
20
25
  expect(layoutsCommand.commands.map(cmd => cmd.name())).toContain('mock-deploy');
26
+ expect(dev_1.default).toHaveBeenCalled();
27
+ expect(layoutsCommand.commands.map(cmd => cmd.name())).toContain('mock-dev');
21
28
  });
22
29
  });
@@ -1,5 +1,6 @@
1
1
  import { z } from 'zod';
2
2
  export declare function loadLayoutDefinition(layoutFile: string): Promise<LayoutDefinition>;
3
+ export declare function loadLayoutFromFile(layoutFile: string): Promise<InputLayoutDefinition>;
3
4
  export declare const BaseLayoutDefinition: z.ZodObject<{
4
5
  /**
5
6
  * User defined identifier for a Page Layout
@@ -43,7 +43,7 @@ var __rest = (this && this.__rest) || function (s, e) {
43
43
  return t;
44
44
  };
45
45
  Object.defineProperty(exports, "__esModule", { value: true });
46
- exports.LayoutDefinition = exports.InputLayoutDefinition = exports.BaseLayoutDefinition = exports.loadLayoutDefinition = void 0;
46
+ exports.LayoutDefinition = exports.InputLayoutDefinition = exports.BaseLayoutDefinition = exports.loadLayoutFromFile = exports.loadLayoutDefinition = void 0;
47
47
  const fs = __importStar(require("node:fs/promises"));
48
48
  const path = __importStar(require("node:path"));
49
49
  const zod_1 = require("zod");
@@ -82,6 +82,7 @@ function loadLayoutFromFile(layoutFile) {
82
82
  }
83
83
  });
84
84
  }
85
+ exports.loadLayoutFromFile = loadLayoutFromFile;
85
86
  function loadTemplate(layoutDirectory, templateFile) {
86
87
  return __awaiter(this, void 0, void 0, function* () {
87
88
  try {
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Parse zones list from command line
3
+ * Supports multiple formats:
4
+ * - Single pair: 'main=./main.html' or 'main:./main.html'
5
+ * - Comma-separated list: 'main=./main.html,aside=./aside.html' or 'main:./main.html,aside:./aside.html'
6
+ * - Multiple --zones flags: merged together
7
+ *
8
+ * @param value Current value being processed
9
+ * @param previous Previously processed value (used for multiple flags)
10
+ * @returns Record of zone names to file paths
11
+ */
12
+ export declare function parseZonesList(value: string, previous: Record<string, string[]>): {
13
+ [x: string]: string[];
14
+ };
15
+ /**
16
+ * Parse options list from command line
17
+ * Supports multiple formats:
18
+ * - Single pair: 'key=value' or 'key:value'
19
+ * - Comma-separated list: 'key1=value1,key2=value2' or 'key1:value1,key2:value2'
20
+ * - Multiple --options flags: later values override earlier ones
21
+ *
22
+ * @param value Current value being processed
23
+ * @param previous Previously processed value (used for multiple flags)
24
+ * @returns Record of option names to values
25
+ */
26
+ export declare function parseOptionsList(value: string, previous: Record<string, string>): {
27
+ [x: string]: string;
28
+ };
@@ -0,0 +1,84 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.parseOptionsList = exports.parseZonesList = void 0;
4
+ /**
5
+ * Parse zones list from command line
6
+ * Supports multiple formats:
7
+ * - Single pair: 'main=./main.html' or 'main:./main.html'
8
+ * - Comma-separated list: 'main=./main.html,aside=./aside.html' or 'main:./main.html,aside:./aside.html'
9
+ * - Multiple --zones flags: merged together
10
+ *
11
+ * @param value Current value being processed
12
+ * @param previous Previously processed value (used for multiple flags)
13
+ * @returns Record of zone names to file paths
14
+ */
15
+ function parseZonesList(value, previous) {
16
+ const result = Object.assign({}, previous);
17
+ if (!value)
18
+ return result;
19
+ // Split comma-separated values if present
20
+ const parts = value.includes(',') ? value.split(',') : [value];
21
+ for (const part of parts) {
22
+ let zoneName;
23
+ let filePath;
24
+ // Handle both colon and equals separators
25
+ if (part.includes('=')) {
26
+ [zoneName, filePath] = part.split('=');
27
+ }
28
+ else if (part.includes(':')) {
29
+ [zoneName, filePath] = part.split(':');
30
+ }
31
+ else {
32
+ continue; // Skip invalid format
33
+ }
34
+ // Skip empty zone names or file paths
35
+ if (!zoneName || !filePath) {
36
+ continue;
37
+ }
38
+ if (!result[zoneName]) {
39
+ result[zoneName] = [];
40
+ }
41
+ result[zoneName].push(filePath);
42
+ }
43
+ return result;
44
+ }
45
+ exports.parseZonesList = parseZonesList;
46
+ /**
47
+ * Parse options list from command line
48
+ * Supports multiple formats:
49
+ * - Single pair: 'key=value' or 'key:value'
50
+ * - Comma-separated list: 'key1=value1,key2=value2' or 'key1:value1,key2:value2'
51
+ * - Multiple --options flags: later values override earlier ones
52
+ *
53
+ * @param value Current value being processed
54
+ * @param previous Previously processed value (used for multiple flags)
55
+ * @returns Record of option names to values
56
+ */
57
+ function parseOptionsList(value, previous) {
58
+ const result = Object.assign({}, previous);
59
+ if (!value)
60
+ return result;
61
+ // Split comma-separated values if present
62
+ const parts = value.includes(',') ? value.split(',') : [value];
63
+ for (const part of parts) {
64
+ let optionName;
65
+ let optionValue;
66
+ // Handle both colon and equals separators
67
+ if (part.includes('=')) {
68
+ [optionName, optionValue] = part.split('=');
69
+ }
70
+ else if (part.includes(':')) {
71
+ [optionName, optionValue] = part.split(':');
72
+ }
73
+ else {
74
+ continue; // Skip invalid format
75
+ }
76
+ // Skip empty option names or values
77
+ if (!optionName || !optionValue) {
78
+ continue;
79
+ }
80
+ result[optionName] = optionValue;
81
+ }
82
+ return result;
83
+ }
84
+ exports.parseOptionsList = parseOptionsList;
@@ -0,0 +1 @@
1
+ export {};