Skip to content

Commit a71aed2

Browse files
authored
Merge pull request #1514 from contentstack/staging
DX | 13-08-2024 | Hotfix
2 parents 1301f79 + 6a62703 commit a71aed2

File tree

12 files changed

+139
-77
lines changed

12 files changed

+139
-77
lines changed

package-lock.json

Lines changed: 3 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/contentstack-launch/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ $ npm install -g @contentstack/cli-launch
1919
$ csdx COMMAND
2020
running command...
2121
$ csdx (--version|-v)
22-
@contentstack/cli-launch/1.1.0 darwin-arm64 node-v22.2.0
22+
@contentstack/cli-launch/1.2.0 darwin-arm64 node-v22.2.0
2323
$ csdx --help [COMMAND]
2424
USAGE
2525
$ csdx COMMAND

packages/contentstack-launch/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@contentstack/cli-launch",
3-
"version": "1.1.0",
3+
"version": "1.2.0",
44
"description": "Launch related operations",
55
"author": "Contentstack CLI",
66
"bin": {

packages/contentstack-launch/src/adapters/file-upload.ts

Lines changed: 70 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,9 @@ import find from 'lodash/find';
55
import FormData from 'form-data';
66
import filter from 'lodash/filter';
77
import includes from 'lodash/includes';
8+
import isEmpty from 'lodash/isEmpty';
89
import { basename, resolve } from 'path';
9-
import { cliux, configHandler, ux } from '@contentstack/cli-utilities';
10+
import { cliux, configHandler, HttpClient, ux } from '@contentstack/cli-utilities';
1011
import { createReadStream, existsSync, PathLike, statSync } from 'fs';
1112

1213
import { print } from '../util';
@@ -263,28 +264,80 @@ export default class FileUpload extends BaseClass {
263264
* @memberof FileUpload
264265
*/
265266
async uploadFile(fileName: string, filePath: PathLike): Promise<void> {
266-
const { uploadUrl, fields } = this.signedUploadUrlData;
267+
const { uploadUrl, fields, headers } = this.signedUploadUrlData;
267268
const formData = new FormData();
268269

269-
for (const { formFieldKey, formFieldValue } of fields) {
270-
formData.append(formFieldKey, formFieldValue);
270+
if (!isEmpty(fields)) {
271+
for (const { formFieldKey, formFieldValue } of fields) {
272+
formData.append(formFieldKey, formFieldValue);
273+
}
274+
275+
formData.append('file', createReadStream(filePath), fileName);
276+
await this.submitFormData(formData, uploadUrl);
277+
} else if (!isEmpty(headers)) {
278+
await this.uploadWithHttpClient(filePath, uploadUrl, headers, fileName);
271279
}
280+
}
272281

273-
formData.append('file', createReadStream(filePath) as any, fileName);
282+
private async submitFormData(formData: FormData, uploadUrl: string): Promise<void> {
283+
ux.action.start('Starting file upload...');
284+
try {
285+
await new Promise<void>((resolve, reject) => {
286+
formData.submit(uploadUrl, (error, res) => {
287+
if (error) {
288+
reject(error);
289+
} else {
290+
resolve();
291+
}
292+
});
293+
});
274294

275-
await new Promise<void>((resolve) => {
276-
ux.action.start('Starting file upload...');
277-
formData.submit(uploadUrl, (error, res) => {
278-
if (error) {
279-
ux.action.stop('File upload failed!');
280-
this.log('File upload failed. Please try again.', 'error');
281-
this.log(error, 'error');
282-
this.exit(1);
283-
}
295+
ux.action.stop();
296+
} catch (error) {
297+
ux.action.stop('File upload failed!');
298+
this.log('File upload failed. Please try again.', 'error');
299+
if (error instanceof Error) {
300+
this.log(error.message, 'error');
301+
}
302+
this.exit(1);
303+
}
304+
}
305+
306+
private async uploadWithHttpClient(
307+
filePath: PathLike,
308+
uploadUrl: string,
309+
headers: Array<{ key: string; value: string }>,
310+
fileName: string,
311+
): Promise<void> {
312+
ux.action.start('Starting file upload...');
313+
const httpClient = new HttpClient();
314+
const form = new FormData();
315+
form.append('file', createReadStream(filePath), fileName);
284316

285-
resolve();
317+
// Convert headers array to a headers object
318+
const headerObject = headers.reduce((acc, { key, value }) => {
319+
acc[key] = value;
320+
return acc;
321+
}, {} as Record<string, string>);
322+
323+
try {
324+
const response = await httpClient.headers(headerObject).put(uploadUrl, form);
325+
const { status } = response;
326+
327+
if (status >= 200 && status < 300) {
286328
ux.action.stop();
287-
});
288-
});
329+
} else {
330+
ux.action.stop('File upload failed!');
331+
this.log('File upload failed. Please try again.', 'error');
332+
this.exit(1);
333+
}
334+
} catch (error) {
335+
ux.action.stop('File upload failed!');
336+
this.log('File upload failed. Please try again.', 'error');
337+
if (error instanceof Error) {
338+
this.log(`Error: ${error.message}`, 'error');
339+
}
340+
this.exit(1);
341+
}
289342
}
290343
}

packages/contentstack-launch/src/base-command.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ import {
1818
} from '@contentstack/cli-utilities';
1919

2020
import config from './config';
21-
import { GraphqlApiClient, Logger } from './util';
21+
import { getLaunchHubUrl, GraphqlApiClient, Logger } from './util';
2222
import { ConfigType, LogFn, Providers } from './types';
2323

2424
export type Flags<T extends typeof Command> = Interfaces.InferredFlags<(typeof BaseCommand)['baseFlags'] & T['flags']>;
@@ -105,7 +105,7 @@ export abstract class BaseCommand<T extends typeof Command> extends Command {
105105
this.flags['data-dir'] || this.flags.config
106106
? this.flags.config || resolve(this.flags['data-dir'], config.configName)
107107
: resolve(process.cwd(), config.configName);
108-
const baseUrl = config.launchBaseUrl || (config.launchHubUrls as Record<string, string>)[this.cmaAPIUrl];
108+
const baseUrl = config.launchBaseUrl || getLaunchHubUrl();
109109
this.sharedConfig = {
110110
...require('./config').default,
111111
currentConfig: {},

packages/contentstack-launch/src/config/index.ts

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -29,13 +29,7 @@ const config = {
2929
GITPROVIDER: 'GitHub',
3030
FILEUPLOAD: 'FileUpload',
3131
},
32-
launchHubUrls: {
33-
// NOTE CMA url used as launch url mapper to avoid conflict if user used any custom name
34-
'https://api.contentstack.io': 'https://launch-api.contentstack.com',
35-
'https://eu-api.contentstack.com': '',
36-
'https://azure-na-api.contentstack.com': '',
37-
'https://azure-eu-api.contentstack.com': '',
38-
},
32+
launchHubUrls: '',
3933
launchBaseUrl: '',
4034
supportedAdapters: ['GitHub'],
4135
deploymentStatus: ['LIVE', 'FAILED', 'SKIPPED', 'DEPLOYED'],
@@ -45,7 +39,7 @@ const config = {
4539
'Manually add custom variables to the list',
4640
'Import variables from the local env file',
4741
],
48-
variableType: ''
42+
variableType: '',
4943
};
5044

5145
export default config;

packages/contentstack-launch/src/graphql/mutation.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,10 @@ const createSignedUploadUrlMutation: DocumentNode = gql`
2828
formFieldKey
2929
formFieldValue
3030
}
31+
headers{
32+
key
33+
value
34+
}
3135
}
3236
}
3337
`;

packages/contentstack-launch/src/util/common-utility.ts

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,4 +133,22 @@ async function selectProject(options: {
133133
}
134134
}
135135

136-
export { getOrganizations, selectOrg, selectProject };
136+
function getLaunchHubUrl(): string {
137+
const { cma } = configHandler.get('region') || {};
138+
if (!cma) {
139+
throw new Error('Region not configured. Please set the region with command $ csdx config:set:region');
140+
}
141+
142+
let launchHubBaseUrl = cma.replace('api', 'launch-api');
143+
144+
if (launchHubBaseUrl.startsWith('http')) {
145+
launchHubBaseUrl = launchHubBaseUrl.split('//')[1];
146+
}
147+
148+
launchHubBaseUrl = launchHubBaseUrl.startsWith('dev11') ? launchHubBaseUrl.replace('dev11', 'dev') : launchHubBaseUrl;
149+
launchHubBaseUrl = launchHubBaseUrl.endsWith('io') ? launchHubBaseUrl.replace('io', 'com') : launchHubBaseUrl;
150+
151+
return `https://${launchHubBaseUrl}`;
152+
}
153+
154+
export { getOrganizations, selectOrg, selectProject, getLaunchHubUrl };

packages/contentstack-launch/src/util/logs-polling-utilities.ts

Lines changed: 33 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,9 @@
1-
import EventEmitter from "events";
2-
import { ux } from "@contentstack/cli-utilities";
3-
import { ApolloClient, ObservableQuery } from "@apollo/client/core";
1+
import EventEmitter from 'events';
2+
import { ux } from '@contentstack/cli-utilities';
3+
import { ApolloClient, ObservableQuery } from '@apollo/client/core';
44

5-
import { LogPollingInput, ConfigType } from "../types";
6-
import {
7-
deploymentQuery,
8-
deploymentLogsQuery,
9-
serverlessLogsQuery,
10-
} from "../graphql";
5+
import { LogPollingInput, ConfigType } from '../types';
6+
import { deploymentQuery, deploymentLogsQuery, serverlessLogsQuery } from '../graphql';
117

128
export default class LogPolling {
139
private config: ConfigType;
@@ -69,15 +65,15 @@ export default class LogPolling {
6965
let statusWatchQuery = this.getDeploymentStatus();
7066
statusWatchQuery.subscribe(({ data, errors, error }) => {
7167
if (error) {
72-
this.$event.emit("deployment-logs", {
68+
this.$event.emit('deployment-logs', {
7369
message: error?.message,
74-
msgType: "error",
70+
msgType: 'error',
7571
});
7672
}
7773
if (errors?.length && data === null) {
78-
this.$event.emit("deployment-logs", {
74+
this.$event.emit('deployment-logs', {
7975
message: errors,
80-
msgType: "error",
76+
msgType: 'error',
8177
});
8278
statusWatchQuery.stopPolling();
8379
}
@@ -110,46 +106,45 @@ export default class LogPolling {
110106
{
111107
deploymentUid: string | undefined;
112108
}
113-
>
109+
>,
114110
): void {
115111
let timestamp: number = 0;
116112
logsWatchQuery.subscribe(({ data, errors, error }) => {
117-
ux.action.start("Loading deployment logs...");
113+
ux.action.start('Loading deployment logs...');
118114

119115
if (error) {
120116
ux.action.stop();
121-
this.$event.emit("deployment-logs", {
117+
this.$event.emit('deployment-logs', {
122118
message: error?.message,
123-
msgType: "error",
119+
msgType: 'error',
124120
});
125-
this.$event.emit("deployment-logs", {
126-
message: "DONE",
127-
msgType: "debug",
121+
this.$event.emit('deployment-logs', {
122+
message: 'DONE',
123+
msgType: 'debug',
128124
});
129125
logsWatchQuery.stopPolling();
130126
}
131127
if (errors?.length && data === null) {
132128
ux.action.stop();
133-
this.$event.emit("deployment-logs", {
129+
this.$event.emit('deployment-logs', {
134130
message: errors,
135-
msgType: "error",
131+
msgType: 'error',
136132
});
137-
this.$event.emit("deployment-logs", {
138-
message: "DONE",
139-
msgType: "debug",
133+
this.$event.emit('deployment-logs', {
134+
message: 'DONE',
135+
msgType: 'debug',
140136
});
141137
logsWatchQuery.stopPolling();
142138
}
143139
if (this.deploymentStatus) {
144140
let logsData = data?.getLogs;
145141
if (logsData?.length) {
146142
ux.action.stop();
147-
this.$event.emit("deployment-logs", {
143+
this.$event.emit('deployment-logs', {
148144
message: logsData,
149-
msgType: "info",
145+
msgType: 'info',
150146
});
151-
timestamp =
152-
new Date(logsData[logsData.length - 1].timestamp).getTime() + 1;
147+
timestamp = new Date(logsData[logsData.length - 1].timestamp).getTime() + 1;
153148
logsWatchQuery.setVariables({
154149
deploymentUid: this.config.deployment,
155150
timestamp: new Date(timestamp).toISOString(),
@@ -158,9 +153,9 @@ export default class LogPolling {
158153

159154
if (this.config.deploymentStatus.includes(this.deploymentStatus)) {
160155
logsWatchQuery.stopPolling();
161-
this.$event.emit("deployment-logs", {
162-
message: "DONE",
163-
msgType: "debug",
156+
this.$event.emit('deployment-logs', {
157+
message: 'DONE',
158+
msgType: 'debug',
164159
});
165160
}
166161
}
@@ -208,27 +203,26 @@ export default class LogPolling {
208203
endTime: number;
209204
};
210205
}
211-
>
206+
>,
212207
): void {
213208
serverLogsWatchQuery.subscribe(({ data, errors, error }) => {
214-
ux.action.start("Loading server logs...");
209+
ux.action.start('Loading server logs...');
215210
if (error) {
216211
ux.action.stop();
217-
this.$event.emit("server-logs", { message: error?.message, msgType: "error" });
212+
this.$event.emit('server-logs', { message: error?.message, msgType: 'error' });
218213
}
219214
if (errors?.length && data === null) {
220215
ux.action.stop();
221-
this.$event.emit("server-logs", { message: errors, msgType: "error" });
216+
this.$event.emit('server-logs', { message: errors, msgType: 'error' });
222217
serverLogsWatchQuery.stopPolling();
223218
}
224219

225220
let logsData = data?.getServerlessLogs?.logs;
226221
let logsLength = logsData?.length;
227222
if (logsLength > 0) {
228223
ux.action.stop();
229-
this.$event.emit("server-logs", { message: logsData, msgType: "info" });
230-
this.startTime =
231-
new Date(logsData[logsLength - 1].timestamp).getTime() + 1;
224+
this.$event.emit('server-logs', { message: logsData, msgType: 'info' });
225+
this.startTime = new Date(logsData[logsLength - 1].timestamp).getTime() + 1;
232226
this.endTime = this.startTime + 10 * 1000;
233227
} else if (logsLength === 0) {
234228
this.endTime = this.endTime + 10 * 1000;
@@ -243,4 +237,3 @@ export default class LogPolling {
243237
});
244238
}
245239
}
246-

packages/contentstack/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ $ npm install -g @contentstack/cli
1818
$ csdx COMMAND
1919
running command...
2020
$ csdx (--version|-v)
21-
@contentstack/cli/1.22.0 darwin-arm64 node-v22.2.0
21+
@contentstack/cli/1.23.0 darwin-arm64 node-v22.2.0
2222
$ csdx --help [COMMAND]
2323
USAGE
2424
$ csdx COMMAND

0 commit comments

Comments
 (0)