Skip to content
132 changes: 132 additions & 0 deletions src/adapters/file-upload.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -304,6 +304,138 @@ describe('FileUpload Adapter', () => {
);
expect(serverCommandCalls.length).toBe(0);
});

it('should prompt for streaming response when framework supports server commands and flag is not provided',
async () => {
(cliux.inquire as jest.Mock).mockResolvedValueOnce('test-project');
(cliux.inquire as jest.Mock).mockResolvedValueOnce('Default');
(cliux.inquire as jest.Mock).mockResolvedValueOnce('npm run build');
(cliux.inquire as jest.Mock).mockResolvedValueOnce('./dist');
(cliux.inquire as jest.Mock).mockResolvedValueOnce('npm start'); // server command prompt
(cliux.inquire as jest.Mock).mockResolvedValueOnce(true);

const createSignedUploadUrlMock = jest
.spyOn(FileUpload.prototype as any, 'createSignedUploadUrl')
.mockResolvedValue({ uploadUid: 'test-upload-uid' });
const archiveMock = jest
.spyOn(FileUpload.prototype as any, 'archive')
.mockResolvedValue({ zipName: 'test.zip', zipPath: '/path/to/test.zip', projectName: 'test-project' });
const uploadFileMock = jest
.spyOn(FileUpload.prototype as any, 'uploadFile')
.mockResolvedValue(undefined);

const fileUploadInstance = new FileUpload({
config: {
flags: {
'server-command': undefined, // Make it undefined so it prompts for server command
'enable-streaming-response': undefined,
},
framework: 'OTHER',
supportedFrameworksForServerCommands: ['ANGULAR', 'OTHER', 'REMIX', 'NUXT'],
outputDirectories: { OTHER: './dist' },
},
log: logMock,
exit: exitMock,
} as any);

await fileUploadInstance.prepareAndUploadNewProjectFile();

expect(cliux.inquire).toHaveBeenCalledWith({
type: 'confirm',
name: 'isStreamingEnabled',
message: 'Enable Streaming Responses',
default: false,
});
expect(fileUploadInstance.config.isStreamingEnabled).toBe(true);

createSignedUploadUrlMock.mockRestore();
archiveMock.mockRestore();
uploadFileMock.mockRestore();
});

it('should not prompt for streaming response when flag is provided', async () => {
(cliux.inquire as jest.Mock).mockResolvedValueOnce('test-project');
(cliux.inquire as jest.Mock).mockResolvedValueOnce('Default');
(cliux.inquire as jest.Mock).mockResolvedValueOnce('npm run build');
(cliux.inquire as jest.Mock).mockResolvedValueOnce('./dist');

const createSignedUploadUrlMock = jest
.spyOn(FileUpload.prototype as any, 'createSignedUploadUrl')
.mockResolvedValue({ uploadUid: 'test-upload-uid' });
const archiveMock = jest
.spyOn(FileUpload.prototype as any, 'archive')
.mockResolvedValue({ zipName: 'test.zip', zipPath: '/path/to/test.zip', projectName: 'test-project' });
const uploadFileMock = jest
.spyOn(FileUpload.prototype as any, 'uploadFile')
.mockResolvedValue(undefined);

const fileUploadInstance = new FileUpload({
config: {
flags: {
'server-command': 'npm start',
'enable-streaming-response': true,
},
framework: 'OTHER',
supportedFrameworksForServerCommands: ['ANGULAR', 'OTHER', 'REMIX', 'NUXT'],
outputDirectories: { OTHER: './dist' },
},
log: logMock,
exit: exitMock,
} as any);

await fileUploadInstance.prepareAndUploadNewProjectFile();

const streamingResponseCalls = (cliux.inquire as jest.Mock).mock.calls.filter(
(call) => call[0]?.name === 'isStreamingEnabled',
);
expect(streamingResponseCalls.length).toBe(0);
expect(fileUploadInstance.config.isStreamingEnabled).toBe(true);

createSignedUploadUrlMock.mockRestore();
archiveMock.mockRestore();
uploadFileMock.mockRestore();
});

