@forge/events 0.0.0-experimental-e05f7a2 → 0.0.0-experimental-64caa5a
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +154 -1
- package/README.md +1 -1
- package/out/__test__/jobProgress.test.d.ts +2 -0
- package/out/__test__/jobProgress.test.d.ts.map +1 -0
- package/out/__test__/jobProgress.test.js +110 -0
- package/out/__test__/queue.test.d.ts +2 -0
- package/out/__test__/queue.test.d.ts.map +1 -0
- package/out/__test__/queue.test.js +179 -0
- package/out/__test__/queueResponse.test.d.ts +2 -0
- package/out/__test__/queueResponse.test.d.ts.map +1 -0
- package/out/__test__/queueResponse.test.js +14 -0
- package/out/__test__/utils.d.ts +7 -0
- package/out/__test__/utils.d.ts.map +1 -0
- package/out/__test__/utils.js +37 -0
- package/out/errors.d.ts +9 -0
- package/out/errors.d.ts.map +1 -1
- package/out/errors.js +19 -1
- package/out/index.d.ts +3 -0
- package/out/index.d.ts.map +1 -1
- package/out/index.js +15 -0
- package/out/jobProgress.d.ts +9 -0
- package/out/jobProgress.d.ts.map +1 -0
- package/out/jobProgress.js +36 -0
- package/out/queries.d.ts +4 -2
- package/out/queries.d.ts.map +1 -1
- package/out/queries.js +13 -8
- package/out/queue.d.ts +4 -4
- package/out/queue.d.ts.map +1 -1
- package/out/queue.js +25 -25
- package/out/queueResponse.d.ts +5 -0
- package/out/queueResponse.d.ts.map +1 -0
- package/out/queueResponse.js +12 -0
- package/out/text.d.ts +14 -0
- package/out/text.d.ts.map +1 -0
- package/out/text.js +16 -0
- package/out/types.d.ts +11 -4
- package/out/types.d.ts.map +1 -1
- package/out/validators.d.ts +10 -4
- package/out/validators.d.ts.map +1 -1
- package/out/validators.js +69 -18
- package/package.json +7 -2
- package/src/__test__/jobProgress.test.ts +149 -0
- package/src/__test__/queue.test.ts +236 -0
- package/src/__test__/queueResponse.test.ts +14 -0
- package/src/__test__/utils.ts +47 -0
- package/src/errors.ts +18 -0
- package/src/index.ts +14 -0
- package/src/jobProgress.ts +48 -0
- package/src/queries.ts +15 -9
- package/src/queue.ts +28 -29
- package/src/queueResponse.ts +7 -0
- package/src/text.ts +15 -0
- package/src/types.ts +12 -4
- package/src/validators.ts +98 -31
- package/tsconfig.json +12 -9
- package/tsconfig.tsbuildinfo +107 -20
- package/out/__test__/index.test.d.ts +0 -2
- package/out/__test__/index.test.d.ts.map +0 -1
- package/out/__test__/index.test.js +0 -126
- package/src/__test__/index.test.ts +0 -168
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.JobProgress = void 0;
|
|
4
|
+
const queries_1 = require("./queries");
|
|
5
|
+
const validators_1 = require("./validators");
|
|
6
|
+
class JobProgress {
|
|
7
|
+
constructor(id, apiClient) {
|
|
8
|
+
this.id = id;
|
|
9
|
+
this.apiClient = apiClient || global.api.asApp().__requestAtlassian;
|
|
10
|
+
}
|
|
11
|
+
async getStats() {
|
|
12
|
+
const [queueName, jobId] = this.id.split('#');
|
|
13
|
+
const getStatsRequest = {
|
|
14
|
+
queueName: queueName,
|
|
15
|
+
jobId: jobId,
|
|
16
|
+
time: new Date().toISOString()
|
|
17
|
+
};
|
|
18
|
+
validators_1.validateGetStatsPayload(getStatsRequest);
|
|
19
|
+
const response = await queries_1.post(queries_1.GET_STATS_PATH, getStatsRequest, this.apiClient);
|
|
20
|
+
await validators_1.validateGetStatsAPIResponse(response, getStatsRequest);
|
|
21
|
+
return response;
|
|
22
|
+
}
|
|
23
|
+
async cancel() {
|
|
24
|
+
const [queueName, jobId] = this.id.split('#');
|
|
25
|
+
const cancelJobRequest = {
|
|
26
|
+
queueName: queueName,
|
|
27
|
+
jobId: jobId,
|
|
28
|
+
time: new Date().toISOString()
|
|
29
|
+
};
|
|
30
|
+
validators_1.validateCancelJobRequest(cancelJobRequest);
|
|
31
|
+
const response = await queries_1.post(queries_1.CANCEL_JOB_PATH, cancelJobRequest, this.apiClient);
|
|
32
|
+
await validators_1.validateCancelJobAPIResponse(response, cancelJobRequest);
|
|
33
|
+
return response;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
exports.JobProgress = JobProgress;
|
package/out/queries.d.ts
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export declare const getPushBody: (params: PushBodyParams) => APIRequest;
|
|
1
|
+
import { APIRequest, APIResponse, FetchMethod } from './types';
|
|
3
2
|
export declare const PUSH_PATH = "/webhook/queue/publish/{cloudId}/{environmentId}/{appId}/{appVersion}";
|
|
3
|
+
export declare const GET_STATS_PATH = "/webhook/queue/stats/{cloudId}/{environmentId}/{appId}/{appVersion}";
|
|
4
|
+
export declare const CANCEL_JOB_PATH = "/webhook/queue/cancel/{cloudId}/{environmentId}/{appId}/{appVersion}";
|
|
5
|
+
export declare const post: (endpoint: string, body: APIRequest, apiClient: FetchMethod) => Promise<APIResponse>;
|
|
4
6
|
//# sourceMappingURL=queries.d.ts.map
|
package/out/queries.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"queries.d.ts","sourceRoot":"","sources":["../src/queries.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"queries.d.ts","sourceRoot":"","sources":["../src/queries.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAE/D,eAAO,MAAM,SAAS,0EAA0E,CAAC;AACjG,eAAO,MAAM,cAAc,wEAAwE,CAAC;AACpG,eAAO,MAAM,eAAe,yEAAyE,CAAC;AAEtG,eAAO,MAAM,IAAI,aAAoB,MAAM,QAAQ,UAAU,aAAa,WAAW,KAAG,OAAO,CAAC,WAAW,CAU1G,CAAC"}
|
package/out/queries.js
CHANGED
|
@@ -1,11 +1,16 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
4
|
-
exports.getPushBody = (params) => ({
|
|
5
|
-
queueName: params.queueName,
|
|
6
|
-
type: params.type,
|
|
7
|
-
schema: params.schema,
|
|
8
|
-
payload: params.payload,
|
|
9
|
-
time: new Date().toISOString()
|
|
10
|
-
});
|
|
3
|
+
exports.post = exports.CANCEL_JOB_PATH = exports.GET_STATS_PATH = exports.PUSH_PATH = void 0;
|
|
11
4
|
exports.PUSH_PATH = '/webhook/queue/publish/{cloudId}/{environmentId}/{appId}/{appVersion}';
|
|
5
|
+
exports.GET_STATS_PATH = '/webhook/queue/stats/{cloudId}/{environmentId}/{appId}/{appVersion}';
|
|
6
|
+
exports.CANCEL_JOB_PATH = '/webhook/queue/cancel/{cloudId}/{environmentId}/{appId}/{appVersion}';
|
|
7
|
+
exports.post = async (endpoint, body, apiClient) => {
|
|
8
|
+
const request = {
|
|
9
|
+
method: 'POST',
|
|
10
|
+
body: JSON.stringify(body),
|
|
11
|
+
headers: {
|
|
12
|
+
'content-type': 'application/json'
|
|
13
|
+
}
|
|
14
|
+
};
|
|
15
|
+
return await apiClient(endpoint, request);
|
|
16
|
+
};
|
package/out/queue.d.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { FetchMethod, Payload, QueueParams, PushSettings } from './types';
|
|
2
|
+
import { JobProgress } from './jobProgress';
|
|
2
3
|
export declare class Queue {
|
|
3
4
|
private readonly apiClient;
|
|
4
5
|
private queueParams;
|
|
5
6
|
constructor(queueParams: QueueParams, apiClient?: FetchMethod);
|
|
6
|
-
push(payloads: Payload | Payload[]): Promise<
|
|
7
|
-
|
|
8
|
-
private buildRequest;
|
|
7
|
+
push(payloads: Payload | Payload[], pushSettings?: PushSettings): Promise<string>;
|
|
8
|
+
getJob(jobId: string): JobProgress;
|
|
9
9
|
}
|
|
10
10
|
//# sourceMappingURL=queue.d.ts.map
|
package/out/queue.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"queue.d.ts","sourceRoot":"","sources":["../src/queue.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,OAAO,
|
|
1
|
+
{"version":3,"file":"queue.d.ts","sourceRoot":"","sources":["../src/queue.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAE,OAAO,EAAE,WAAW,EAAE,YAAY,EAAe,MAAM,SAAS,CAAC;AAEvF,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAE5C,qBAAa,KAAK;IAChB,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAc;IACxC,OAAO,CAAC,WAAW,CAAc;gBAErB,WAAW,EAAE,WAAW,EAAE,SAAS,CAAC,EAAE,WAAW;IAMvD,IAAI,CAAC,QAAQ,EAAE,OAAO,GAAG,OAAO,EAAE,EAAE,YAAY,CAAC,EAAE,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC;IA0BvF,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,WAAW;CAGnC"}
|
package/out/queue.js
CHANGED
|
@@ -1,41 +1,41 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.Queue = void 0;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
4
5
|
const queries_1 = require("./queries");
|
|
5
6
|
const validators_1 = require("./validators");
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
return response;
|
|
9
|
-
}
|
|
7
|
+
const v4_1 = tslib_1.__importDefault(require("uuid/v4"));
|
|
8
|
+
const jobProgress_1 = require("./jobProgress");
|
|
10
9
|
class Queue {
|
|
11
10
|
constructor(queueParams, apiClient) {
|
|
12
|
-
validators_1.
|
|
11
|
+
validators_1.validateQueueKey(queueParams.key);
|
|
13
12
|
this.queueParams = queueParams;
|
|
14
13
|
this.apiClient = apiClient || global.api.asApp().__requestAtlassian;
|
|
15
14
|
}
|
|
16
|
-
async push(payloads) {
|
|
17
|
-
validators_1.
|
|
18
|
-
const
|
|
19
|
-
|
|
20
|
-
|
|
15
|
+
async push(payloads, pushSettings) {
|
|
16
|
+
validators_1.validatePushPayloads(payloads);
|
|
17
|
+
const queueName = this.queueParams.key;
|
|
18
|
+
const jobId = v4_1.default();
|
|
19
|
+
const pushRequest = {
|
|
20
|
+
queueName: queueName,
|
|
21
|
+
jobId: jobId,
|
|
22
|
+
type: 'avi:forge:app:event',
|
|
21
23
|
schema: 'ari:cloud:ecosystem::forge/app-event',
|
|
22
|
-
|
|
24
|
+
payload: Array.isArray(payloads) ? payloads : [payloads],
|
|
25
|
+
time: new Date().toISOString()
|
|
23
26
|
};
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
const response = await this.apiClient(endpoint, this.buildRequest(body));
|
|
29
|
-
return await getResponseBody(response, body);
|
|
30
|
-
}
|
|
31
|
-
buildRequest(requestBody) {
|
|
32
|
-
return {
|
|
33
|
-
method: 'POST',
|
|
34
|
-
body: JSON.stringify(requestBody),
|
|
35
|
-
headers: {
|
|
36
|
-
'content-type': 'application/json'
|
|
27
|
+
if (pushSettings) {
|
|
28
|
+
validators_1.validatePushSettings(pushSettings);
|
|
29
|
+
if (pushSettings.delayInSeconds) {
|
|
30
|
+
pushRequest.delayInSeconds = pushSettings.delayInSeconds;
|
|
37
31
|
}
|
|
38
|
-
}
|
|
32
|
+
}
|
|
33
|
+
const response = await queries_1.post(queries_1.PUSH_PATH, pushRequest, this.apiClient);
|
|
34
|
+
await validators_1.validatePushAPIResponse(response, pushRequest);
|
|
35
|
+
return `${queueName}#${jobId}`;
|
|
36
|
+
}
|
|
37
|
+
getJob(jobId) {
|
|
38
|
+
return new jobProgress_1.JobProgress(jobId, this.apiClient);
|
|
39
39
|
}
|
|
40
40
|
}
|
|
41
41
|
exports.Queue = Queue;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"queueResponse.d.ts","sourceRoot":"","sources":["../src/queueResponse.ts"],"names":[],"mappings":"AAAA,qBAAa,aAAa;IACxB,SAAS,CAAC,MAAM,UAAS;IAEzB,KAAK,IAAI,IAAI;CAGd"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.QueueResponse = void 0;
|
|
4
|
+
class QueueResponse {
|
|
5
|
+
constructor() {
|
|
6
|
+
this._retry = false;
|
|
7
|
+
}
|
|
8
|
+
retry() {
|
|
9
|
+
this._retry = true;
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
exports.QueueResponse = QueueResponse;
|
package/out/text.d.ts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export declare const Text: {
|
|
2
|
+
error: {
|
|
3
|
+
invalidQueueName: string;
|
|
4
|
+
invalidDelayInSecondsSetting: string;
|
|
5
|
+
maxEventsAllowed: (maxEventsCount: number) => string;
|
|
6
|
+
maxPayloadAllowed: (maxPayloadSize: number) => string;
|
|
7
|
+
noEventsPushed: string;
|
|
8
|
+
rateLimitError: string;
|
|
9
|
+
invocationLimitReachedError: string;
|
|
10
|
+
jobIdEmpty: string;
|
|
11
|
+
jobDoesNotExit: (jobId: string, queueName: string) => string;
|
|
12
|
+
};
|
|
13
|
+
};
|
|
14
|
+
//# sourceMappingURL=text.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"text.d.ts","sourceRoot":"","sources":["../src/text.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,IAAI;;;;2CAIsB,MAAM,KAAG,MAAM;4CAEd,MAAM,KAAG,MAAM;;;;;gCAK3B,MAAM,aAAa,MAAM,KAAG,MAAM;;CAG7D,CAAC"}
|
package/out/text.js
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Text = void 0;
|
|
4
|
+
exports.Text = {
|
|
5
|
+
error: {
|
|
6
|
+
invalidQueueName: `Queue names can only contain alphanumeric characters, dashes and underscores.`,
|
|
7
|
+
invalidDelayInSecondsSetting: `The delayInSeconds setting must be between 0 and 900.`,
|
|
8
|
+
maxEventsAllowed: (maxEventsCount) => `This push contains more than the ${maxEventsCount} events allowed.`,
|
|
9
|
+
maxPayloadAllowed: (maxPayloadSize) => `The maximum payload size is ${maxPayloadSize}KB.`,
|
|
10
|
+
noEventsPushed: `No events pushed.`,
|
|
11
|
+
rateLimitError: `Too many requests.`,
|
|
12
|
+
invocationLimitReachedError: `The limit on cyclic invocation has been reached.`,
|
|
13
|
+
jobIdEmpty: `jobId cannot be empty.`,
|
|
14
|
+
jobDoesNotExit: (jobId, queueName) => `The job ${jobId} was not found for the queue ${queueName}.`
|
|
15
|
+
}
|
|
16
|
+
};
|
package/out/types.d.ts
CHANGED
|
@@ -4,20 +4,27 @@ export declare type FetchMethod = (url: string, init: RequestInit) => Promise<AP
|
|
|
4
4
|
export declare type Payload = string | number | boolean | {
|
|
5
5
|
[key: string]: Payload;
|
|
6
6
|
};
|
|
7
|
+
export interface PushSettings {
|
|
8
|
+
delayInSeconds: number;
|
|
9
|
+
}
|
|
7
10
|
export interface QueueParams {
|
|
8
|
-
|
|
11
|
+
key: string;
|
|
9
12
|
}
|
|
10
|
-
export interface
|
|
13
|
+
export interface PushRequest extends APIRequest {
|
|
11
14
|
payload: Payload[];
|
|
12
|
-
queueName: string;
|
|
13
15
|
schema: string;
|
|
14
16
|
type: string;
|
|
17
|
+
delayInSeconds?: number;
|
|
15
18
|
}
|
|
16
|
-
export interface APIRequest
|
|
19
|
+
export interface APIRequest {
|
|
20
|
+
queueName: string;
|
|
21
|
+
jobId: string;
|
|
17
22
|
time: string;
|
|
18
23
|
}
|
|
19
24
|
export interface FailedEvent {
|
|
20
25
|
errorMessage: string;
|
|
21
26
|
payload: Payload;
|
|
22
27
|
}
|
|
28
|
+
export declare type GetStatsRequest = APIRequest;
|
|
29
|
+
export declare type CancelJobRequest = APIRequest;
|
|
23
30
|
//# sourceMappingURL=types.d.ts.map
|
package/out/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAEnD,oBAAY,WAAW,GAAG,IAAI,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,aAAa,GAAG,IAAI,GAAG,QAAQ,GAAG,YAAY,CAAC,CAAC;AAC3G,oBAAY,WAAW,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,WAAW,KAAK,OAAO,CAAC,WAAW,CAAC,CAAC;AACnF,oBAAY,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;CAAE,CAAC;AAE7E,MAAM,WAAW,WAAW;IAC1B,
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAEnD,oBAAY,WAAW,GAAG,IAAI,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,aAAa,GAAG,IAAI,GAAG,QAAQ,GAAG,YAAY,CAAC,CAAC;AAC3G,oBAAY,WAAW,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,WAAW,KAAK,OAAO,CAAC,WAAW,CAAC,CAAC;AACnF,oBAAY,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;CAAE,CAAC;AAE7E,MAAM,WAAW,YAAY;IAC3B,cAAc,EAAE,MAAM,CAAC;CACxB;AACD,MAAM,WAAW,WAAW;IAC1B,GAAG,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,WAAY,SAAQ,UAAU;IAC7C,OAAO,EAAE,OAAO,EAAE,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,UAAU;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,WAAW;IAC1B,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,OAAO,CAAC;CAClB;AAED,oBAAY,eAAe,GAAG,UAAU,CAAC;AACzC,oBAAY,gBAAgB,GAAG,UAAU,CAAC"}
|
package/out/validators.d.ts
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
|
-
import { APIResponse, Payload,
|
|
2
|
-
export declare const
|
|
3
|
-
export declare const
|
|
4
|
-
export declare const
|
|
1
|
+
import { APIResponse, CancelJobRequest, GetStatsRequest, Payload, PushRequest, PushSettings } from './types';
|
|
2
|
+
export declare const validateQueueKey: (queueName: string) => void;
|
|
3
|
+
export declare const validatePushSettings: (settings: PushSettings) => void;
|
|
4
|
+
export declare const validatePushPayloads: (payloads: Payload | Payload[]) => void;
|
|
5
|
+
export declare const validateGetStatsPayload: (getStatsRequest: GetStatsRequest) => void;
|
|
6
|
+
export declare const validateCancelJobRequest: (cancelJobRequest: CancelJobRequest) => void;
|
|
7
|
+
export declare const validateAPIResponse: (response: APIResponse, expectedSuccessStatus: number) => Promise<void>;
|
|
8
|
+
export declare const validatePushAPIResponse: (response: APIResponse, requestBody: PushRequest) => Promise<void>;
|
|
9
|
+
export declare const validateGetStatsAPIResponse: (response: APIResponse, getStatsRequest: GetStatsRequest) => Promise<void>;
|
|
10
|
+
export declare const validateCancelJobAPIResponse: (response: APIResponse, cancelJobRequest: GetStatsRequest) => Promise<void>;
|
|
5
11
|
//# sourceMappingURL=validators.d.ts.map
|
package/out/validators.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validators.d.ts","sourceRoot":"","sources":["../src/validators.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"validators.d.ts","sourceRoot":"","sources":["../src/validators.ts"],"names":[],"mappings":"AAaA,OAAO,EAAE,WAAW,EAAE,gBAAgB,EAAE,eAAe,EAAE,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAM7G,eAAO,MAAM,gBAAgB,cAAe,MAAM,SAIjD,CAAC;AAEF,eAAO,MAAM,oBAAoB,aAAc,YAAY,SAI1D,CAAC;AAEF,eAAO,MAAM,oBAAoB,aAAc,OAAO,GAAG,OAAO,EAAE,SAajE,CAAC;AAEF,eAAO,MAAM,uBAAuB,oBAAqB,eAAe,SAKvE,CAAC;AAEF,eAAO,MAAM,wBAAwB,qBAAsB,gBAAgB,SAK1E,CAAC;AAEF,eAAO,MAAM,mBAAmB,aAAoB,WAAW,yBAAyB,MAAM,kBA6B7F,CAAC;AAEF,eAAO,MAAM,uBAAuB,aAAoB,WAAW,eAAe,WAAW,kBAkC5F,CAAC;AAEF,eAAO,MAAM,2BAA2B,aAAoB,WAAW,mBAAmB,eAAe,kBAMxG,CAAC;AAEF,eAAO,MAAM,4BAA4B,aAAoB,WAAW,oBAAoB,eAAe,kBAM1G,CAAC"}
|
package/out/validators.js
CHANGED
|
@@ -1,52 +1,103 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.validateAPIResponse = exports.
|
|
3
|
+
exports.validateCancelJobAPIResponse = exports.validateGetStatsAPIResponse = exports.validatePushAPIResponse = exports.validateAPIResponse = exports.validateCancelJobRequest = exports.validateGetStatsPayload = exports.validatePushPayloads = exports.validatePushSettings = exports.validateQueueKey = void 0;
|
|
4
4
|
const errors_1 = require("./errors");
|
|
5
|
+
const text_1 = require("./text");
|
|
5
6
|
const VALID_QUEUE_NAME_PATTERN = /^[a-zA-Z0-9-_]+$/;
|
|
6
|
-
const MAXIMUM_EVENTS =
|
|
7
|
+
const MAXIMUM_EVENTS = 50;
|
|
7
8
|
const MAXIMUM_PAYLOAD_SIZE_KB = 200;
|
|
8
|
-
exports.
|
|
9
|
+
exports.validateQueueKey = (queueName) => {
|
|
9
10
|
if (!queueName || !VALID_QUEUE_NAME_PATTERN.test(queueName)) {
|
|
10
|
-
throw new errors_1.InvalidQueueNameError(
|
|
11
|
+
throw new errors_1.InvalidQueueNameError(text_1.Text.error.invalidQueueName);
|
|
11
12
|
}
|
|
12
13
|
};
|
|
13
|
-
exports.
|
|
14
|
+
exports.validatePushSettings = (settings) => {
|
|
15
|
+
if ((settings.delayInSeconds && settings.delayInSeconds > 900) || settings.delayInSeconds < 0) {
|
|
16
|
+
throw new errors_1.InvalidPushSettingsError(text_1.Text.error.invalidDelayInSecondsSetting);
|
|
17
|
+
}
|
|
18
|
+
};
|
|
19
|
+
exports.validatePushPayloads = (payloads) => {
|
|
14
20
|
if (!payloads || (Array.isArray(payloads) && payloads.length === 0)) {
|
|
15
|
-
throw new errors_1.NoEventsToPushError(
|
|
21
|
+
throw new errors_1.NoEventsToPushError(text_1.Text.error.noEventsPushed);
|
|
16
22
|
}
|
|
17
23
|
if (Array.isArray(payloads) && payloads.length > MAXIMUM_EVENTS) {
|
|
18
|
-
throw new errors_1.TooManyEventsError(
|
|
24
|
+
throw new errors_1.TooManyEventsError(text_1.Text.error.maxEventsAllowed(MAXIMUM_EVENTS));
|
|
19
25
|
}
|
|
20
26
|
const payloadSizeKB = Buffer.byteLength(JSON.stringify(payloads)) / 1024;
|
|
21
27
|
if (payloadSizeKB > MAXIMUM_PAYLOAD_SIZE_KB) {
|
|
22
|
-
throw new errors_1.PayloadTooBigError(
|
|
28
|
+
throw new errors_1.PayloadTooBigError(text_1.Text.error.maxPayloadAllowed(MAXIMUM_PAYLOAD_SIZE_KB));
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
exports.validateGetStatsPayload = (getStatsRequest) => {
|
|
32
|
+
if (!getStatsRequest.jobId) {
|
|
33
|
+
throw new errors_1.JobDoesNotExistError(text_1.Text.error.jobIdEmpty);
|
|
23
34
|
}
|
|
35
|
+
exports.validateQueueKey(getStatsRequest.queueName);
|
|
24
36
|
};
|
|
25
|
-
exports.
|
|
37
|
+
exports.validateCancelJobRequest = (cancelJobRequest) => {
|
|
38
|
+
if (!cancelJobRequest.jobId) {
|
|
39
|
+
throw new errors_1.JobDoesNotExistError(text_1.Text.error.jobIdEmpty);
|
|
40
|
+
}
|
|
41
|
+
exports.validateQueueKey(cancelJobRequest.queueName);
|
|
42
|
+
};
|
|
43
|
+
exports.validateAPIResponse = async (response, expectedSuccessStatus) => {
|
|
26
44
|
if (response.status === 429) {
|
|
27
|
-
throw new errors_1.RateLimitError(
|
|
45
|
+
throw new errors_1.RateLimitError(text_1.Text.error.rateLimitError);
|
|
28
46
|
}
|
|
47
|
+
if (response.status === 405) {
|
|
48
|
+
throw new errors_1.InvocationLimitReachedError(text_1.Text.error.invocationLimitReachedError);
|
|
49
|
+
}
|
|
50
|
+
if (response.status != expectedSuccessStatus && response.status) {
|
|
51
|
+
let internalServerError;
|
|
52
|
+
try {
|
|
53
|
+
const responseBody = await response.json();
|
|
54
|
+
const errorMessage = responseBody.message ? `: ${responseBody.message}` : '';
|
|
55
|
+
const errors = responseBody.errors ? `: ${responseBody.errors.join(', ')}` : '';
|
|
56
|
+
internalServerError = new errors_1.InternalServerError(`${response.status} ${response.statusText}${errorMessage}${errors}`, responseBody.code, responseBody.details);
|
|
57
|
+
}
|
|
58
|
+
catch (ignore) {
|
|
59
|
+
internalServerError = new errors_1.InternalServerError(`${response.status} ${response.statusText}`, response.status);
|
|
60
|
+
}
|
|
61
|
+
throw internalServerError;
|
|
62
|
+
}
|
|
63
|
+
};
|
|
64
|
+
exports.validatePushAPIResponse = async (response, requestBody) => {
|
|
29
65
|
if (response.status === 413) {
|
|
30
66
|
const responseBody = await response.json();
|
|
31
67
|
throw new errors_1.PayloadTooBigError(responseBody.errorMessage);
|
|
32
68
|
}
|
|
33
69
|
if (response.status === 202) {
|
|
34
70
|
const responseBody = await response.json();
|
|
71
|
+
const defaultErrorMessage = 'Failed to process some events.';
|
|
72
|
+
const partialSuccessError = new errors_1.PartialSuccessError(defaultErrorMessage, []);
|
|
35
73
|
if (responseBody.failedEvents && responseBody.failedEvents.length > 0) {
|
|
36
|
-
|
|
74
|
+
partialSuccessError.message = `Failed to process ${responseBody.failedEvents.length} event(s).`;
|
|
75
|
+
partialSuccessError.failedEvents = responseBody.failedEvents.map((failedEvent) => {
|
|
37
76
|
return {
|
|
38
77
|
errorMessage: failedEvent.errorMessage,
|
|
39
78
|
payload: requestBody.payload[+failedEvent.index]
|
|
40
79
|
};
|
|
41
|
-
})
|
|
80
|
+
});
|
|
42
81
|
}
|
|
43
|
-
|
|
44
|
-
|
|
82
|
+
if (responseBody.errorMessage) {
|
|
83
|
+
partialSuccessError.message =
|
|
84
|
+
partialSuccessError.message !== defaultErrorMessage
|
|
85
|
+
? `${partialSuccessError.message} ${responseBody.errorMessage}`
|
|
86
|
+
: responseBody.errorMessage;
|
|
45
87
|
}
|
|
88
|
+
throw partialSuccessError;
|
|
46
89
|
}
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
90
|
+
await exports.validateAPIResponse(response, 201);
|
|
91
|
+
};
|
|
92
|
+
exports.validateGetStatsAPIResponse = async (response, getStatsRequest) => {
|
|
93
|
+
if (response.status === 404) {
|
|
94
|
+
throw new errors_1.JobDoesNotExistError(text_1.Text.error.jobDoesNotExit(getStatsRequest.jobId, getStatsRequest.queueName));
|
|
95
|
+
}
|
|
96
|
+
await exports.validateAPIResponse(response, 200);
|
|
97
|
+
};
|
|
98
|
+
exports.validateCancelJobAPIResponse = async (response, cancelJobRequest) => {
|
|
99
|
+
if (response.status === 404) {
|
|
100
|
+
throw new errors_1.JobDoesNotExistError(text_1.Text.error.jobDoesNotExit(cancelJobRequest.jobId, cancelJobRequest.queueName));
|
|
51
101
|
}
|
|
102
|
+
await exports.validateAPIResponse(response, 204);
|
|
52
103
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@forge/events",
|
|
3
|
-
"version": "0.0.0-experimental-
|
|
3
|
+
"version": "0.0.0-experimental-64caa5a",
|
|
4
4
|
"description": "Forge Async Event methods",
|
|
5
5
|
"author": "Atlassian",
|
|
6
6
|
"license": "UNLICENSED",
|
|
@@ -12,6 +12,11 @@
|
|
|
12
12
|
"compile": "tsc -b -v"
|
|
13
13
|
},
|
|
14
14
|
"devDependencies": {
|
|
15
|
-
"@types/node": "^12.12.63"
|
|
15
|
+
"@types/node": "^12.12.63",
|
|
16
|
+
"@types/uuid": "^3.4.7"
|
|
17
|
+
},
|
|
18
|
+
"dependencies": {
|
|
19
|
+
"@forge/api": "^0.0.0-experimental-64caa5a",
|
|
20
|
+
"uuid": "^3.4.0"
|
|
16
21
|
}
|
|
17
22
|
}
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
import { getApiClientMock, verifyApiClientCalledWith } from './utils';
|
|
2
|
+
import { InternalServerError, InvalidQueueNameError, JobDoesNotExistError, RateLimitError } from '../errors';
|
|
3
|
+
import { JobProgress } from '../jobProgress';
|
|
4
|
+
|
|
5
|
+
const getJobProgress = (apiClientMock: any, jobId: string) => new JobProgress(jobId, apiClientMock);
|
|
6
|
+
|
|
7
|
+
describe('JobProgress methods', () => {
|
|
8
|
+
describe('getStats', () => {
|
|
9
|
+
it('should call the queue/stats endpoint', async () => {
|
|
10
|
+
const apiClientMock = getApiClientMock(
|
|
11
|
+
{
|
|
12
|
+
success: 100,
|
|
13
|
+
inProgress: 50,
|
|
14
|
+
failed: 1
|
|
15
|
+
},
|
|
16
|
+
200
|
|
17
|
+
);
|
|
18
|
+
const jobProgress = getJobProgress(apiClientMock, 'test-queue-name#test-job-id');
|
|
19
|
+
const response = await jobProgress.getStats();
|
|
20
|
+
const { success, inProgress, failed } = await response.json();
|
|
21
|
+
verifyApiClientCalledWith(apiClientMock, '/webhook/queue/stats/{cloudId}/{environmentId}/{appId}/{appVersion}', {
|
|
22
|
+
queueName: 'test-queue-name',
|
|
23
|
+
jobId: 'test-job-id'
|
|
24
|
+
});
|
|
25
|
+
expect(success).toEqual(100);
|
|
26
|
+
expect(inProgress).toEqual(50);
|
|
27
|
+
expect(failed).toEqual(1);
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
it('should throw JobDoesNotExistError', async () => {
|
|
31
|
+
const apiClientMock = getApiClientMock(
|
|
32
|
+
{
|
|
33
|
+
message: 'Job Not Found',
|
|
34
|
+
code: 404
|
|
35
|
+
},
|
|
36
|
+
404
|
|
37
|
+
);
|
|
38
|
+
const jobProgress = getJobProgress(apiClientMock, 'test-queue-name#test-job-id');
|
|
39
|
+
await expect(jobProgress.getStats()).rejects.toThrow(
|
|
40
|
+
new JobDoesNotExistError(`The job test-job-id was not found for the queue test-queue-name.`)
|
|
41
|
+
);
|
|
42
|
+
verifyApiClientCalledWith(apiClientMock, '/webhook/queue/stats/{cloudId}/{environmentId}/{appId}/{appVersion}', {
|
|
43
|
+
queueName: 'test-queue-name',
|
|
44
|
+
jobId: 'test-job-id'
|
|
45
|
+
});
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
it('should throw RateLimitError', async () => {
|
|
49
|
+
const apiClientMock = getApiClientMock({}, 429);
|
|
50
|
+
const jobProgress = getJobProgress(apiClientMock, 'test-queue-name#test-job-id');
|
|
51
|
+
await expect(jobProgress.getStats()).rejects.toThrow(new RateLimitError(`Too many requests.`));
|
|
52
|
+
verifyApiClientCalledWith(apiClientMock, '/webhook/queue/stats/{cloudId}/{environmentId}/{appId}/{appVersion}', {
|
|
53
|
+
queueName: 'test-queue-name',
|
|
54
|
+
jobId: 'test-job-id'
|
|
55
|
+
});
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
it('should throw InternalServerError', async () => {
|
|
59
|
+
const apiClientMock = getApiClientMock(
|
|
60
|
+
{
|
|
61
|
+
message: 'Service is not available',
|
|
62
|
+
code: 513,
|
|
63
|
+
details: 'The request processing has failed because of an unknown error, exception or failure'
|
|
64
|
+
},
|
|
65
|
+
513
|
|
66
|
+
);
|
|
67
|
+
const jobProgress = getJobProgress(apiClientMock, 'test-queue-name#test-job-id');
|
|
68
|
+
await expect(jobProgress.getStats()).rejects.toThrow(
|
|
69
|
+
new InternalServerError(`513 Status Text: Service is not available`, 513)
|
|
70
|
+
);
|
|
71
|
+
verifyApiClientCalledWith(apiClientMock, '/webhook/queue/stats/{cloudId}/{environmentId}/{appId}/{appVersion}', {
|
|
72
|
+
queueName: 'test-queue-name',
|
|
73
|
+
jobId: 'test-job-id'
|
|
74
|
+
});
|
|
75
|
+
});
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
describe('cancel', () => {
|
|
79
|
+
it('should call the queue/cancel endpoint', async () => {
|
|
80
|
+
const apiClientMock = getApiClientMock({}, 204);
|
|
81
|
+
const jobProgress = getJobProgress(apiClientMock, 'test-queue-name#test-job-id');
|
|
82
|
+
const response = await jobProgress.cancel();
|
|
83
|
+
verifyApiClientCalledWith(apiClientMock, '/webhook/queue/cancel/{cloudId}/{environmentId}/{appId}/{appVersion}', {
|
|
84
|
+
queueName: 'test-queue-name',
|
|
85
|
+
jobId: 'test-job-id'
|
|
86
|
+
});
|
|
87
|
+
expect(response.status).toEqual(204);
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
it('should throw JobDoesNotExistError', async () => {
|
|
91
|
+
const apiClientMock = getApiClientMock(
|
|
92
|
+
{
|
|
93
|
+
message: 'Job Not Found',
|
|
94
|
+
code: 404
|
|
95
|
+
},
|
|
96
|
+
404
|
|
97
|
+
);
|
|
98
|
+
const jobProgress = getJobProgress(apiClientMock, 'test-queue-name#test-job-id');
|
|
99
|
+
await expect(jobProgress.cancel()).rejects.toThrow(
|
|
100
|
+
new JobDoesNotExistError(`The job test-job-id was not found for the queue test-queue-name.`)
|
|
101
|
+
);
|
|
102
|
+
verifyApiClientCalledWith(apiClientMock, '/webhook/queue/cancel/{cloudId}/{environmentId}/{appId}/{appVersion}', {
|
|
103
|
+
queueName: 'test-queue-name',
|
|
104
|
+
jobId: 'test-job-id'
|
|
105
|
+
});
|
|
106
|
+
});
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
it('should throw InternalServerError when WHP returns 422 response', async () => {
|
|
110
|
+
const apiClientMock = getApiClientMock(
|
|
111
|
+
{
|
|
112
|
+
errors: ['jobId must not be null', 'queueName must not be null']
|
|
113
|
+
},
|
|
114
|
+
422
|
|
115
|
+
);
|
|
116
|
+
const jobProgress = getJobProgress(apiClientMock, 'test-queue-name#test-job-id');
|
|
117
|
+
await expect(jobProgress.getStats()).rejects.toThrow(
|
|
118
|
+
new InternalServerError(`422 Status Text: jobId must not be null, queueName must not be null`)
|
|
119
|
+
);
|
|
120
|
+
|
|
121
|
+
verifyApiClientCalledWith(apiClientMock, '/webhook/queue/stats/{cloudId}/{environmentId}/{appId}/{appVersion}', {
|
|
122
|
+
queueName: 'test-queue-name',
|
|
123
|
+
jobId: 'test-job-id'
|
|
124
|
+
});
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
it('should throw errors when queueName or jobId is empty', async () => {
|
|
128
|
+
const apiClientMock = getApiClientMock(
|
|
129
|
+
{
|
|
130
|
+
success: 100,
|
|
131
|
+
inProgress: 50,
|
|
132
|
+
failed: 1
|
|
133
|
+
},
|
|
134
|
+
200
|
|
135
|
+
);
|
|
136
|
+
const jobProgress1 = getJobProgress(apiClientMock, 'test-queue-name#');
|
|
137
|
+
await expect(jobProgress1.getStats()).rejects.toThrow(new JobDoesNotExistError(`jobId cannot be empty.`));
|
|
138
|
+
|
|
139
|
+
const jobProgress2 = getJobProgress(apiClientMock, '#test-job-id');
|
|
140
|
+
await expect(jobProgress2.getStats()).rejects.toThrow(
|
|
141
|
+
new InvalidQueueNameError('Queue names can only contain alphanumeric characters, dashes and underscores.')
|
|
142
|
+
);
|
|
143
|
+
|
|
144
|
+
const jobProgress3 = getJobProgress(apiClientMock, '');
|
|
145
|
+
await expect(jobProgress3.getStats()).rejects.toThrow(new JobDoesNotExistError(`jobId cannot be empty.`));
|
|
146
|
+
|
|
147
|
+
expect(apiClientMock).toHaveBeenCalledTimes(0);
|
|
148
|
+
});
|
|
149
|
+
});
|