Skip to content

Commit 26b92de

Browse files
feat: prompt for streaming/buffered response mode via text input
1 parent 2a485b3 commit 26b92de

7 files changed

Lines changed: 987 additions & 731 deletions

File tree

.talismanrc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,5 @@ fileignoreconfig:
99
- filename: test/unit/commands/rollback.test.ts
1010
checksum: d1f931f2d9a397131409399ad6463653e28b5a2224e870b641d9ba57c4418f18
1111
- filename: package-lock.json
12-
checksum: d24dfc90fb69ded83dfe4f6839cd17801e65a1f84be04244fb917e6bef6b5cc6
12+
checksum: e8262e57f73252240a076fa99be712c4d1403c058378cc2bb23f897bb4e45648
1313
version: "1.0"

package-lock.json

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

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.10.0",
3+
"version": "1.10.1",
44
"description": "Launch related operations",
55
"author": "Contentstack CLI",
66
"bin": {

src/adapters/file-upload.test.ts

Lines changed: 131 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -312,7 +312,7 @@ describe('FileUpload Adapter', () => {
312312
(cliux.inquire as jest.Mock).mockResolvedValueOnce('npm run build');
313313
(cliux.inquire as jest.Mock).mockResolvedValueOnce('./dist');
314314
(cliux.inquire as jest.Mock).mockResolvedValueOnce('npm start');
315-
(cliux.inquire as jest.Mock).mockResolvedValueOnce(true);
315+
(cliux.inquire as jest.Mock).mockResolvedValueOnce('streaming');
316316

317317
const createSignedUploadUrlMock = jest
318318
.spyOn(FileUpload.prototype as any, 'createSignedUploadUrl')
@@ -340,12 +340,15 @@ describe('FileUpload Adapter', () => {
340340

341341
await fileUploadInstance.prepareAndUploadNewProjectFile();
342342

343-
expect(cliux.inquire).toHaveBeenCalledWith({
344-
type: 'confirm',
345-
name: 'enableStreamingResponse',
346-
message: 'Enable Streaming Responses',
347-
default: false,
348-
});
343+
expect(cliux.inquire).toHaveBeenCalledWith(
344+
expect.objectContaining({
345+
type: 'input',
346+
name: 'responseMode',
347+
message: 'Response Mode (s: streaming, b: buffered)',
348+
default: 'buffered',
349+
validate: expect.any(Function),
350+
}),
351+
);
349352
expect(fileUploadInstance.config.isStreamingEnabled).toBe(true);
350353

351354
createSignedUploadUrlMock.mockRestore();
@@ -386,7 +389,7 @@ describe('FileUpload Adapter', () => {
386389
await fileUploadInstance.prepareAndUploadNewProjectFile();
387390

388391
const enableStreamingCalls = (cliux.inquire as jest.Mock).mock.calls.filter(
389-
(call) => call[0]?.name === 'enableStreamingResponse',
392+
(call) => call[0]?.name === 'responseMode',
390393
);
391394
expect(enableStreamingCalls.length).toBe(0);
392395
expect(fileUploadInstance.config.isStreamingEnabled).toBe(true);
@@ -429,7 +432,7 @@ describe('FileUpload Adapter', () => {
429432
await fileUploadInstance.prepareAndUploadNewProjectFile();
430433

431434
const enableStreamingCalls = (cliux.inquire as jest.Mock).mock.calls.filter(
432-
(call) => call[0]?.name === 'enableStreamingResponse',
435+
(call) => call[0]?.name === 'responseMode',
433436
);
434437
expect(enableStreamingCalls.length).toBe(0);
435438
expect(fileUploadInstance.config.isStreamingEnabled).toBe(false);
@@ -444,7 +447,7 @@ describe('FileUpload Adapter', () => {
444447
(cliux.inquire as jest.Mock).mockResolvedValueOnce('Default');
445448
(cliux.inquire as jest.Mock).mockResolvedValueOnce('npm run build');
446449
(cliux.inquire as jest.Mock).mockResolvedValueOnce('./public');
447-
(cliux.inquire as jest.Mock).mockResolvedValueOnce(true);
450+
(cliux.inquire as jest.Mock).mockResolvedValueOnce('streaming');
448451

449452
const createSignedUploadUrlMock = jest
450453
.spyOn(FileUpload.prototype as any, 'createSignedUploadUrl')
@@ -479,12 +482,15 @@ describe('FileUpload Adapter', () => {
479482
(call) => call[0]?.name === 'serverCommand',
480483
);
481484
expect(serverCommandCalls.length).toBe(0);
482-
expect(cliux.inquire).toHaveBeenCalledWith({
483-
type: 'confirm',
484-
name: 'enableStreamingResponse',
485-
message: 'Enable Streaming Responses',
486-
default: false,
487-
});
485+
expect(cliux.inquire).toHaveBeenCalledWith(
486+
expect.objectContaining({
487+
type: 'input',
488+
name: 'responseMode',
489+
message: 'Response Mode (s: streaming, b: buffered)',
490+
default: 'buffered',
491+
validate: expect.any(Function),
492+
}),
493+
);
488494
expect(fileUploadInstance.config.isStreamingEnabled).toBe(true);
489495

490496
createSignedUploadUrlMock.mockRestore();
@@ -529,7 +535,7 @@ describe('FileUpload Adapter', () => {
529535
await fileUploadInstance.prepareAndUploadNewProjectFile();
530536

531537
const enableStreamingCalls = (cliux.inquire as jest.Mock).mock.calls.filter(
532-
(call) => call[0]?.name === 'enableStreamingResponse',
538+
(call) => call[0]?.name === 'responseMode',
533539
);
534540
expect(enableStreamingCalls.length).toBe(0);
535541
expect(fileUploadInstance.config.isStreamingEnabled).toBe(false);
@@ -539,6 +545,114 @@ describe('FileUpload Adapter', () => {
539545
uploadFileMock.mockRestore();
540546
handleEnvImportFlowMock.mockRestore();
541547
});
548+
549+
it.each([
550+
['s', true],
551+
['streaming', true],
552+
['STREAMING', true],
553+
[' Streaming ', true],
554+
['b', false],
555+
['buffered', false],
556+
['BUFFERED', false],
557+
[' Buffered ', false],
558+
])('should map Response Mode input "%s" to isStreamingEnabled %s', async (input, expected) => {
559+
(cliux.inquire as jest.Mock).mockResolvedValueOnce('test-project');
560+
(cliux.inquire as jest.Mock).mockResolvedValueOnce('Default');
561+
(cliux.inquire as jest.Mock).mockResolvedValueOnce('npm run build');
562+
(cliux.inquire as jest.Mock).mockResolvedValueOnce('./public');
563+
(cliux.inquire as jest.Mock).mockResolvedValueOnce(input);
564+
565+
const createSignedUploadUrlMock = jest
566+
.spyOn(FileUpload.prototype as any, 'createSignedUploadUrl')
567+
.mockResolvedValue({ uploadUid: 'test-upload-uid' });
568+
const archiveMock = jest
569+
.spyOn(FileUpload.prototype as any, 'archive')
570+
.mockResolvedValue({ zipName: 'test.zip', zipPath: '/path/to/test.zip', projectName: 'test-project' });
571+
const uploadFileMock = jest
572+
.spyOn(FileUpload.prototype as any, 'uploadFile')
573+
.mockResolvedValue(undefined);
574+
575+
const fileUploadInstance = new FileUpload({
576+
config: {
577+
flags: {
578+
'response-mode': undefined,
579+
},
580+
framework: 'GATSBY',
581+
supportedFrameworksForServerCommands: ['ANGULAR', 'OTHER', 'REMIX', 'NUXT'],
582+
outputDirectories: { GATSBY: './public' },
583+
},
584+
log: logMock,
585+
exit: exitMock,
586+
} as any);
587+
588+
const handleEnvImportFlowMock = jest
589+
.spyOn(fileUploadInstance, 'handleEnvImportFlow' as any)
590+
.mockResolvedValue(undefined);
591+
592+
await fileUploadInstance.prepareAndUploadNewProjectFile();
593+
594+
expect(fileUploadInstance.config.isStreamingEnabled).toBe(expected);
595+
596+
createSignedUploadUrlMock.mockRestore();
597+
archiveMock.mockRestore();
598+
uploadFileMock.mockRestore();
599+
handleEnvImportFlowMock.mockRestore();
600+
});
601+
602+
it('Response Mode validate should accept s/b/streaming/buffered and reject anything else', async () => {
603+
(cliux.inquire as jest.Mock).mockResolvedValueOnce('test-project');
604+
(cliux.inquire as jest.Mock).mockResolvedValueOnce('Default');
605+
(cliux.inquire as jest.Mock).mockResolvedValueOnce('npm run build');
606+
(cliux.inquire as jest.Mock).mockResolvedValueOnce('./public');
607+
(cliux.inquire as jest.Mock).mockResolvedValueOnce('streaming');
608+
609+
const createSignedUploadUrlMock = jest
610+
.spyOn(FileUpload.prototype as any, 'createSignedUploadUrl')
611+
.mockResolvedValue({ uploadUid: 'test-upload-uid' });
612+
const archiveMock = jest
613+
.spyOn(FileUpload.prototype as any, 'archive')
614+
.mockResolvedValue({ zipName: 'test.zip', zipPath: '/path/to/test.zip', projectName: 'test-project' });
615+
const uploadFileMock = jest
616+
.spyOn(FileUpload.prototype as any, 'uploadFile')
617+
.mockResolvedValue(undefined);
618+
619+
const fileUploadInstance = new FileUpload({
620+
config: {
621+
flags: {
622+
'response-mode': undefined,
623+
},
624+
framework: 'GATSBY',
625+
supportedFrameworksForServerCommands: ['ANGULAR', 'OTHER', 'REMIX', 'NUXT'],
626+
outputDirectories: { GATSBY: './public' },
627+
},
628+
log: logMock,
629+
exit: exitMock,
630+
} as any);
631+
632+
const handleEnvImportFlowMock = jest
633+
.spyOn(fileUploadInstance, 'handleEnvImportFlow' as any)
634+
.mockResolvedValue(undefined);
635+
636+
await fileUploadInstance.prepareAndUploadNewProjectFile();
637+
638+
const responseModeCall = (cliux.inquire as jest.Mock).mock.calls.find(
639+
(call) => call[0]?.name === 'responseMode',
640+
);
641+
const { validate } = responseModeCall[0];
642+
643+
expect(validate('s')).toBe(true);
644+
expect(validate('streaming')).toBe(true);
645+
expect(validate('b')).toBe(true);
646+
expect(validate('buffered')).toBe(true);
647+
expect(validate(' STREAMING ')).toBe(true);
648+
expect(validate('')).toBe('Please enter "s"/"streaming" or "b"/"buffered".');
649+
expect(validate('yes')).toBe('Please enter "s"/"streaming" or "b"/"buffered".');
650+
651+
createSignedUploadUrlMock.mockRestore();
652+
archiveMock.mockRestore();
653+
uploadFileMock.mockRestore();
654+
handleEnvImportFlowMock.mockRestore();
655+
});
542656
});
543657
});
544658

src/adapters/file-upload.ts

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -250,12 +250,21 @@ export default class FileUpload extends BaseClass {
250250
}
251251
}
252252
if (!responseMode) {
253-
this.config.isStreamingEnabled = (await cliux.inquire({
254-
type: 'confirm',
255-
name: 'enableStreamingResponse',
256-
message: 'Enable Streaming Responses',
257-
default: false,
258-
})) as boolean;
253+
const responseModeInput = (await cliux.inquire({
254+
type: 'input',
255+
name: 'responseMode',
256+
message: 'Response Mode (s: streaming, b: buffered)',
257+
default: 'buffered',
258+
validate: (input: string) => {
259+
const value = String(input).trim().toLowerCase();
260+
if (['s', 'streaming', 'b', 'buffered'].includes(value)) {
261+
return true;
262+
}
263+
return 'Please enter "s"/"streaming" or "b"/"buffered".';
264+
},
265+
})) as string;
266+
const normalizedResponseMode = String(responseModeInput ?? '').trim().toLowerCase();
267+
this.config.isStreamingEnabled = normalizedResponseMode === 's' || normalizedResponseMode === 'streaming';
259268
} else {
260269
this.config.isStreamingEnabled = responseMode === 'streaming';
261270
}

0 commit comments

Comments
 (0)