it('should not prompt for streaming response when framework does not support server commands', async () => {
(cliux.inquire as jest.Mock).mockResolvedValueOnce('test-project');
(cliux.inquire as jest.Mock).mockResolvedValueOnce('Default');
(cliux.inquire as jest.Mock).mockResolvedValueOnce('npm run build');
(cliux.inquire as jest.Mock).mockResolvedValueOnce('./public');

const createSignedUploadUrlMock = jest
.spyOn(FileUpload.prototype as any, 'createSignedUploadUrl')
.mockResolvedValue({ uploadUid: 'test-upload-uid' });
const archiveMock = jest
.spyOn(FileUpload.prototype as any, 'archive')
.mockResolvedValue({ zipName: 'test.zip', zipPath: '/path/to/test.zip', projectName: 'test-project' });
const uploadFileMock = jest
.spyOn(FileUpload.prototype as any, 'uploadFile')
.mockResolvedValue(undefined);

const fileUploadInstance = new FileUpload({
config: {
flags: {
'enable-streaming-response': undefined,
},
framework: 'GATSBY',
supportedFrameworksForServerCommands: ['ANGULAR', 'OTHER', 'REMIX', 'NUXT'],
outputDirectories: { GATSBY: './public' },
},
log: logMock,
exit: exitMock,
} as any);

await fileUploadInstance.prepareAndUploadNewProjectFile();

const streamingResponseCalls = (cliux.inquire as jest.Mock).mock.calls.filter(
(call) => call[0]?.name === 'isStreamingEnabled',
);
expect(streamingResponseCalls.length).toBe(0);

createSignedUploadUrlMock.mockRestore();
archiveMock.mockRestore();
uploadFileMock.mockRestore();
});
});
});

