Skip to content

Commit

Permalink
chore: Remove request promise in favor of node-fetch (#9069)
Browse files Browse the repository at this point in the history
* switched from request-promise to node-fetch

* linting fix

* removed unnecessary babel changes

* attempting fix to schema compiler integration tests

* reverting schema compiler changes

* Update packages/cubejs-cli/src/command/typegen.ts

* udpate internal yarn.lock deps

* remove request-promise dep from schema-compiler

* run lint:fix

* removed obsolete pkgs from lock

---------

Co-authored-by: Josh lloyd <josh.lloyd@acquia.com>
  • Loading branch information
KSDaemon and jlloyd-widen authored Jan 9, 2025
1 parent ee826e1 commit cd91f7d
Show file tree
Hide file tree
Showing 13 changed files with 531 additions and 224 deletions.
7 changes: 4 additions & 3 deletions packages/cubejs-backend-cloud/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,10 @@
"license": "Apache-2.0",
"devDependencies": {
"@cubejs-backend/linter": "^1.0.0",
"@babel/core": "^7.24.5",
"@babel/preset-env": "^7.24.5",
"@types/fs-extra": "^9.0.8",
"@types/jest": "^27",
"@types/request-promise": "^4.1.46",
"jest": "^27",
"typescript": "~5.2.2"
},
Expand All @@ -35,10 +36,10 @@
"@cubejs-backend/shared": "1.1.10",
"chokidar": "^3.5.1",
"env-var": "^6.3.0",
"form-data": "^4.0.0",
"fs-extra": "^9.1.0",
"jsonwebtoken": "^9.0.2",
"request": "^2.88.2",
"request-promise": "^4.2.5"
"node-fetch": "^2.7.0"
},
"publishConfig": {
"access": "public"
Expand Down
134 changes: 79 additions & 55 deletions packages/cubejs-backend-cloud/src/cloud.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import rp, { RequestPromiseOptions } from 'request-promise';
import fetch, { RequestInit } from 'node-fetch';
import FormData from 'form-data';
import path from 'path';
import { ReadStream } from 'fs';

Expand All @@ -8,32 +9,49 @@ export type AuthObject = {
deploymentId?: string
};

export interface StartUploadResponse {
transaction: string;
deploymentName: string;
}

export interface UpstreamHashesResponse {
[key: string]: {
hash: string;
};
}

export class CubeCloudClient {
public constructor(
protected readonly auth?: AuthObject,
protected readonly livePreview?: boolean
) {
}

private async request(options: {
private async request<T>(options: {
url: (deploymentId: string) => string,
auth?: AuthObject,
} & RequestPromiseOptions) {
} & RequestInit): Promise<T> {
const { url, auth, ...restOptions } = options;

const authorization = auth || this.auth;
if (!authorization) {
throw new Error('Auth isn\'t set');
}
// Ensure headers object exists in restOptions
restOptions.headers = restOptions.headers || {};
// Add authorization to headers
(restOptions.headers as any).authorization = authorization.auth;

const response = await fetch(
`${authorization.url}/${url(authorization.deploymentId || '')}`,
restOptions,
);

if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}

return rp({
headers: {
authorization: authorization.auth
},
...restOptions,
url: `${authorization.url}/${url(authorization.deploymentId || '')}`,
json: true
});
return await response.json() as Promise<T>;
}

public getDeploymentsList({ auth }: { auth?: AuthObject } = {}) {
Expand All @@ -45,99 +63,105 @@ export class CubeCloudClient {
}

public async getDeploymentToken(authToken: string) {
const res = await rp({
url: `${process.env.CUBE_CLOUD_HOST || 'https://cubecloud.dev'}/v1/token`,
method: 'POST',
headers: {
'Content-type': 'application/json'
},
json: true,
body: {
token: authToken
const response = await fetch(
`${process.env.CUBE_CLOUD_HOST || 'https://cubecloud.dev'}/v1/token`,
{
method: 'POST',
headers: { 'Content-type': 'application/json' },
body: JSON.stringify({ token: authToken })
}
});
);

if (res && res.error) {
throw res.error;
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}

const res = await response.json() as any;

if (!res.jwt) {
throw new Error('JWT token is not present in the response');
}

return res.jwt;
}

private extendRequestByLivePreview() {
return this.livePreview ? { qs: { live: 'true' } } : {};
return this.livePreview ? '?live=true' : '';
}

public getUpstreamHashes({ auth }: { auth?: AuthObject } = {}) {
public getUpstreamHashes({ auth }: { auth?: AuthObject } = {}): Promise<UpstreamHashesResponse> {
return this.request({
url: (deploymentId: string) => `build/deploy/${deploymentId}/files`,
url: (deploymentId: string) => `build/deploy/${deploymentId}/files${this.extendRequestByLivePreview()}`,
method: 'GET',
auth,
...this.extendRequestByLivePreview()
});
}

public startUpload({ auth }: { auth?: AuthObject } = {}) {
public startUpload({ auth }: { auth?: AuthObject } = {}): Promise<StartUploadResponse> {
return this.request({
url: (deploymentId: string) => `build/deploy/${deploymentId}/start-upload`,
url: (deploymentId: string) => `build/deploy/${deploymentId}/start-upload${this.extendRequestByLivePreview()}`,
method: 'POST',
auth,
...this.extendRequestByLivePreview()
});
}

public uploadFile(
{ transaction, fileName, data, auth }:
{ transaction: any, fileName: string, data: ReadStream, auth?: AuthObject }
) {
const formData = new FormData();
formData.append('transaction', JSON.stringify(transaction));
formData.append('fileName', fileName);
formData.append('file', {
value: data,
options: {
filename: path.basename(fileName),
contentType: 'application/octet-stream'
}
});

// Get the form data buffer and headers
const formDataBuffer = formData.getBuffer();
const formDataHeaders = formData.getHeaders();

return this.request({
url: (deploymentId: string) => `build/deploy/${deploymentId}/upload-file`,
url: (deploymentId: string) => `build/deploy/${deploymentId}/upload-file${this.extendRequestByLivePreview()}`,
method: 'POST',
formData: {
transaction: JSON.stringify(transaction),
fileName,
file: {
value: data,
options: {
filename: path.basename(fileName),
contentType: 'application/octet-stream'
}
}
body: formDataBuffer,
headers: {
...formDataHeaders,
},
auth,
...this.extendRequestByLivePreview()
});
}

public finishUpload({ transaction, files, auth }:
{ transaction: any, files: any, auth?: AuthObject }) {
return this.request({
url: (deploymentId: string) => `build/deploy/${deploymentId}/finish-upload`,
url: (deploymentId: string) => `build/deploy/${deploymentId}/finish-upload${this.extendRequestByLivePreview()}`,
method: 'POST',
body: {
transaction,
files
},
body: JSON.stringify({ transaction, files }),
auth,
...this.extendRequestByLivePreview()
});
}

public setEnvVars({ envVariables, auth }: { envVariables: any, auth?: AuthObject }) {
return this.request({
url: (deploymentId) => `build/deploy/${deploymentId}/set-env`,
method: 'POST',
body: {
envVariables: JSON.stringify(envVariables),
},
body: JSON.stringify({ envVariables }),
auth
});
}

public getStatusDevMode({ auth, lastHash }: { auth?: AuthObject, lastHash?: string } = {}) {
public getStatusDevMode({ auth, lastHash }: { auth?: AuthObject, lastHash?: string } = {}): Promise<{[key: string]: any}> {
const params = new URLSearchParams();
if (lastHash) {
params.append('lastHash', lastHash);
}

return this.request({
url: (deploymentId) => `devmode/${deploymentId}/status`,
qs: { lastHash },
url: (deploymentId) => `devmode/${deploymentId}/status?${params.toString()}`,
method: 'GET',
auth
});
Expand All @@ -147,7 +171,7 @@ export class CubeCloudClient {
return this.request({
url: (deploymentId) => `devmode/${deploymentId}/token`,
method: 'POST',
body: payload,
body: JSON.stringify(payload),
auth
});
}
Expand Down
7 changes: 6 additions & 1 deletion packages/cubejs-backend-cloud/src/deploy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,14 +70,19 @@ type DeployHooks = {
onFinally?: Function
};

export interface DeployResponse {
lastHash?: string;
[key: string]: any; // for other properties
}

export class DeployController {
public constructor(
protected readonly cubeCloudClient: CubeCloudClient,
protected readonly hooks: DeployHooks = {}
) {
}

public async deploy(directory: string) {
public async deploy(directory: string): Promise<DeployResponse> {
let result;
const deployDir = new DeployDirectory({ directory });
const fileHashes: any = await deployDir.fileHashes();
Expand Down
2 changes: 2 additions & 0 deletions packages/cubejs-backend-cloud/src/live-preview.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,8 @@ export class LivePreviewWatcher {
lastHashTarget: this.lastHash,
uploading: this.uploading,
active: Boolean(this.watcher),
deploymentId: '' as any,
url: '' as any,
};

if (auth) {
Expand Down
5 changes: 2 additions & 3 deletions packages/cubejs-cli/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,12 +37,12 @@
"cli-progress": "^3.10",
"commander": "^2.19.0",
"cross-spawn": "^7.0.1",
"form-data": "^4.0.0",
"fs-extra": "^8.1.0",
"inquirer": "^7.1.0",
"jsonwebtoken": "^9.0.2",
"request": "^2.88.2",
"request-promise": "^4.2.5",
"semver": "^7.6.3",
"node-fetch": "2",
"source-map-support": "^0.5.19"
},
"resolutions": {
Expand All @@ -59,7 +59,6 @@
"@types/jest": "^27",
"@types/jsonwebtoken": "^9.0.2",
"@types/node": "^18",
"@types/request-promise": "^4.1.46",
"@types/semver": "^7.5.8",
"husky": "^4.2.3",
"jest": "^27",
Expand Down
Loading

0 comments on commit cd91f7d

Please sign in to comment.