Skip to content

Commit 508bef6

Browse files
committed
Merge branch 'jlloyd-widen-deprecate-request-promise' into chore/remove-request-promise
2 parents e1911d4 + 8799042 commit 508bef6

File tree

9 files changed

+197
-148
lines changed

9 files changed

+197
-148
lines changed

packages/cubejs-backend-cloud/package.json

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@
2626
"@cubejs-backend/linter": "^1.0.0",
2727
"@types/fs-extra": "^9.0.8",
2828
"@types/jest": "^27",
29-
"@types/request-promise": "^4.1.46",
3029
"jest": "^27",
3130
"typescript": "~5.2.2"
3231
},
@@ -35,10 +34,10 @@
3534
"@cubejs-backend/shared": "1.1.10",
3635
"chokidar": "^3.5.1",
3736
"env-var": "^6.3.0",
37+
"form-data": "^4.0.0",
3838
"fs-extra": "^9.1.0",
3939
"jsonwebtoken": "^9.0.2",
40-
"request": "^2.88.2",
41-
"request-promise": "^4.2.5"
40+
"node-fetch": "^2.7.0"
4241
},
4342
"publishConfig": {
4443
"access": "public"

packages/cubejs-backend-cloud/src/cloud.ts

Lines changed: 79 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
import rp, { RequestPromiseOptions } from 'request-promise';
1+
import fetch, { RequestInit } from 'node-fetch';
2+
import FormData from 'form-data';
23
import path from 'path';
34
import { ReadStream } from 'fs';
45

@@ -8,32 +9,49 @@ export type AuthObject = {
89
deploymentId?: string
910
};
1011

12+
export interface StartUploadResponse {
13+
transaction: string;
14+
deploymentName: string;
15+
}
16+
17+
export interface UpstreamHashesResponse {
18+
[key: string]: {
19+
hash: string;
20+
};
21+
}
22+
1123
export class CubeCloudClient {
1224
public constructor(
1325
protected readonly auth?: AuthObject,
1426
protected readonly livePreview?: boolean
1527
) {
1628
}
1729

18-
private async request(options: {
30+
private async request<T>(options: {
1931
url: (deploymentId: string) => string,
2032
auth?: AuthObject,
21-
} & RequestPromiseOptions) {
33+
} & RequestInit): Promise<T> {
2234
const { url, auth, ...restOptions } = options;
2335

2436
const authorization = auth || this.auth;
2537
if (!authorization) {
2638
throw new Error('Auth isn\'t set');
2739
}
40+
// Ensure headers object exists in restOptions
41+
restOptions.headers = restOptions.headers || {};
42+
// Add authorization to headers
43+
(restOptions.headers as any).authorization = authorization.auth;
44+
45+
const response = await fetch(
46+
`${authorization.url}/${url(authorization.deploymentId || '')}`,
47+
restOptions,
48+
);
49+
50+
if (!response.ok) {
51+
throw new Error(`HTTP error! status: ${response.status}`);
52+
}
2853

29-
return rp({
30-
headers: {
31-
authorization: authorization.auth
32-
},
33-
...restOptions,
34-
url: `${authorization.url}/${url(authorization.deploymentId || '')}`,
35-
json: true
36-
});
54+
return await response.json() as Promise<T>;
3755
}
3856

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

4765
public async getDeploymentToken(authToken: string) {
48-
const res = await rp({
49-
url: `${process.env.CUBE_CLOUD_HOST || 'https://cubecloud.dev'}/v1/token`,
50-
method: 'POST',
51-
headers: {
52-
'Content-type': 'application/json'
53-
},
54-
json: true,
55-
body: {
56-
token: authToken
66+
const response = await fetch(
67+
`${process.env.CUBE_CLOUD_HOST || 'https://cubecloud.dev'}/v1/token`,
68+
{
69+
method: 'POST',
70+
headers: { 'Content-type': 'application/json' },
71+
body: JSON.stringify({ token: authToken })
5772
}
58-
});
73+
);
5974

60-
if (res && res.error) {
61-
throw res.error;
75+
if (!response.ok) {
76+
throw new Error(`HTTP error! status: ${response.status}`);
77+
}
78+
79+
const res = await response.json() as any;
80+
81+
if (!res.jwt) {
82+
throw new Error('JWT token is not present in the response');
6283
}
6384

6485
return res.jwt;
6586
}
6687

6788
private extendRequestByLivePreview() {
68-
return this.livePreview ? { qs: { live: 'true' } } : {};
89+
return this.livePreview ? '?live=true' : '';
6990
}
7091

71-
public getUpstreamHashes({ auth }: { auth?: AuthObject } = {}) {
92+
public getUpstreamHashes({ auth }: { auth?: AuthObject } = {}): Promise<UpstreamHashesResponse> {
7293
return this.request({
73-
url: (deploymentId: string) => `build/deploy/${deploymentId}/files`,
94+
url: (deploymentId: string) => `build/deploy/${deploymentId}/files${this.extendRequestByLivePreview()}`,
7495
method: 'GET',
7596
auth,
76-
...this.extendRequestByLivePreview()
7797
});
7898
}
7999

80-
public startUpload({ auth }: { auth?: AuthObject } = {}) {
100+
public startUpload({ auth }: { auth?: AuthObject } = {}): Promise<StartUploadResponse> {
81101
return this.request({
82-
url: (deploymentId: string) => `build/deploy/${deploymentId}/start-upload`,
102+
url: (deploymentId: string) => `build/deploy/${deploymentId}/start-upload${this.extendRequestByLivePreview()}`,
83103
method: 'POST',
84104
auth,
85-
...this.extendRequestByLivePreview()
86105
});
87106
}
88107

89108
public uploadFile(
90109
{ transaction, fileName, data, auth }:
91110
{ transaction: any, fileName: string, data: ReadStream, auth?: AuthObject }
92111
) {
112+
const formData = new FormData();
113+
formData.append('transaction', JSON.stringify(transaction));
114+
formData.append('fileName', fileName);
115+
formData.append('file', {
116+
value: data,
117+
options: {
118+
filename: path.basename(fileName),
119+
contentType: 'application/octet-stream'
120+
}
121+
});
122+
123+
// Get the form data buffer and headers
124+
const formDataBuffer = formData.getBuffer();
125+
const formDataHeaders = formData.getHeaders();
126+
93127
return this.request({
94-
url: (deploymentId: string) => `build/deploy/${deploymentId}/upload-file`,
128+
url: (deploymentId: string) => `build/deploy/${deploymentId}/upload-file${this.extendRequestByLivePreview()}`,
95129
method: 'POST',
96-
formData: {
97-
transaction: JSON.stringify(transaction),
98-
fileName,
99-
file: {
100-
value: data,
101-
options: {
102-
filename: path.basename(fileName),
103-
contentType: 'application/octet-stream'
104-
}
105-
}
130+
body: formDataBuffer,
131+
headers: {
132+
...formDataHeaders,
106133
},
107134
auth,
108-
...this.extendRequestByLivePreview()
109135
});
110136
}
111137

112138
public finishUpload({ transaction, files, auth }:
113139
{ transaction: any, files: any, auth?: AuthObject }) {
114140
return this.request({
115-
url: (deploymentId: string) => `build/deploy/${deploymentId}/finish-upload`,
141+
url: (deploymentId: string) => `build/deploy/${deploymentId}/finish-upload${this.extendRequestByLivePreview()}`,
116142
method: 'POST',
117-
body: {
118-
transaction,
119-
files
120-
},
143+
body: JSON.stringify({ transaction, files }),
121144
auth,
122-
...this.extendRequestByLivePreview()
123145
});
124146
}
125147

126148
public setEnvVars({ envVariables, auth }: { envVariables: any, auth?: AuthObject }) {
127149
return this.request({
128150
url: (deploymentId) => `build/deploy/${deploymentId}/set-env`,
129151
method: 'POST',
130-
body: {
131-
envVariables: JSON.stringify(envVariables),
132-
},
152+
body: JSON.stringify({ envVariables }),
133153
auth
134154
});
135155
}
136156

137-
public getStatusDevMode({ auth, lastHash }: { auth?: AuthObject, lastHash?: string } = {}) {
157+
public getStatusDevMode({ auth, lastHash }: { auth?: AuthObject, lastHash?: string } = {}): Promise<{[key: string]: any}> {
158+
const params = new URLSearchParams();
159+
if (lastHash) {
160+
params.append('lastHash', lastHash);
161+
}
162+
138163
return this.request({
139-
url: (deploymentId) => `devmode/${deploymentId}/status`,
140-
qs: { lastHash },
164+
url: (deploymentId) => `devmode/${deploymentId}/status?${params.toString()}`,
141165
method: 'GET',
142166
auth
143167
});
@@ -147,7 +171,7 @@ export class CubeCloudClient {
147171
return this.request({
148172
url: (deploymentId) => `devmode/${deploymentId}/token`,
149173
method: 'POST',
150-
body: payload,
174+
body: JSON.stringify(payload),
151175
auth
152176
});
153177
}

packages/cubejs-backend-cloud/src/deploy.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,14 +70,19 @@ type DeployHooks = {
7070
onFinally?: Function
7171
};
7272

73+
export interface DeployResponse {
74+
lastHash?: string;
75+
[key: string]: any; // for other properties
76+
}
77+
7378
export class DeployController {
7479
public constructor(
7580
protected readonly cubeCloudClient: CubeCloudClient,
7681
protected readonly hooks: DeployHooks = {}
7782
) {
7883
}
7984

80-
public async deploy(directory: string) {
85+
public async deploy(directory: string): Promise<DeployResponse> {
8186
let result;
8287
const deployDir = new DeployDirectory({ directory });
8388
const fileHashes: any = await deployDir.fileHashes();

packages/cubejs-backend-cloud/src/live-preview.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,8 @@ export class LivePreviewWatcher {
8787
lastHashTarget: this.lastHash,
8888
uploading: this.uploading,
8989
active: Boolean(this.watcher),
90+
deploymentId: '' as any,
91+
url: '' as any,
9092
};
9193

9294
if (auth) {

packages/cubejs-cli/package.json

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,11 +37,11 @@
3737
"cli-progress": "^3.10",
3838
"commander": "^2.19.0",
3939
"cross-spawn": "^7.0.1",
40+
"form-data": "^4.0.0",
4041
"fs-extra": "^8.1.0",
4142
"inquirer": "^7.1.0",
4243
"jsonwebtoken": "^9.0.2",
43-
"request": "^2.88.2",
44-
"request-promise": "^4.2.5",
44+
"node-fetch": "2",
4545
"semver": "^7.6.3",
4646
"source-map-support": "^0.5.19"
4747
},
@@ -59,7 +59,6 @@
5959
"@types/jest": "^27",
6060
"@types/jsonwebtoken": "^9.0.2",
6161
"@types/node": "^18",
62-
"@types/request-promise": "^4.1.46",
6362
"@types/semver": "^7.5.8",
6463
"husky": "^4.2.3",
6564
"jest": "^27",

packages/cubejs-cli/src/command/deploy.ts

Lines changed: 30 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import FormData from 'form-data';
12
import fs from 'fs-extra';
23
import path from 'path';
34
import cliProgress from 'cli-progress';
@@ -7,6 +8,17 @@ import { DeployDirectory } from '../deploy';
78
import { logStage, displayError, event } from '../utils';
89
import { Config } from '../config';
910

11+
interface Hashes {
12+
[key: string]: {
13+
hash: string;
14+
};
15+
}
16+
17+
interface CloudReqResult {
18+
transaction: string;
19+
deploymentName: string;
20+
}
21+
1022
const deploy = async ({ directory, auth, uploadEnv, token }: any) => {
1123
if (!(await fs.pathExists(path.join(process.cwd(), 'node_modules', '@cubejs-backend/server-core')))) {
1224
await displayError(
@@ -36,13 +48,13 @@ const deploy = async ({ directory, auth, uploadEnv, token }: any) => {
3648
const deployDir = new DeployDirectory({ directory });
3749
const fileHashes: any = await deployDir.fileHashes();
3850

39-
const upstreamHashes = await config.cloudReq({
51+
const upstreamHashes: Hashes = await config.cloudReq({
4052
url: (deploymentId: string) => `build/deploy/${deploymentId}/files`,
4153
method: 'GET',
4254
auth
4355
});
4456

45-
const { transaction, deploymentName } = await config.cloudReq({
57+
const { transaction, deploymentName }: CloudReqResult = await config.cloudReq({
4658
url: (deploymentId: string) => `build/deploy/${deploymentId}/start-upload`,
4759
method: 'POST',
4860
auth
@@ -53,9 +65,9 @@ const deploy = async ({ directory, auth, uploadEnv, token }: any) => {
5365
await config.cloudReq({
5466
url: (deploymentId) => `build/deploy/${deploymentId}/set-env`,
5567
method: 'POST',
56-
body: {
57-
envVariables: JSON.stringify(envVariables),
58-
},
68+
body: JSON.stringify({
69+
envVariables,
70+
}),
5971
auth
6072
});
6173
}
@@ -78,32 +90,31 @@ const deploy = async ({ directory, auth, uploadEnv, token }: any) => {
7890
fileHashesPosix[filePosix] = fileHashes[file];
7991

8092
if (!upstreamHashes[filePosix] || upstreamHashes[filePosix].hash !== fileHashes[file].hash) {
93+
const formData = new FormData();
94+
formData.append('transaction', JSON.stringify(transaction));
95+
formData.append('fileName', filePosix);
96+
formData.append('file', fs.createReadStream(path.join(directory, file)), {
97+
filename: path.basename(file),
98+
contentType: 'application/octet-stream'
99+
});
100+
81101
await config.cloudReq({
82102
url: (deploymentId: string) => `build/deploy/${deploymentId}/upload-file`,
83103
method: 'POST',
84-
formData: {
85-
transaction: JSON.stringify(transaction),
86-
fileName: filePosix,
87-
file: {
88-
value: fs.createReadStream(path.join(directory, file)),
89-
options: {
90-
filename: path.basename(file),
91-
contentType: 'application/octet-stream'
92-
}
93-
}
94-
},
95-
auth
104+
body: formData,
105+
auth,
106+
headers: formData.getHeaders()
96107
});
97108
}
98109
}
99110
bar.update(files.length, { file: 'Post processing...' });
100111
await config.cloudReq({
101112
url: (deploymentId: string) => `build/deploy/${deploymentId}/finish-upload`,
102113
method: 'POST',
103-
body: {
114+
body: JSON.stringify({
104115
transaction,
105116
files: fileHashesPosix
106-
},
117+
}),
107118
auth
108119
});
109120
} finally {

0 commit comments

Comments
 (0)