24 changes: 23 additions & 1 deletion src/adapters/file-upload.ts
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,15 @@ export default class FileUpload extends BaseClass {
* @memberof FileUpload
*/
async createNewProject(uploadUid: string): Promise<void> {
const { framework, projectName, buildCommand, outputDirectory, environmentName, serverCommand } = this.config;
const {
framework,
projectName,
buildCommand,
outputDirectory,
environmentName,
serverCommand,
isStreamingEnabled
} = this.config;
await this.apolloClient
.mutate({
mutation: importProjectMutation,
Expand All @@ -130,6 +138,7 @@ export default class FileUpload extends BaseClass {
environmentVariables: map(this.envVariables, ({ key, value }) => ({ key, value })),
buildCommand: buildCommand === undefined || buildCommand === null ? 'npm run build' : buildCommand,
...(serverCommand && serverCommand.trim() !== '' ? { serverCommand } : {}),
...(isStreamingEnabled !== undefined ? { isStreamingEnabled } : {}),
},
},
skipGitData: true,
Expand Down Expand Up @@ -167,6 +176,7 @@ export default class FileUpload extends BaseClass {
'variable-type': variableType,
'env-variables': envVariables,
'server-command': serverCommand,
'enable-streaming-response': isStreamingEnabled,
alias,
} = this.config.flags;
const { token, apiKey } = configHandler.get(`tokens.${alias}`) ?? {};
Expand Down Expand Up @@ -238,6 +248,18 @@ export default class FileUpload extends BaseClass {
} else {
this.config.serverCommand = serverCommand;
}

if (isStreamingEnabled === undefined) {
const isStreamingEnabledInput = await cliux.inquire({
type: 'confirm',
name: 'isStreamingEnabled',
message: 'Enable Streaming Responses',
default: false,
});
this.config.isStreamingEnabled = isStreamingEnabledInput as boolean;
} else {
this.config.isStreamingEnabled = isStreamingEnabled as unknown as boolean;
}
Comment on lines +252 to +262
}
this.config.variableType = variableType as unknown as string;
this.config.envVariables = envVariables;
Expand Down
111 changes: 111 additions & 0 deletions src/adapters/github.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -564,5 +564,116 @@ describe('GitHub Adapter', () => {
);
expect(serverCommandCalls.length).toBe(0);
});

it('should prompt for streaming response when framework supports server commands and flag is not provided',
async () => {
(ux.inquire as jest.Mock).mockResolvedValueOnce('test-project');
(ux.inquire as jest.Mock).mockResolvedValueOnce('Default');
(ux.inquire as jest.Mock).mockResolvedValueOnce('npm run build');
(ux.inquire as jest.Mock).mockResolvedValueOnce('./dist');
(ux.inquire as jest.Mock).mockResolvedValueOnce('npm start');
(ux.inquire as jest.Mock).mockResolvedValueOnce(true);

const githubInstance = new GitHub({
config: {
flags: {
'server-command': undefined, // Make it undefined so it prompts for server command
'enable-streaming-response': undefined,
},
framework: 'OTHER',
repository: { fullName: 'test-user/repo', name: 'repo' },
supportedFrameworksForServerCommands: ['ANGULAR', 'OTHER', 'REMIX', 'NUXT'],
outputDirectories: { OTHER: './dist' },
},
log: logMock,
exit: exitMock,
} as any);

const handleEnvImportFlowMock = jest
.spyOn(githubInstance, 'handleEnvImportFlow' as any)
.mockResolvedValue(undefined);

await githubInstance.prepareForNewProjectCreation();

expect(ux.inquire).toHaveBeenCalledWith({
type: 'confirm',
name: 'isStreamingEnabled',
message: 'Enable Streaming Responses',
default: false,
});
expect(githubInstance.config.isStreamingEnabled).toBe(true);

handleEnvImportFlowMock.mockRestore();
});

it('should not prompt for streaming response when flag is provided', async () => {
(ux.inquire as jest.Mock).mockResolvedValueOnce('test-project');
(ux.inquire as jest.Mock).mockResolvedValueOnce('Default');
(ux.inquire as jest.Mock).mockResolvedValueOnce('npm run build');
(ux.inquire as jest.Mock).mockResolvedValueOnce('./dist');

const githubInstance = new GitHub({
config: {
flags: {
'server-command': 'npm start',
'enable-streaming-response': true,
},
framework: 'OTHER',
repository: { fullName: 'test-user/repo', name: 'repo' },
supportedFrameworksForServerCommands: ['ANGULAR', 'OTHER', 'REMIX', 'NUXT'],
outputDirectories: { OTHER: './dist' },
},
log: logMock,
exit: exitMock,
} as any);

const handleEnvImportFlowMock = jest
.spyOn(githubInstance, 'handleEnvImportFlow' as any)
.mockResolvedValue(undefined);

await githubInstance.prepareForNewProjectCreation();

const streamingResponseCalls = (ux.inquire as jest.Mock).mock.calls.filter(
(call) => call[0]?.name === 'isStreamingEnabled',
);
expect(streamingResponseCalls.length).toBe(0);
expect(githubInstance.config.isStreamingEnabled).toBe(true);

handleEnvImportFlowMock.mockRestore();
});

it('should not prompt for streaming response when framework does not support server commands', async () => {
(ux.inquire as jest.Mock).mockResolvedValueOnce('test-project');
(ux.inquire as jest.Mock).mockResolvedValueOnce('Default');
(ux.inquire as jest.Mock).mockResolvedValueOnce('npm run build');
(ux.inquire as jest.Mock).mockResolvedValueOnce('./public');

const githubInstance = new GitHub({
config: {
flags: {
'enable-streaming-response': undefined,
},
framework: 'GATSBY',
repository: { fullName: 'test-user/repo', name: 'repo' },
supportedFrameworksForServerCommands: ['ANGULAR', 'OTHER', 'REMIX', 'NUXT'],
outputDirectories: { GATSBY: './public' },
},
log: logMock,
exit: exitMock,
} as any);

const handleEnvImportFlowMock = jest
.spyOn(githubInstance, 'handleEnvImportFlow' as any)
.mockResolvedValue(undefined);

await githubInstance.prepareForNewProjectCreation();

const streamingResponseCalls = (ux.inquire as jest.Mock).mock.calls.filter(
(call) => call[0]?.name === 'isStreamingEnabled',
);
expect(streamingResponseCalls.length).toBe(0);

handleEnvImportFlowMock.mockRestore();
});
});
});
15 changes: 15 additions & 0 deletions src/adapters/github.ts
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ export default class GitHub extends BaseClass {
environmentName,
provider: gitProvider,
serverCommand,
isStreamingEnabled,
} = this.config;
const username = split(repository?.fullName, '/')[0];

