@allurereport/service 3.0.0 → 3.1.0
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/dist/history.d.ts +10 -3
- package/dist/history.js +8 -5
- package/dist/service.d.ts +12 -21
- package/dist/service.js +37 -77
- package/dist/utils/http.d.ts +1 -1
- package/dist/utils/http.js +3 -8
- package/package.json +3 -3
- package/dist/utils/token.d.ts +0 -12
- package/dist/utils/token.js +0 -56
package/dist/history.d.ts
CHANGED
|
@@ -1,9 +1,16 @@
|
|
|
1
1
|
import type { AllureHistory } from "@allurereport/core-api";
|
|
2
2
|
import type { AllureServiceClient } from "./service.js";
|
|
3
3
|
export declare class AllureRemoteHistory implements AllureHistory {
|
|
4
|
-
readonly
|
|
5
|
-
|
|
6
|
-
|
|
4
|
+
readonly params: {
|
|
5
|
+
allureServiceClient: AllureServiceClient;
|
|
6
|
+
branch?: string;
|
|
7
|
+
limit?: number;
|
|
8
|
+
};
|
|
9
|
+
constructor(params: {
|
|
10
|
+
allureServiceClient: AllureServiceClient;
|
|
11
|
+
branch?: string;
|
|
12
|
+
limit?: number;
|
|
13
|
+
});
|
|
7
14
|
readHistory(): Promise<import("@allurereport/core-api").HistoryDataPoint[]>;
|
|
8
15
|
appendHistory(): Promise<void>;
|
|
9
16
|
}
|
package/dist/history.js
CHANGED
|
@@ -1,15 +1,18 @@
|
|
|
1
1
|
import { KnownError } from "./utils/http.js";
|
|
2
2
|
export class AllureRemoteHistory {
|
|
3
|
-
constructor(
|
|
4
|
-
this.
|
|
5
|
-
this.branch = branch;
|
|
3
|
+
constructor(params) {
|
|
4
|
+
this.params = params;
|
|
6
5
|
}
|
|
7
6
|
async readHistory() {
|
|
8
|
-
|
|
7
|
+
const { allureServiceClient, branch, limit } = this.params;
|
|
8
|
+
if (!branch) {
|
|
9
9
|
return [];
|
|
10
10
|
}
|
|
11
11
|
try {
|
|
12
|
-
const res = await
|
|
12
|
+
const res = await allureServiceClient.downloadHistory({
|
|
13
|
+
branch,
|
|
14
|
+
limit,
|
|
15
|
+
});
|
|
13
16
|
return res;
|
|
14
17
|
}
|
|
15
18
|
catch (err) {
|
package/dist/service.d.ts
CHANGED
|
@@ -2,19 +2,16 @@ import { type HistoryDataPoint } from "@allurereport/core-api";
|
|
|
2
2
|
import { type Config } from "@allurereport/plugin-api";
|
|
3
3
|
export declare class AllureServiceClient {
|
|
4
4
|
#private;
|
|
5
|
-
readonly config: Config["allureService"]
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
currentProjectUuid: string | undefined;
|
|
9
|
-
constructor(config: Config["allureService"] & {
|
|
10
|
-
pollingDelay?: number;
|
|
11
|
-
});
|
|
12
|
-
setProject(project: string): void;
|
|
13
|
-
login(): Promise<any>;
|
|
14
|
-
logout(): Promise<void>;
|
|
5
|
+
readonly config: Config["allureService"];
|
|
6
|
+
constructor(config: Config["allureService"]);
|
|
7
|
+
decodeToken(token: string): any;
|
|
15
8
|
profile(): Promise<{
|
|
16
|
-
|
|
9
|
+
user: {
|
|
10
|
+
email: string;
|
|
11
|
+
};
|
|
12
|
+
project: any;
|
|
17
13
|
}>;
|
|
14
|
+
generateNewAccessToken(projectUuid: string): Promise<string>;
|
|
18
15
|
projects(): Promise<{
|
|
19
16
|
projects: {
|
|
20
17
|
id: string;
|
|
@@ -27,16 +24,10 @@ export declare class AllureServiceClient {
|
|
|
27
24
|
name: string;
|
|
28
25
|
};
|
|
29
26
|
}>;
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
name: string;
|
|
35
|
-
}>;
|
|
36
|
-
deleteProject(payload: {
|
|
37
|
-
id: string;
|
|
38
|
-
}): Promise<unknown>;
|
|
39
|
-
downloadHistory(branch: string): Promise<HistoryDataPoint[]>;
|
|
27
|
+
downloadHistory(payload: {
|
|
28
|
+
branch: string;
|
|
29
|
+
limit?: number;
|
|
30
|
+
}): Promise<HistoryDataPoint[]>;
|
|
40
31
|
createReport(payload: {
|
|
41
32
|
reportName: string;
|
|
42
33
|
reportUuid?: string;
|
package/dist/service.js
CHANGED
|
@@ -9,68 +9,50 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
|
|
|
9
9
|
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
|
10
10
|
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
11
11
|
};
|
|
12
|
-
var
|
|
12
|
+
var _AllureServiceClient_client, _AllureServiceClient_url;
|
|
13
13
|
import { readFile } from "node:fs/promises";
|
|
14
14
|
import { join as joinPosix } from "node:path/posix";
|
|
15
|
-
import open from "open";
|
|
16
15
|
import { createServiceHttpClient } from "./utils/http.js";
|
|
17
|
-
import { decryptExchangeToken, deleteAccessToken, writeAccessToken, writeExchangeToken } from "./utils/token.js";
|
|
18
16
|
const ASSET_MAX_FILE_SIZE = 200 * 1024 * 1024;
|
|
19
17
|
export class AllureServiceClient {
|
|
20
18
|
constructor(config) {
|
|
21
|
-
_AllureServiceClient_instances.add(this);
|
|
22
19
|
this.config = config;
|
|
23
20
|
_AllureServiceClient_client.set(this, void 0);
|
|
24
21
|
_AllureServiceClient_url.set(this, void 0);
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
throw new Error("Allure service URL is required!");
|
|
22
|
+
if (!config?.accessToken) {
|
|
23
|
+
throw new Error("Allure service access token is required");
|
|
28
24
|
}
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
this.currentProjectUuid = project;
|
|
36
|
-
}
|
|
37
|
-
async login() {
|
|
38
|
-
const clientUrl = await __classPrivateFieldGet(this, _AllureServiceClient_instances, "m", _AllureServiceClient_getClientUrl).call(this);
|
|
39
|
-
const exchangeToken = await writeExchangeToken();
|
|
40
|
-
const connectUrl = new URL("/connect", clientUrl);
|
|
41
|
-
connectUrl.searchParams.set("token", decryptExchangeToken(exchangeToken));
|
|
42
|
-
await open(connectUrl.toString());
|
|
43
|
-
let currentExchangeAttemptTimeout;
|
|
44
|
-
return await new Promise((res) => {
|
|
45
|
-
const makeExchangeAttempt = () => {
|
|
46
|
-
return globalThis.setTimeout(async () => {
|
|
47
|
-
const token = decryptExchangeToken(exchangeToken);
|
|
48
|
-
const { accessToken } = await __classPrivateFieldGet(this, _AllureServiceClient_client, "f").post("/auth/exchange", {
|
|
49
|
-
headers: {
|
|
50
|
-
"Content-Type": "application/json",
|
|
51
|
-
},
|
|
52
|
-
body: {
|
|
53
|
-
token,
|
|
54
|
-
},
|
|
55
|
-
});
|
|
56
|
-
if (!accessToken) {
|
|
57
|
-
globalThis.clearTimeout(currentExchangeAttemptTimeout);
|
|
58
|
-
currentExchangeAttemptTimeout = makeExchangeAttempt();
|
|
59
|
-
return;
|
|
60
|
-
}
|
|
61
|
-
await writeAccessToken(accessToken);
|
|
62
|
-
return res(accessToken);
|
|
63
|
-
}, __classPrivateFieldGet(this, _AllureServiceClient_pollingDelay, "f"));
|
|
64
|
-
};
|
|
65
|
-
currentExchangeAttemptTimeout = makeExchangeAttempt();
|
|
66
|
-
});
|
|
25
|
+
const { iss, projectId, url: baseUrl } = this.decodeToken(config.accessToken) ?? {};
|
|
26
|
+
if (iss !== "allure-service" || !baseUrl || !projectId) {
|
|
27
|
+
throw new Error("Invalid access token");
|
|
28
|
+
}
|
|
29
|
+
__classPrivateFieldSet(this, _AllureServiceClient_url, baseUrl, "f");
|
|
30
|
+
__classPrivateFieldSet(this, _AllureServiceClient_client, createServiceHttpClient(__classPrivateFieldGet(this, _AllureServiceClient_url, "f"), config.accessToken), "f");
|
|
67
31
|
}
|
|
68
|
-
|
|
69
|
-
|
|
32
|
+
decodeToken(token) {
|
|
33
|
+
try {
|
|
34
|
+
const base64Url = token.split(".")[1];
|
|
35
|
+
const base64 = base64Url.replace(/-/g, "+").replace(/_/g, "/");
|
|
36
|
+
return JSON.parse(atob(base64));
|
|
37
|
+
}
|
|
38
|
+
catch {
|
|
39
|
+
return undefined;
|
|
40
|
+
}
|
|
70
41
|
}
|
|
71
42
|
async profile() {
|
|
72
|
-
const { user } = await __classPrivateFieldGet(this, _AllureServiceClient_client, "f").get("/user/profile");
|
|
73
|
-
return
|
|
43
|
+
const { user, project } = await __classPrivateFieldGet(this, _AllureServiceClient_client, "f").get("/user/profile");
|
|
44
|
+
return {
|
|
45
|
+
user,
|
|
46
|
+
project,
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
async generateNewAccessToken(projectUuid) {
|
|
50
|
+
const { accessToken } = await __classPrivateFieldGet(this, _AllureServiceClient_client, "f").post("/auth/tokens", {
|
|
51
|
+
body: {
|
|
52
|
+
projectId: projectUuid,
|
|
53
|
+
},
|
|
54
|
+
});
|
|
55
|
+
return accessToken;
|
|
74
56
|
}
|
|
75
57
|
async projects() {
|
|
76
58
|
return __classPrivateFieldGet(this, _AllureServiceClient_client, "f").get("/projects");
|
|
@@ -78,30 +60,17 @@ export class AllureServiceClient {
|
|
|
78
60
|
async project(uuid) {
|
|
79
61
|
return __classPrivateFieldGet(this, _AllureServiceClient_client, "f").get(`/projects/${uuid}`);
|
|
80
62
|
}
|
|
81
|
-
async
|
|
82
|
-
const {
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
}
|
|
87
|
-
async deleteProject(payload) {
|
|
88
|
-
return __classPrivateFieldGet(this, _AllureServiceClient_client, "f").delete(`/projects/${payload.id}`);
|
|
89
|
-
}
|
|
90
|
-
async downloadHistory(branch) {
|
|
91
|
-
if (!this.currentProjectUuid) {
|
|
92
|
-
throw new Error("Project is not set");
|
|
93
|
-
}
|
|
94
|
-
const { history } = await __classPrivateFieldGet(this, _AllureServiceClient_client, "f").get(`/projects/${this.currentProjectUuid}/${encodeURIComponent(branch)}/history`);
|
|
63
|
+
async downloadHistory(payload) {
|
|
64
|
+
const { branch, limit } = payload;
|
|
65
|
+
const { history } = await __classPrivateFieldGet(this, _AllureServiceClient_client, "f").get(limit
|
|
66
|
+
? `/projects/history/${encodeURIComponent(branch)}?limit=${encodeURIComponent(limit.toString())}`
|
|
67
|
+
: `/projects/history/${encodeURIComponent(branch)}`);
|
|
95
68
|
return history;
|
|
96
69
|
}
|
|
97
70
|
async createReport(payload) {
|
|
98
71
|
const { reportName, reportUuid, branch } = payload;
|
|
99
|
-
if (!this.currentProjectUuid) {
|
|
100
|
-
throw new Error("Project is not set");
|
|
101
|
-
}
|
|
102
72
|
return __classPrivateFieldGet(this, _AllureServiceClient_client, "f").post("/reports", {
|
|
103
73
|
body: {
|
|
104
|
-
projectUuid: this.currentProjectUuid,
|
|
105
74
|
reportName,
|
|
106
75
|
reportUuid,
|
|
107
76
|
branch,
|
|
@@ -110,9 +79,6 @@ export class AllureServiceClient {
|
|
|
110
79
|
}
|
|
111
80
|
async completeReport(payload) {
|
|
112
81
|
const { reportUuid, historyPoint } = payload;
|
|
113
|
-
if (!this.currentProjectUuid) {
|
|
114
|
-
throw new Error("Project is not set");
|
|
115
|
-
}
|
|
116
82
|
return __classPrivateFieldGet(this, _AllureServiceClient_client, "f").post(`/reports/${reportUuid}/complete`, {
|
|
117
83
|
body: {
|
|
118
84
|
historyPoint,
|
|
@@ -121,9 +87,6 @@ export class AllureServiceClient {
|
|
|
121
87
|
}
|
|
122
88
|
async deleteReport(payload) {
|
|
123
89
|
const { reportUuid, pluginId = "" } = payload;
|
|
124
|
-
if (!this.currentProjectUuid) {
|
|
125
|
-
throw new Error("Project is not set");
|
|
126
|
-
}
|
|
127
90
|
return __classPrivateFieldGet(this, _AllureServiceClient_client, "f").post(`/reports/${reportUuid}/delete`, {
|
|
128
91
|
body: {
|
|
129
92
|
pluginId,
|
|
@@ -176,7 +139,4 @@ export class AllureServiceClient {
|
|
|
176
139
|
return joinPosix(__classPrivateFieldGet(this, _AllureServiceClient_url, "f"), reportUuid, filename);
|
|
177
140
|
}
|
|
178
141
|
}
|
|
179
|
-
_AllureServiceClient_client = new WeakMap(), _AllureServiceClient_url = new WeakMap()
|
|
180
|
-
const { url } = await __classPrivateFieldGet(this, _AllureServiceClient_client, "f").get("/info");
|
|
181
|
-
return url;
|
|
182
|
-
};
|
|
142
|
+
_AllureServiceClient_client = new WeakMap(), _AllureServiceClient_url = new WeakMap();
|
package/dist/utils/http.d.ts
CHANGED
|
@@ -7,7 +7,7 @@ export declare class UnknownError extends Error {
|
|
|
7
7
|
stack?: string;
|
|
8
8
|
constructor(message: string, stack?: string);
|
|
9
9
|
}
|
|
10
|
-
export declare const createServiceHttpClient: (
|
|
10
|
+
export declare const createServiceHttpClient: (serviceUrl: string, accessToken: string) => {
|
|
11
11
|
get: <T>(endpoint: string, payload?: AxiosRequestConfig & {
|
|
12
12
|
params?: Record<string, any>;
|
|
13
13
|
body?: any;
|
package/dist/utils/http.js
CHANGED
|
@@ -1,6 +1,4 @@
|
|
|
1
1
|
import axios, { isAxiosError } from "axios";
|
|
2
|
-
import { DEFAULT_HISTORY_SERVICE_URL } from "../model.js";
|
|
3
|
-
import { readAccessToken } from "./token.js";
|
|
4
2
|
export class KnownError extends Error {
|
|
5
3
|
constructor(message, status) {
|
|
6
4
|
super(message);
|
|
@@ -15,20 +13,17 @@ export class UnknownError extends Error {
|
|
|
15
13
|
this.stack = stack;
|
|
16
14
|
}
|
|
17
15
|
}
|
|
18
|
-
export const createServiceHttpClient = (
|
|
16
|
+
export const createServiceHttpClient = (serviceUrl, accessToken) => {
|
|
19
17
|
const client = axios.create({
|
|
20
|
-
baseURL:
|
|
18
|
+
baseURL: serviceUrl,
|
|
21
19
|
withCredentials: true,
|
|
22
20
|
validateStatus: (status) => status < 400,
|
|
23
21
|
});
|
|
24
22
|
const sendRequest = (method) => async (endpoint, payload) => {
|
|
25
|
-
const actualAccessToken = accessToken || (await readAccessToken());
|
|
26
23
|
const headers = {
|
|
27
24
|
...(payload?.headers ?? {}),
|
|
25
|
+
Authorization: `Bearer ${accessToken}`,
|
|
28
26
|
};
|
|
29
|
-
if (actualAccessToken) {
|
|
30
|
-
headers.Authorization = `Bearer ${actualAccessToken}`;
|
|
31
|
-
}
|
|
32
27
|
try {
|
|
33
28
|
let res;
|
|
34
29
|
if (payload?.body) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@allurereport/service",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.1.0",
|
|
4
4
|
"description": "Allure Service API",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"allure",
|
|
@@ -30,8 +30,8 @@
|
|
|
30
30
|
"test": "rimraf ./out && vitest run"
|
|
31
31
|
},
|
|
32
32
|
"dependencies": {
|
|
33
|
-
"@allurereport/core-api": "3.
|
|
34
|
-
"@allurereport/plugin-api": "3.
|
|
33
|
+
"@allurereport/core-api": "3.1.0",
|
|
34
|
+
"@allurereport/plugin-api": "3.1.0",
|
|
35
35
|
"axios": "^1.13.1",
|
|
36
36
|
"open": "^10.1.0"
|
|
37
37
|
},
|
package/dist/utils/token.d.ts
DELETED
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
export declare class InvalidTokenError extends Error {
|
|
2
|
-
constructor();
|
|
3
|
-
}
|
|
4
|
-
export declare class ExpiredTokenError extends Error {
|
|
5
|
-
constructor();
|
|
6
|
-
}
|
|
7
|
-
export declare const generateExchangeToken: () => string;
|
|
8
|
-
export declare const decryptExchangeToken: (exchangeToken: string) => string;
|
|
9
|
-
export declare const writeExchangeToken: () => Promise<string>;
|
|
10
|
-
export declare const writeAccessToken: (token: string) => Promise<void>;
|
|
11
|
-
export declare const readAccessToken: () => Promise<string | undefined>;
|
|
12
|
-
export declare const deleteAccessToken: () => Promise<void>;
|
package/dist/utils/token.js
DELETED
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
import { randomBytes } from "node:crypto";
|
|
2
|
-
import { mkdir, readFile, rm, writeFile } from "node:fs/promises";
|
|
3
|
-
import { EOL } from "node:os";
|
|
4
|
-
import { ALLURE_ACCESS_TOKEN_PATH, ALLURE_FILES_DIRNAME, ALLURE_LOGIN_EXCHANGE_TOKEN_PATH } from "../model.js";
|
|
5
|
-
export class InvalidTokenError extends Error {
|
|
6
|
-
constructor() {
|
|
7
|
-
super("Invalid token");
|
|
8
|
-
this.name = "InvalidTokenError";
|
|
9
|
-
}
|
|
10
|
-
}
|
|
11
|
-
export class ExpiredTokenError extends Error {
|
|
12
|
-
constructor() {
|
|
13
|
-
super("Expired token");
|
|
14
|
-
this.name = "ExpiredTokenError";
|
|
15
|
-
}
|
|
16
|
-
}
|
|
17
|
-
export const generateExchangeToken = () => {
|
|
18
|
-
const token = randomBytes(32).toString("hex");
|
|
19
|
-
const validTill = Date.now() + 10 * 60 * 1000;
|
|
20
|
-
return Buffer.from(`${token}:${validTill}`, "utf8").toString("base64");
|
|
21
|
-
};
|
|
22
|
-
export const decryptExchangeToken = (exchangeToken) => {
|
|
23
|
-
const [token, validTill] = Buffer.from(exchangeToken, "base64").toString("utf8").split(":");
|
|
24
|
-
if (!token) {
|
|
25
|
-
throw new InvalidTokenError();
|
|
26
|
-
}
|
|
27
|
-
if (validTill && parseInt(validTill, 10) < Date.now()) {
|
|
28
|
-
throw new ExpiredTokenError();
|
|
29
|
-
}
|
|
30
|
-
return token;
|
|
31
|
-
};
|
|
32
|
-
export const writeExchangeToken = async () => {
|
|
33
|
-
const tempToken = generateExchangeToken();
|
|
34
|
-
await mkdir(ALLURE_FILES_DIRNAME, { recursive: true });
|
|
35
|
-
await writeFile(ALLURE_LOGIN_EXCHANGE_TOKEN_PATH, tempToken);
|
|
36
|
-
return tempToken;
|
|
37
|
-
};
|
|
38
|
-
export const writeAccessToken = async (token) => {
|
|
39
|
-
await mkdir(ALLURE_FILES_DIRNAME, { recursive: true });
|
|
40
|
-
await writeFile(ALLURE_ACCESS_TOKEN_PATH, token);
|
|
41
|
-
};
|
|
42
|
-
export const readAccessToken = async () => {
|
|
43
|
-
try {
|
|
44
|
-
const accessToken = await readFile(ALLURE_ACCESS_TOKEN_PATH, "utf-8");
|
|
45
|
-
return accessToken.replaceAll(EOL, "").trim();
|
|
46
|
-
}
|
|
47
|
-
catch (e) {
|
|
48
|
-
return undefined;
|
|
49
|
-
}
|
|
50
|
-
};
|
|
51
|
-
export const deleteAccessToken = async () => {
|
|
52
|
-
try {
|
|
53
|
-
await rm(ALLURE_ACCESS_TOKEN_PATH, { force: true });
|
|
54
|
-
}
|
|
55
|
-
catch (ignore) { }
|
|
56
|
-
};
|