@machhub-dev/sdk-ts 1.0.17 → 1.0.18
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/cjs/classes/collection.d.ts +1 -3
- package/dist/cjs/classes/collection.js +1 -4
- package/dist/cjs/classes/historian.d.ts +23 -0
- package/dist/cjs/classes/historian.js +25 -0
- package/dist/cjs/sdk-ts.js +2 -1
- package/dist/cjs/services/http.service.d.ts +1 -0
- package/dist/cjs/services/http.service.js +9 -1
- package/dist/classes/collection.d.ts +1 -3
- package/dist/classes/collection.js +1 -4
- package/dist/classes/historian.d.ts +23 -0
- package/dist/classes/historian.js +25 -0
- package/dist/sdk-ts.js +2 -1
- package/dist/services/http.service.d.ts +1 -0
- package/dist/services/http.service.js +9 -1
- package/package.json +1 -1
- package/src/classes/collection.ts +1 -6
- package/src/classes/historian.ts +45 -2
- package/src/sdk-ts.ts +2 -2
- package/src/services/http.service.ts +17 -1
|
@@ -24,9 +24,7 @@ export declare class Collection {
|
|
|
24
24
|
expand?: string | string[];
|
|
25
25
|
fields?: string | string[];
|
|
26
26
|
}): Promise<any[]>;
|
|
27
|
-
count(
|
|
28
|
-
filter?: any;
|
|
29
|
-
}): Promise<number>;
|
|
27
|
+
count(): Promise<number>;
|
|
30
28
|
getOne(id: string, options?: {
|
|
31
29
|
expand?: string | string[];
|
|
32
30
|
}): Promise<any>;
|
|
@@ -66,12 +66,9 @@ class Collection {
|
|
|
66
66
|
throw new CollectionError('getAll', this.collectionName, error);
|
|
67
67
|
}
|
|
68
68
|
}
|
|
69
|
-
async count(
|
|
69
|
+
async count() {
|
|
70
70
|
try {
|
|
71
|
-
this.applyOptions(options);
|
|
72
|
-
// Build query parameters for filters
|
|
73
71
|
const response = await this.httpService.request.get(`${this.collectionName}/count`, this.queryParams);
|
|
74
|
-
// Extract count from response
|
|
75
72
|
return response.count;
|
|
76
73
|
}
|
|
77
74
|
catch (error) {
|
|
@@ -1,6 +1,13 @@
|
|
|
1
1
|
import { HTTPService } from "../services/http.service.js";
|
|
2
2
|
import { MQTTService } from "../services/mqtt.service.js";
|
|
3
3
|
import { HistorizedData } from "../types/tag.models.js";
|
|
4
|
+
interface AggregationOption {
|
|
5
|
+
mean: "mean";
|
|
6
|
+
sum: "sum";
|
|
7
|
+
min: "min";
|
|
8
|
+
max: "max";
|
|
9
|
+
median: "median";
|
|
10
|
+
}
|
|
4
11
|
export declare class Historian {
|
|
5
12
|
private httpService;
|
|
6
13
|
private mqttService;
|
|
@@ -10,4 +17,20 @@ export declare class Historian {
|
|
|
10
17
|
subscribeLiveData(topic: string, callback: (data: any) => void): Promise<any>;
|
|
11
18
|
getLastNValues(topic: string, n: number): Promise<HistorizedData[]>;
|
|
12
19
|
query(SurrealQL: string): Promise<any>;
|
|
20
|
+
/**
|
|
21
|
+
* Export historized data for one or more topics as a gzipped CSV file (Blob).
|
|
22
|
+
* When multiple topics are provided, they are merged into a single CSV with columns: [Timestamp, topic1, topic2, ...].
|
|
23
|
+
* Supports optional time bucketing (sampleRate) and aggregation (mean, sum, min, max, median).
|
|
24
|
+
*
|
|
25
|
+
* @param topics - Array of topic strings to export
|
|
26
|
+
* @param startDate - Start date for the data range
|
|
27
|
+
* @param endDate - End date for the data range
|
|
28
|
+
* @param timezone - Optional Timezone string (e.g. "Asia/Kuala Lumpur")
|
|
29
|
+
* @param sampleRate - Optional bucket interval in underscore format (e.g. "5_second", "1_minute", "1_hour")
|
|
30
|
+
* @param aggregation - Optional aggregation function: "mean" | "sum" | "min" | "max" | "median" | "none"
|
|
31
|
+
* @param mapping - Optional key-value pairs to rename topic columns in the CSV header (e.g. { "Sensor/Temperature": "Temp °C" })
|
|
32
|
+
* @returns A Blob containing the gzipped CSV data
|
|
33
|
+
*/
|
|
34
|
+
getHistoricalDataAsCSV(topics: string[], startDate: Date, endDate: Date, timezone?: string, sampleRate?: string, aggregation?: AggregationOption, mapping?: Record<string, string>): Promise<Blob>;
|
|
13
35
|
}
|
|
36
|
+
export {};
|
|
@@ -41,5 +41,30 @@ class Historian {
|
|
|
41
41
|
query: SurrealQL
|
|
42
42
|
}).post("historian/query");
|
|
43
43
|
}
|
|
44
|
+
/**
|
|
45
|
+
* Export historized data for one or more topics as a gzipped CSV file (Blob).
|
|
46
|
+
* When multiple topics are provided, they are merged into a single CSV with columns: [Timestamp, topic1, topic2, ...].
|
|
47
|
+
* Supports optional time bucketing (sampleRate) and aggregation (mean, sum, min, max, median).
|
|
48
|
+
*
|
|
49
|
+
* @param topics - Array of topic strings to export
|
|
50
|
+
* @param startDate - Start date for the data range
|
|
51
|
+
* @param endDate - End date for the data range
|
|
52
|
+
* @param timezone - Optional Timezone string (e.g. "Asia/Kuala Lumpur")
|
|
53
|
+
* @param sampleRate - Optional bucket interval in underscore format (e.g. "5_second", "1_minute", "1_hour")
|
|
54
|
+
* @param aggregation - Optional aggregation function: "mean" | "sum" | "min" | "max" | "median" | "none"
|
|
55
|
+
* @param mapping - Optional key-value pairs to rename topic columns in the CSV header (e.g. { "Sensor/Temperature": "Temp °C" })
|
|
56
|
+
* @returns A Blob containing the gzipped CSV data
|
|
57
|
+
*/
|
|
58
|
+
async getHistoricalDataAsCSV(topics, startDate, endDate, timezone, sampleRate, aggregation, mapping) {
|
|
59
|
+
return this.httpService.request.withJSON({
|
|
60
|
+
topics,
|
|
61
|
+
startDate: startDate.toISOString(),
|
|
62
|
+
endDate: endDate.toISOString(),
|
|
63
|
+
timezone,
|
|
64
|
+
sampleRate: sampleRate ?? "",
|
|
65
|
+
aggregation: aggregation ?? "",
|
|
66
|
+
mapping: mapping ?? {},
|
|
67
|
+
}).postAsBlob("historian/export/aggregated");
|
|
68
|
+
}
|
|
44
69
|
}
|
|
45
70
|
exports.Historian = Historian;
|
package/dist/cjs/sdk-ts.js
CHANGED
|
@@ -145,7 +145,8 @@ class SDK {
|
|
|
145
145
|
host += envCfg.pathHosted;
|
|
146
146
|
}
|
|
147
147
|
if (!config.httpUrl) {
|
|
148
|
-
|
|
148
|
+
const httpHost = envCfg.hostingMode === 'path' ? `${host}/` : host;
|
|
149
|
+
config.httpUrl = `${secured ? 'https' : 'http'}://${httpHost}`;
|
|
149
150
|
}
|
|
150
151
|
if (!config.mqttUrl) {
|
|
151
152
|
config.mqttUrl = `${secured ? 'wss' : 'ws'}://${host}/mqtt`;
|
|
@@ -40,6 +40,7 @@ declare class RequestParameters {
|
|
|
40
40
|
withJSON(body: Record<string, unknown>): RequestParameters;
|
|
41
41
|
get<ReturnType>(path: string, query?: Record<string, string>): Promise<ReturnType>;
|
|
42
42
|
post<ReturnType>(path: string, query?: Record<string, string>, body?: FormData | Record<string, string>): Promise<ReturnType>;
|
|
43
|
+
postAsBlob(path: string, query?: Record<string, string>): Promise<Blob>;
|
|
43
44
|
put<ReturnType>(path: string, query?: Record<string, string>): Promise<ReturnType>;
|
|
44
45
|
delete<ReturnType>(path: string, query?: Record<string, string>): Promise<ReturnType>;
|
|
45
46
|
patch<ReturnType>(path: string, query?: Record<string, string>): Promise<ReturnType>;
|
|
@@ -40,7 +40,7 @@ class RequestParameters {
|
|
|
40
40
|
this.withRuntimeID(); // Ensure withRuntimeID() is called by default
|
|
41
41
|
}
|
|
42
42
|
withQuery(path, query) {
|
|
43
|
-
const newPath = [this.base.pathname, path].map(pathPart => pathPart.replace(/(^\/|\/$)/g, "")).join("/");
|
|
43
|
+
const newPath = "/" + [this.base.pathname, path].map(pathPart => pathPart.replace(/(^\/|\/$)/g, "")).join("/");
|
|
44
44
|
const newURL = new URL(newPath, this.base);
|
|
45
45
|
for (const key in query) {
|
|
46
46
|
newURL.searchParams.append(key, query[key]);
|
|
@@ -183,6 +183,14 @@ class RequestParameters {
|
|
|
183
183
|
}
|
|
184
184
|
return response.json();
|
|
185
185
|
}
|
|
186
|
+
async postAsBlob(path, query) {
|
|
187
|
+
const init = this.parseInit("POST") || {};
|
|
188
|
+
const response = await fetch(this.withQuery(path, query), init);
|
|
189
|
+
if (!response.ok) {
|
|
190
|
+
throw new HTTPException(response.status, response.statusText, await response.text());
|
|
191
|
+
}
|
|
192
|
+
return response.blob();
|
|
193
|
+
}
|
|
186
194
|
async put(path, query) {
|
|
187
195
|
const response = await fetch(this.withQuery(path, query), this.parseInit("PUT"));
|
|
188
196
|
if (!response.ok) {
|
|
@@ -24,9 +24,7 @@ export declare class Collection {
|
|
|
24
24
|
expand?: string | string[];
|
|
25
25
|
fields?: string | string[];
|
|
26
26
|
}): Promise<any[]>;
|
|
27
|
-
count(
|
|
28
|
-
filter?: any;
|
|
29
|
-
}): Promise<number>;
|
|
27
|
+
count(): Promise<number>;
|
|
30
28
|
getOne(id: string, options?: {
|
|
31
29
|
expand?: string | string[];
|
|
32
30
|
}): Promise<any>;
|
|
@@ -62,12 +62,9 @@ export class Collection {
|
|
|
62
62
|
throw new CollectionError('getAll', this.collectionName, error);
|
|
63
63
|
}
|
|
64
64
|
}
|
|
65
|
-
async count(
|
|
65
|
+
async count() {
|
|
66
66
|
try {
|
|
67
|
-
this.applyOptions(options);
|
|
68
|
-
// Build query parameters for filters
|
|
69
67
|
const response = await this.httpService.request.get(`${this.collectionName}/count`, this.queryParams);
|
|
70
|
-
// Extract count from response
|
|
71
68
|
return response.count;
|
|
72
69
|
}
|
|
73
70
|
catch (error) {
|
|
@@ -1,6 +1,13 @@
|
|
|
1
1
|
import { HTTPService } from "../services/http.service.js";
|
|
2
2
|
import { MQTTService } from "../services/mqtt.service.js";
|
|
3
3
|
import { HistorizedData } from "../types/tag.models.js";
|
|
4
|
+
interface AggregationOption {
|
|
5
|
+
mean: "mean";
|
|
6
|
+
sum: "sum";
|
|
7
|
+
min: "min";
|
|
8
|
+
max: "max";
|
|
9
|
+
median: "median";
|
|
10
|
+
}
|
|
4
11
|
export declare class Historian {
|
|
5
12
|
private httpService;
|
|
6
13
|
private mqttService;
|
|
@@ -10,4 +17,20 @@ export declare class Historian {
|
|
|
10
17
|
subscribeLiveData(topic: string, callback: (data: any) => void): Promise<any>;
|
|
11
18
|
getLastNValues(topic: string, n: number): Promise<HistorizedData[]>;
|
|
12
19
|
query(SurrealQL: string): Promise<any>;
|
|
20
|
+
/**
|
|
21
|
+
* Export historized data for one or more topics as a gzipped CSV file (Blob).
|
|
22
|
+
* When multiple topics are provided, they are merged into a single CSV with columns: [Timestamp, topic1, topic2, ...].
|
|
23
|
+
* Supports optional time bucketing (sampleRate) and aggregation (mean, sum, min, max, median).
|
|
24
|
+
*
|
|
25
|
+
* @param topics - Array of topic strings to export
|
|
26
|
+
* @param startDate - Start date for the data range
|
|
27
|
+
* @param endDate - End date for the data range
|
|
28
|
+
* @param timezone - Optional Timezone string (e.g. "Asia/Kuala Lumpur")
|
|
29
|
+
* @param sampleRate - Optional bucket interval in underscore format (e.g. "5_second", "1_minute", "1_hour")
|
|
30
|
+
* @param aggregation - Optional aggregation function: "mean" | "sum" | "min" | "max" | "median" | "none"
|
|
31
|
+
* @param mapping - Optional key-value pairs to rename topic columns in the CSV header (e.g. { "Sensor/Temperature": "Temp °C" })
|
|
32
|
+
* @returns A Blob containing the gzipped CSV data
|
|
33
|
+
*/
|
|
34
|
+
getHistoricalDataAsCSV(topics: string[], startDate: Date, endDate: Date, timezone?: string, sampleRate?: string, aggregation?: AggregationOption, mapping?: Record<string, string>): Promise<Blob>;
|
|
13
35
|
}
|
|
36
|
+
export {};
|
|
@@ -38,4 +38,29 @@ export class Historian {
|
|
|
38
38
|
query: SurrealQL
|
|
39
39
|
}).post("historian/query");
|
|
40
40
|
}
|
|
41
|
+
/**
|
|
42
|
+
* Export historized data for one or more topics as a gzipped CSV file (Blob).
|
|
43
|
+
* When multiple topics are provided, they are merged into a single CSV with columns: [Timestamp, topic1, topic2, ...].
|
|
44
|
+
* Supports optional time bucketing (sampleRate) and aggregation (mean, sum, min, max, median).
|
|
45
|
+
*
|
|
46
|
+
* @param topics - Array of topic strings to export
|
|
47
|
+
* @param startDate - Start date for the data range
|
|
48
|
+
* @param endDate - End date for the data range
|
|
49
|
+
* @param timezone - Optional Timezone string (e.g. "Asia/Kuala Lumpur")
|
|
50
|
+
* @param sampleRate - Optional bucket interval in underscore format (e.g. "5_second", "1_minute", "1_hour")
|
|
51
|
+
* @param aggregation - Optional aggregation function: "mean" | "sum" | "min" | "max" | "median" | "none"
|
|
52
|
+
* @param mapping - Optional key-value pairs to rename topic columns in the CSV header (e.g. { "Sensor/Temperature": "Temp °C" })
|
|
53
|
+
* @returns A Blob containing the gzipped CSV data
|
|
54
|
+
*/
|
|
55
|
+
async getHistoricalDataAsCSV(topics, startDate, endDate, timezone, sampleRate, aggregation, mapping) {
|
|
56
|
+
return this.httpService.request.withJSON({
|
|
57
|
+
topics,
|
|
58
|
+
startDate: startDate.toISOString(),
|
|
59
|
+
endDate: endDate.toISOString(),
|
|
60
|
+
timezone,
|
|
61
|
+
sampleRate: sampleRate ?? "",
|
|
62
|
+
aggregation: aggregation ?? "",
|
|
63
|
+
mapping: mapping ?? {},
|
|
64
|
+
}).postAsBlob("historian/export/aggregated");
|
|
65
|
+
}
|
|
41
66
|
}
|
package/dist/sdk-ts.js
CHANGED
|
@@ -142,7 +142,8 @@ export class SDK {
|
|
|
142
142
|
host += envCfg.pathHosted;
|
|
143
143
|
}
|
|
144
144
|
if (!config.httpUrl) {
|
|
145
|
-
|
|
145
|
+
const httpHost = envCfg.hostingMode === 'path' ? `${host}/` : host;
|
|
146
|
+
config.httpUrl = `${secured ? 'https' : 'http'}://${httpHost}`;
|
|
146
147
|
}
|
|
147
148
|
if (!config.mqttUrl) {
|
|
148
149
|
config.mqttUrl = `${secured ? 'wss' : 'ws'}://${host}/mqtt`;
|
|
@@ -40,6 +40,7 @@ declare class RequestParameters {
|
|
|
40
40
|
withJSON(body: Record<string, unknown>): RequestParameters;
|
|
41
41
|
get<ReturnType>(path: string, query?: Record<string, string>): Promise<ReturnType>;
|
|
42
42
|
post<ReturnType>(path: string, query?: Record<string, string>, body?: FormData | Record<string, string>): Promise<ReturnType>;
|
|
43
|
+
postAsBlob(path: string, query?: Record<string, string>): Promise<Blob>;
|
|
43
44
|
put<ReturnType>(path: string, query?: Record<string, string>): Promise<ReturnType>;
|
|
44
45
|
delete<ReturnType>(path: string, query?: Record<string, string>): Promise<ReturnType>;
|
|
45
46
|
patch<ReturnType>(path: string, query?: Record<string, string>): Promise<ReturnType>;
|
|
@@ -35,7 +35,7 @@ class RequestParameters {
|
|
|
35
35
|
this.withRuntimeID(); // Ensure withRuntimeID() is called by default
|
|
36
36
|
}
|
|
37
37
|
withQuery(path, query) {
|
|
38
|
-
const newPath = [this.base.pathname, path].map(pathPart => pathPart.replace(/(^\/|\/$)/g, "")).join("/");
|
|
38
|
+
const newPath = "/" + [this.base.pathname, path].map(pathPart => pathPart.replace(/(^\/|\/$)/g, "")).join("/");
|
|
39
39
|
const newURL = new URL(newPath, this.base);
|
|
40
40
|
for (const key in query) {
|
|
41
41
|
newURL.searchParams.append(key, query[key]);
|
|
@@ -178,6 +178,14 @@ class RequestParameters {
|
|
|
178
178
|
}
|
|
179
179
|
return response.json();
|
|
180
180
|
}
|
|
181
|
+
async postAsBlob(path, query) {
|
|
182
|
+
const init = this.parseInit("POST") || {};
|
|
183
|
+
const response = await fetch(this.withQuery(path, query), init);
|
|
184
|
+
if (!response.ok) {
|
|
185
|
+
throw new HTTPException(response.status, response.statusText, await response.text());
|
|
186
|
+
}
|
|
187
|
+
return response.blob();
|
|
188
|
+
}
|
|
181
189
|
async put(path, query) {
|
|
182
190
|
const response = await fetch(this.withQuery(path, query), this.parseInit("PUT"));
|
|
183
191
|
if (!response.ok) {
|
package/package.json
CHANGED
|
@@ -84,14 +84,9 @@ export class Collection {
|
|
|
84
84
|
}
|
|
85
85
|
}
|
|
86
86
|
|
|
87
|
-
async count(
|
|
87
|
+
async count(): Promise<number> {
|
|
88
88
|
try {
|
|
89
|
-
this.applyOptions(options);
|
|
90
|
-
|
|
91
|
-
// Build query parameters for filters
|
|
92
89
|
const response: { count: number } = await this.httpService.request.get(`${this.collectionName}/count`, this.queryParams);
|
|
93
|
-
|
|
94
|
-
// Extract count from response
|
|
95
90
|
return response.count;
|
|
96
91
|
} catch (error) {
|
|
97
92
|
throw new CollectionError('count', this.collectionName, error as Error);
|
package/src/classes/historian.ts
CHANGED
|
@@ -2,6 +2,15 @@ import { HTTPService } from "../services/http.service.js";
|
|
|
2
2
|
import { MQTTService } from "../services/mqtt.service.js";
|
|
3
3
|
import { HistorizedData } from "../types/tag.models.js";
|
|
4
4
|
|
|
5
|
+
interface AggregationOption {
|
|
6
|
+
mean: "mean",
|
|
7
|
+
sum: "sum",
|
|
8
|
+
min: "min",
|
|
9
|
+
max: "max",
|
|
10
|
+
median: "median",
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
|
|
5
14
|
export class Historian {
|
|
6
15
|
private httpService: HTTPService;
|
|
7
16
|
private mqttService: MQTTService | null;
|
|
@@ -36,7 +45,7 @@ export class Historian {
|
|
|
36
45
|
throw new Error("The number of values to fetch must be greater than 0.");
|
|
37
46
|
}
|
|
38
47
|
|
|
39
|
-
if (n > 100){
|
|
48
|
+
if (n > 100) {
|
|
40
49
|
throw new Error("The number of values to fetch must be less than 100.");
|
|
41
50
|
}
|
|
42
51
|
|
|
@@ -47,9 +56,43 @@ export class Historian {
|
|
|
47
56
|
}).patch("historian/last");
|
|
48
57
|
}
|
|
49
58
|
|
|
50
|
-
async query(SurrealQL:string): Promise<any> {
|
|
59
|
+
async query(SurrealQL: string): Promise<any> {
|
|
51
60
|
return this.httpService.request.withJSON({
|
|
52
61
|
query: SurrealQL
|
|
53
62
|
}).post("historian/query");
|
|
54
63
|
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Export historized data for one or more topics as a gzipped CSV file (Blob).
|
|
67
|
+
* When multiple topics are provided, they are merged into a single CSV with columns: [Timestamp, topic1, topic2, ...].
|
|
68
|
+
* Supports optional time bucketing (sampleRate) and aggregation (mean, sum, min, max, median).
|
|
69
|
+
*
|
|
70
|
+
* @param topics - Array of topic strings to export
|
|
71
|
+
* @param startDate - Start date for the data range
|
|
72
|
+
* @param endDate - End date for the data range
|
|
73
|
+
* @param timezone - Optional Timezone string (e.g. "Asia/Kuala Lumpur")
|
|
74
|
+
* @param sampleRate - Optional bucket interval in underscore format (e.g. "5_second", "1_minute", "1_hour")
|
|
75
|
+
* @param aggregation - Optional aggregation function: "mean" | "sum" | "min" | "max" | "median" | "none"
|
|
76
|
+
* @param mapping - Optional key-value pairs to rename topic columns in the CSV header (e.g. { "Sensor/Temperature": "Temp °C" })
|
|
77
|
+
* @returns A Blob containing the gzipped CSV data
|
|
78
|
+
*/
|
|
79
|
+
async getHistoricalDataAsCSV(
|
|
80
|
+
topics: string[],
|
|
81
|
+
startDate: Date,
|
|
82
|
+
endDate: Date,
|
|
83
|
+
timezone?: string,
|
|
84
|
+
sampleRate?: string,
|
|
85
|
+
aggregation?: AggregationOption,
|
|
86
|
+
mapping?: Record<string, string>,
|
|
87
|
+
): Promise<Blob> {
|
|
88
|
+
return this.httpService.request.withJSON({
|
|
89
|
+
topics,
|
|
90
|
+
startDate: startDate.toISOString(),
|
|
91
|
+
endDate: endDate.toISOString(),
|
|
92
|
+
timezone,
|
|
93
|
+
sampleRate: sampleRate ?? "",
|
|
94
|
+
aggregation: aggregation ?? "",
|
|
95
|
+
mapping: mapping ?? {},
|
|
96
|
+
}).postAsBlob("historian/export/aggregated");
|
|
97
|
+
}
|
|
55
98
|
}
|
package/src/sdk-ts.ts
CHANGED
|
@@ -138,7 +138,6 @@ export class SDK {
|
|
|
138
138
|
if (!config.application_id) config = { application_id: "" }
|
|
139
139
|
|
|
140
140
|
const envCfg = await getEnvConfig();
|
|
141
|
-
|
|
142
141
|
// Extract application_id from runtimeID if not provided in config
|
|
143
142
|
const application_id = config.application_id ||
|
|
144
143
|
this.extractApplicationIDFromRuntimeID(envCfg.runtimeID);
|
|
@@ -164,7 +163,8 @@ export class SDK {
|
|
|
164
163
|
}
|
|
165
164
|
|
|
166
165
|
if (!config.httpUrl) {
|
|
167
|
-
|
|
166
|
+
const httpHost = envCfg.hostingMode === 'path' ? `${host}/` : host;
|
|
167
|
+
config.httpUrl = `${secured ? 'https' : 'http'}://${httpHost}`;
|
|
168
168
|
}
|
|
169
169
|
|
|
170
170
|
if (!config.mqttUrl) {
|
|
@@ -56,7 +56,7 @@ class RequestParameters {
|
|
|
56
56
|
}
|
|
57
57
|
|
|
58
58
|
private withQuery(path: string, query?: Record<string, string>): URL {
|
|
59
|
-
const newPath = [this.base.pathname, path].map(pathPart => pathPart.replace(/(^\/|\/$)/g, "")).join("/");
|
|
59
|
+
const newPath = "/" + [this.base.pathname, path].map(pathPart => pathPart.replace(/(^\/|\/$)/g, "")).join("/");
|
|
60
60
|
const newURL = new URL(newPath, this.base);
|
|
61
61
|
|
|
62
62
|
for (const key in query) {
|
|
@@ -231,6 +231,22 @@ class RequestParameters {
|
|
|
231
231
|
}
|
|
232
232
|
|
|
233
233
|
|
|
234
|
+
public async postAsBlob(path: string, query?: Record<string, string>): Promise<Blob> {
|
|
235
|
+
const init: RequestInit = this.parseInit("POST") || {};
|
|
236
|
+
|
|
237
|
+
const response = await fetch(this.withQuery(path, query), init);
|
|
238
|
+
|
|
239
|
+
if (!response.ok) {
|
|
240
|
+
throw new HTTPException(
|
|
241
|
+
response.status,
|
|
242
|
+
response.statusText,
|
|
243
|
+
await response.text(),
|
|
244
|
+
);
|
|
245
|
+
}
|
|
246
|
+
return response.blob();
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
|
|
234
250
|
public async put<ReturnType>(path: string, query?: Record<string, string>): Promise<ReturnType> {
|
|
235
251
|
const response = await fetch(this.withQuery(path, query), this.parseInit("PUT"));
|
|
236
252
|
|