Expand All @@ -124,6 +125,7 @@ export default class GitHub extends BaseClass {
environmentVariables: map(this.envVariables, ({ key, value }) => ({ key, value })),
buildCommand: buildCommand === undefined || buildCommand === null ? 'npm run build' : buildCommand,
...(serverCommand && serverCommand.trim() !== '' ? { serverCommand } : {}),
...(isStreamingEnabled !== undefined ? { isStreamingEnabled } : {}),
},
},
},
Expand Down Expand Up @@ -160,6 +162,7 @@ export default class GitHub extends BaseClass {
'variable-type': variableType,
'env-variables': envVariables,
'server-command': serverCommand,
'enable-streaming-response': isStreamingEnabled,
alias,
} = this.config.flags;
const { token, apiKey } = configHandler.get(`tokens.${alias}`) ?? {};
Expand Down Expand Up @@ -233,6 +236,18 @@ export default class GitHub extends BaseClass {
} else {
this.config.serverCommand = serverCommand;
}

if (isStreamingEnabled === undefined) {
const isStreamingEnabledInput = await ux.inquire({
type: 'confirm',
name: 'isStreamingEnabled',
message: 'Enable Streaming Responses',
default: false,
});
this.config.isStreamingEnabled = isStreamingEnabledInput as boolean;
} else {
this.config.isStreamingEnabled = isStreamingEnabled as unknown as boolean;
}
}
this.config.variableType = variableType as unknown as string;
this.config.envVariables = envVariables;
Expand Down
5 changes: 5 additions & 0 deletions src/commands/launch/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ export default class Launch extends BaseCommand<typeof Launch> {
// eslint-disable-next-line max-len
'<%= config.bin %> <%= command.id %> --config <path/to/launch/config/file> --type <options: GitHub|FileUpload> --name=<value> --environment=<value> --branch=<value> --build-command=<value> --framework=<option> --org=<value> --out-dir=<value> --server-command=<value>',
// eslint-disable-next-line max-len
'<%= config.bin %> <%= command.id %> --config <path/to/launch/config/file> --type <options: GitHub|FileUpload> --name=<value> --environment=<value> --branch=<value> --build-command=<value> --framework=<option> --org=<value> --out-dir=<value> --server-command=<value> --enable-streaming-response',
// eslint-disable-next-line max-len
'<%= config.bin %> <%= command.id %> --config <path/to/launch/config/file> --type <options: GitHub|FileUpload> --name=<value> --environment=<value> --branch=<value> --build-command=<value> --framework=<option> --org=<value> --out-dir=<value> --variable-type="Import variables from a stack" --alias=<value>',
// eslint-disable-next-line max-len
'<%= config.bin %> <%= command.id %> --config <path/to/launch/config/file> --type <options: GitHub|FileUpload> --name=<value> --environment=<value> --branch=<value> --build-command=<value> --framework=<option> --org=<value> --out-dir=<value> --variable-type="Manually add custom variables to the list" --env-variables="APP_ENV:prod, TEST_ENV:testVal"',
Expand Down Expand Up @@ -98,6 +100,9 @@ export default class Launch extends BaseCommand<typeof Launch> {
description: '[optional] Redeploy with last file upload',
default: false,
}),
'enable-streaming-response': Flags.boolean({
description: '[optional] Enable streaming response for the server.',
}),
};

async run(): Promise<void> {
Expand Down
1 change: 1 addition & 0 deletions src/types/launch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ type ConfigType = {
repository?: Record<string, any>;
currentConfig: Record<string, any>;
deliveryToken?: Record<string, any>;
isStreamingEnabled?: boolean;
} & typeof config &
Record<string, any>;

Expand Down
Loading