@attlaz/client 1.96.0 → 1.97.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/Catalog/Service/CatalogEndpoint.js +2 -1
- package/dist/Catalog/Service/CatalogProductEndpoint.js +3 -2
- package/dist/Client.d.ts +12 -12
- package/dist/Client.js +12 -12
- package/dist/{EnhanceData → DataEnrichment}/Service/GenerateContentEndpoint.js +3 -2
- package/dist/DataQuality/Model/QualityReportEntity.d.ts +31 -0
- package/dist/DataQuality/Model/QualityReportEntity.js +44 -0
- package/dist/DataQuality/Model/QualityReportProblem.d.ts +22 -0
- package/dist/DataQuality/Model/QualityReportProblem.js +35 -0
- package/dist/DataQuality/Model/QualityReportResult.d.ts +9 -0
- package/dist/DataQuality/Model/QualityReportResult.js +14 -0
- package/dist/DataQuality/Model/QualityScan.d.ts +19 -0
- package/dist/DataQuality/Model/QualityScan.js +28 -0
- package/dist/DataQuality/Service/QualityEndpoint.d.ts +57 -0
- package/dist/DataQuality/Service/QualityEndpoint.js +107 -21
- package/dist/FeedManagement/Service/CatalogFeedEndpoint.js +2 -1
- package/dist/Flow/Service/FlowEndpoint.js +6 -5
- package/dist/Flow/Service/FlowRunEndpoint.js +8 -7
- package/dist/Flow/Service/FlowRunRequestEndpoint.js +2 -1
- package/dist/Flow/Service/FlowRunStatsEndpoint.js +2 -1
- package/dist/Helper/LoadAllHelper.js +7 -1
- package/dist/Http/Data/Path.d.ts +11 -0
- package/dist/Http/Data/Path.js +31 -0
- package/dist/Http/HttpClient.d.ts +8 -1
- package/dist/Http/HttpClient.js +21 -1
- package/dist/Http/OAuthClientOptions.d.ts +2 -0
- package/dist/Http/OAuthClientOptions.js +3 -0
- package/dist/Http/Transport/OAuthClient.d.ts +7 -0
- package/dist/Http/Transport/OAuthClient.js +31 -4
- package/dist/Logging/Service/LogEndpoint.d.ts +5 -1
- package/dist/Logging/Service/LogEndpoint.js +14 -8
- package/dist/{Pulse → MarketPulse}/Service/CompetitorEndpoint.js +4 -3
- package/dist/{Pulse → MarketPulse}/Service/CrawlJobEndpoint.d.ts +1 -0
- package/dist/{Pulse → MarketPulse}/Service/CrawlJobEndpoint.js +8 -6
- package/dist/{Pulse → MarketPulse}/Service/IndexJobEndpoint.js +5 -4
- package/dist/{Pulse → MarketPulse}/Service/PriceAlertEndpoint.js +8 -7
- package/dist/{Pulse → MarketPulse}/Service/PricingEndpoint.js +9 -8
- package/dist/{Pulse → MarketPulse}/Service/ProductGroupEndpoint.js +4 -3
- package/dist/{Pulse → MarketPulse}/Service/ProductMatchEndpoint.js +6 -5
- package/dist/{Pulse → MarketPulse}/Service/ProductMatchJobEndpoint.js +5 -4
- package/dist/{Pulse → MarketPulse}/Service/PulseCatalogProductEndpoint.js +4 -3
- package/dist/{Pulse → MarketPulse}/Service/PulseStatisticsEndpoint.js +5 -4
- package/dist/{Pulse → MarketPulse}/Service/VendorProductEndpoint.js +11 -7
- package/dist/Service/AccessTokenEndpoint.js +3 -2
- package/dist/Service/AdapterConnectionEndpoint.js +9 -8
- package/dist/Service/AdapterEndpoint.js +3 -2
- package/dist/Service/ChannelEndpoint.js +5 -4
- package/dist/Service/CodeDeployEndpoint.js +5 -4
- package/dist/Service/CodeSourceStrategiesEndpoint.js +3 -2
- package/dist/Service/CollectionsEndpoint.js +5 -4
- package/dist/Service/CommandExecutionEndpoint.js +2 -1
- package/dist/Service/ConfigEndpoint.d.ts +6 -1
- package/dist/Service/ConfigEndpoint.js +9 -3
- package/dist/Service/ConfigurationEndpoint.js +5 -4
- package/dist/Service/HealthAlertEndpoint.js +3 -2
- package/dist/Service/PlatformEndpoint.js +3 -2
- package/dist/Service/PlatformLanguageEndpoint.js +2 -1
- package/dist/Service/ProjectEndpoint.js +3 -2
- package/dist/Service/ProjectEnvironmentEndpoint.js +3 -2
- package/dist/Service/ProviderTokenEndpoint.js +4 -3
- package/dist/Service/RunnerPoolEndpoint.js +5 -4
- package/dist/Service/SourcesAccountEndpoint.js +6 -5
- package/dist/Service/StorageEndpoint.js +8 -7
- package/dist/Service/SubscriberEndpoint.js +4 -3
- package/dist/Service/TriggerEndpoint.js +5 -4
- package/dist/Service/UserActionEndpoint.js +4 -3
- package/dist/Service/UserEndpoint.js +3 -2
- package/dist/Service/WorkspaceEndpoint.js +2 -1
- package/dist/Service/WorkspaceMemberEndpoint.js +5 -4
- package/dist/index.d.ts +50 -46
- package/dist/index.js +37 -33
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +4 -2
- /package/dist/{EnhanceData → DataEnrichment}/Model/GenerateContentBatch.d.ts +0 -0
- /package/dist/{EnhanceData → DataEnrichment}/Model/GenerateContentBatch.js +0 -0
- /package/dist/{EnhanceData → DataEnrichment}/Model/GenerateContentBatchData.d.ts +0 -0
- /package/dist/{EnhanceData → DataEnrichment}/Model/GenerateContentBatchData.js +0 -0
- /package/dist/{EnhanceData → DataEnrichment}/Service/GenerateContentEndpoint.d.ts +0 -0
- /package/dist/{Pulse → MarketPulse}/Model/CatalogProductWithMatches.d.ts +0 -0
- /package/dist/{Pulse → MarketPulse}/Model/CatalogProductWithMatches.js +0 -0
- /package/dist/{Pulse → MarketPulse}/Model/CompetingVendorProduct.d.ts +0 -0
- /package/dist/{Pulse → MarketPulse}/Model/CompetingVendorProduct.js +0 -0
- /package/dist/{Pulse → MarketPulse}/Model/Competitor.d.ts +0 -0
- /package/dist/{Pulse → MarketPulse}/Model/Competitor.js +0 -0
- /package/dist/{Pulse → MarketPulse}/Model/CrawlJob.d.ts +0 -0
- /package/dist/{Pulse → MarketPulse}/Model/CrawlJob.js +0 -0
- /package/dist/{Pulse → MarketPulse}/Model/IndexJob.d.ts +0 -0
- /package/dist/{Pulse → MarketPulse}/Model/IndexJob.js +0 -0
- /package/dist/{Pulse → MarketPulse}/Model/MarketSummaryEntry.d.ts +0 -0
- /package/dist/{Pulse → MarketPulse}/Model/MarketSummaryEntry.js +0 -0
- /package/dist/{Pulse → MarketPulse}/Model/MatchHistory.d.ts +0 -0
- /package/dist/{Pulse → MarketPulse}/Model/MatchHistory.js +0 -0
- /package/dist/{Pulse → MarketPulse}/Model/MatchHistoryBucket.d.ts +0 -0
- /package/dist/{Pulse → MarketPulse}/Model/MatchHistoryBucket.js +0 -0
- /package/dist/{Pulse → MarketPulse}/Model/MatchHistoryInterval.d.ts +0 -0
- /package/dist/{Pulse → MarketPulse}/Model/MatchHistoryInterval.js +0 -0
- /package/dist/{Pulse → MarketPulse}/Model/MatchedVendorProduct.d.ts +0 -0
- /package/dist/{Pulse → MarketPulse}/Model/MatchedVendorProduct.js +0 -0
- /package/dist/{Pulse → MarketPulse}/Model/PriceAlertConfig.d.ts +0 -0
- /package/dist/{Pulse → MarketPulse}/Model/PriceAlertConfig.js +0 -0
- /package/dist/{Pulse → MarketPulse}/Model/PriceAlertConfigData.d.ts +0 -0
- /package/dist/{Pulse → MarketPulse}/Model/PriceAlertConfigData.js +0 -0
- /package/dist/{Pulse → MarketPulse}/Model/PriceAlertEvent.d.ts +0 -0
- /package/dist/{Pulse → MarketPulse}/Model/PriceAlertEvent.js +0 -0
- /package/dist/{Pulse → MarketPulse}/Model/PriceIndexSnapshotEntry.d.ts +0 -0
- /package/dist/{Pulse → MarketPulse}/Model/PriceIndexSnapshotEntry.js +0 -0
- /package/dist/{Pulse → MarketPulse}/Model/PriceSuggestion.d.ts +0 -0
- /package/dist/{Pulse → MarketPulse}/Model/PriceSuggestion.js +0 -0
- /package/dist/{Pulse → MarketPulse}/Model/PricingRule.d.ts +0 -0
- /package/dist/{Pulse → MarketPulse}/Model/PricingRule.js +0 -0
- /package/dist/{Pulse → MarketPulse}/Model/PricingRuleData.d.ts +0 -0
- /package/dist/{Pulse → MarketPulse}/Model/PricingRuleData.js +0 -0
- /package/dist/{Pulse → MarketPulse}/Model/ProductGroup.d.ts +0 -0
- /package/dist/{Pulse → MarketPulse}/Model/ProductGroup.js +0 -0
- /package/dist/{Pulse → MarketPulse}/Model/ProductGroupData.d.ts +0 -0
- /package/dist/{Pulse → MarketPulse}/Model/ProductGroupData.js +0 -0
- /package/dist/{Pulse → MarketPulse}/Model/ProductMatch.d.ts +0 -0
- /package/dist/{Pulse → MarketPulse}/Model/ProductMatch.js +0 -0
- /package/dist/{Pulse → MarketPulse}/Model/ProductMatchJob.d.ts +0 -0
- /package/dist/{Pulse → MarketPulse}/Model/ProductMatchJob.js +0 -0
- /package/dist/{Pulse → MarketPulse}/Model/ProductSegmentType.d.ts +0 -0
- /package/dist/{Pulse → MarketPulse}/Model/ProductSegmentType.js +0 -0
- /package/dist/{Pulse → MarketPulse}/Model/ProductsSegment.d.ts +0 -0
- /package/dist/{Pulse → MarketPulse}/Model/ProductsSegment.js +0 -0
- /package/dist/{Pulse → MarketPulse}/Model/PulseCatalogProductFilterOptions.d.ts +0 -0
- /package/dist/{Pulse → MarketPulse}/Model/PulseCatalogProductFilterOptions.js +0 -0
- /package/dist/{Pulse → MarketPulse}/Model/PulseCatalogProductFilters.d.ts +0 -0
- /package/dist/{Pulse → MarketPulse}/Model/PulseCatalogProductFilters.js +0 -0
- /package/dist/{Pulse → MarketPulse}/Model/ReviewMatch.d.ts +0 -0
- /package/dist/{Pulse → MarketPulse}/Model/ReviewMatch.js +0 -0
- /package/dist/{Pulse → MarketPulse}/Model/ReviewMatchFilters.d.ts +0 -0
- /package/dist/{Pulse → MarketPulse}/Model/ReviewMatchFilters.js +0 -0
- /package/dist/{Pulse → MarketPulse}/Model/TopCompetitor.d.ts +0 -0
- /package/dist/{Pulse → MarketPulse}/Model/TopCompetitor.js +0 -0
- /package/dist/{Pulse → MarketPulse}/Model/Vendor.d.ts +0 -0
- /package/dist/{Pulse → MarketPulse}/Model/Vendor.js +0 -0
- /package/dist/{Pulse → MarketPulse}/Model/VendorProduct.d.ts +0 -0
- /package/dist/{Pulse → MarketPulse}/Model/VendorProduct.js +0 -0
- /package/dist/{Pulse → MarketPulse}/Model/VendorProductPriceHistoryEntry.d.ts +0 -0
- /package/dist/{Pulse → MarketPulse}/Model/VendorProductPriceHistoryEntry.js +0 -0
- /package/dist/{Pulse → MarketPulse}/Model/VendorStatus.d.ts +0 -0
- /package/dist/{Pulse → MarketPulse}/Model/VendorStatus.js +0 -0
- /package/dist/{Pulse → MarketPulse}/Service/CompetitorEndpoint.d.ts +0 -0
- /package/dist/{Pulse → MarketPulse}/Service/IndexJobEndpoint.d.ts +0 -0
- /package/dist/{Pulse → MarketPulse}/Service/PriceAlertEndpoint.d.ts +0 -0
- /package/dist/{Pulse → MarketPulse}/Service/PricingEndpoint.d.ts +0 -0
- /package/dist/{Pulse → MarketPulse}/Service/ProductGroupEndpoint.d.ts +0 -0
- /package/dist/{Pulse → MarketPulse}/Service/ProductMatchEndpoint.d.ts +0 -0
- /package/dist/{Pulse → MarketPulse}/Service/ProductMatchJobEndpoint.d.ts +0 -0
- /package/dist/{Pulse → MarketPulse}/Service/PulseCatalogProductEndpoint.d.ts +0 -0
- /package/dist/{Pulse → MarketPulse}/Service/PulseStatisticsEndpoint.d.ts +0 -0
- /package/dist/{Pulse → MarketPulse}/Service/VendorProductEndpoint.d.ts +0 -0
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { path } from '../../Http/Data/Path.js';
|
|
1
2
|
import { QueryString } from '../../Http/Data/QueryString.js';
|
|
2
3
|
import { HttpStatus } from '../../Http/HttpStatus.js';
|
|
3
4
|
import { Flow } from '../Model/Flow.js';
|
|
@@ -7,7 +8,7 @@ import { Endpoint } from '../../Service/Endpoint.js';
|
|
|
7
8
|
export class FlowEndpoint extends Endpoint {
|
|
8
9
|
async getByProject(projectId, pagination) {
|
|
9
10
|
try {
|
|
10
|
-
const queryString = new QueryString('/projects/'
|
|
11
|
+
const queryString = new QueryString(path('/projects/:projectId/flows', { projectId }));
|
|
11
12
|
queryString.addPagination(pagination);
|
|
12
13
|
const result = await this.requestCollection(queryString, Flow.parse);
|
|
13
14
|
return result;
|
|
@@ -21,7 +22,7 @@ export class FlowEndpoint extends Endpoint {
|
|
|
21
22
|
}
|
|
22
23
|
async getById(flowId) {
|
|
23
24
|
try {
|
|
24
|
-
const result = await this.requestObject('/flows
|
|
25
|
+
const result = await this.requestObject(path('/flows/:flowId', { flowId }), null, Flow.parse);
|
|
25
26
|
return result.getData();
|
|
26
27
|
}
|
|
27
28
|
catch (error) {
|
|
@@ -39,7 +40,7 @@ export class FlowEndpoint extends Endpoint {
|
|
|
39
40
|
if (!Utils.isNullOrUndefined(projectEnvironmentId)) {
|
|
40
41
|
parameters = { environment: projectEnvironmentId };
|
|
41
42
|
}
|
|
42
|
-
const queryString = new QueryString('projects/'
|
|
43
|
+
const queryString = new QueryString(path('projects/:projectId/flowsummaries', { projectId }));
|
|
43
44
|
if (pagination !== null) {
|
|
44
45
|
queryString.addPagination(pagination);
|
|
45
46
|
}
|
|
@@ -51,7 +52,7 @@ export class FlowEndpoint extends Endpoint {
|
|
|
51
52
|
parameters = { environment: projectEnvironmentId };
|
|
52
53
|
}
|
|
53
54
|
try {
|
|
54
|
-
const rawFlowSummaries = await this.requestObject('flows/'
|
|
55
|
+
const rawFlowSummaries = await this.requestObject(path('flows/:flowId/summaries', { flowId }), parameters, FlowSummary.parse);
|
|
55
56
|
if (rawFlowSummaries.getData() === null) {
|
|
56
57
|
return null;
|
|
57
58
|
}
|
|
@@ -66,7 +67,7 @@ export class FlowEndpoint extends Endpoint {
|
|
|
66
67
|
}
|
|
67
68
|
async save(flow) {
|
|
68
69
|
try {
|
|
69
|
-
const url = '/projects/'
|
|
70
|
+
const url = path('/projects/:projectId/flows', { projectId: flow.projectId });
|
|
70
71
|
const result = await this.requestObject(url, flow, Flow.parse, 'POST');
|
|
71
72
|
const updatedFlow = result.getData();
|
|
72
73
|
if (updatedFlow === null) {
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { path } from '../../Http/Data/Path.js';
|
|
1
2
|
import { FlowRun } from '../Model/FlowRun.js';
|
|
2
3
|
import { FlowRunSummary } from '../Model/FlowRunSummary.js';
|
|
3
4
|
import { FlowRunHistory } from '../Model/FlowRunHistory.js';
|
|
@@ -6,12 +7,12 @@ import { QueryString } from '../../Http/Data/QueryString.js';
|
|
|
6
7
|
import { Endpoint } from '../../Service/Endpoint.js';
|
|
7
8
|
export class FlowRunEndpoint extends Endpoint {
|
|
8
9
|
async getFlowRuns(flowId) {
|
|
9
|
-
const result = await this.requestCollection('/flows/'
|
|
10
|
+
const result = await this.requestCollection(path('/flows/:flowId/runs', { flowId }), FlowRun.parse);
|
|
10
11
|
return result;
|
|
11
12
|
}
|
|
12
13
|
async getFlowRunSummaries(flowId, flowRunStatuses = null, pagination = null, projectEnvironmentId = null) {
|
|
13
14
|
try {
|
|
14
|
-
const queryString = new QueryString('/flows/'
|
|
15
|
+
const queryString = new QueryString(path('/flows/:flowId/runsummaries', { flowId }));
|
|
15
16
|
queryString.addPagination(pagination);
|
|
16
17
|
// if (from !== null && from !== undefined) {
|
|
17
18
|
//
|
|
@@ -49,7 +50,7 @@ export class FlowRunEndpoint extends Endpoint {
|
|
|
49
50
|
}
|
|
50
51
|
async getFlowRunSummary(flowRunId) {
|
|
51
52
|
try {
|
|
52
|
-
const result = await this.requestObject('/flowruns/'
|
|
53
|
+
const result = await this.requestObject(path('/flowruns/:flowRunId/summaries', { flowRunId }), null, FlowRunSummary.parse);
|
|
53
54
|
return result.getData();
|
|
54
55
|
}
|
|
55
56
|
catch (error) {
|
|
@@ -67,7 +68,7 @@ export class FlowRunEndpoint extends Endpoint {
|
|
|
67
68
|
*/
|
|
68
69
|
async getFlowRun(flowRunId) {
|
|
69
70
|
try {
|
|
70
|
-
const result = await this.requestObject('/flowruns/'
|
|
71
|
+
const result = await this.requestObject(path('/flowruns/:flowRunId/summaries', { flowRunId }), null, FlowRun.parse);
|
|
71
72
|
return result.getData();
|
|
72
73
|
}
|
|
73
74
|
catch (error) {
|
|
@@ -78,7 +79,7 @@ export class FlowRunEndpoint extends Endpoint {
|
|
|
78
79
|
}
|
|
79
80
|
}
|
|
80
81
|
async getFlowRunHistory(flowRunId) {
|
|
81
|
-
const result = await this.requestCollection('/flowruns/'
|
|
82
|
+
const result = await this.requestCollection(path('/flowruns/:flowRunId/history', { flowRunId }), FlowRunHistory.parse);
|
|
82
83
|
return result;
|
|
83
84
|
}
|
|
84
85
|
/**
|
|
@@ -87,7 +88,7 @@ export class FlowRunEndpoint extends Endpoint {
|
|
|
87
88
|
* reflects the eventually-consistent index projection which can lag the history.
|
|
88
89
|
*/
|
|
89
90
|
async getFlowRunLifecycle(flowRunId) {
|
|
90
|
-
const result = await this.requestObject('/flowruns/'
|
|
91
|
+
const result = await this.requestObject(path('/flowruns/:flowRunId/lifecycle', { flowRunId }), null, FlowRunLifecycle.parse);
|
|
91
92
|
return result.getData();
|
|
92
93
|
}
|
|
93
94
|
async updateFlowRun(flowRunId, status, time = null) {
|
|
@@ -101,7 +102,7 @@ export class FlowRunEndpoint extends Endpoint {
|
|
|
101
102
|
if (time !== null && time !== undefined) {
|
|
102
103
|
params.time = time;
|
|
103
104
|
}
|
|
104
|
-
const result = await this.requestObject('/flowruns
|
|
105
|
+
const result = await this.requestObject(path('/flowruns/:flowRunId', { flowRunId }), params, FlowRun.parse, 'POST');
|
|
105
106
|
const updatedFlowRun = result.getData();
|
|
106
107
|
if (updatedFlowRun === null) {
|
|
107
108
|
throw new Error('FlowRun not updated');
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
+
import { path } from '../../Http/Data/Path.js';
|
|
1
2
|
import { FlowRunResponse } from '../Model/FlowRunResponse.js';
|
|
2
3
|
import { Endpoint } from '../../Service/Endpoint.js';
|
|
3
4
|
export class FlowRunRequestEndpoint extends Endpoint {
|
|
4
5
|
async requestFlowRun(flowId, params, wait = false) {
|
|
5
|
-
let url = '/flows/'
|
|
6
|
+
let url = path('/flows/:flowId/flowrunrequests', { flowId });
|
|
6
7
|
if (wait) {
|
|
7
8
|
url += '?wait=true';
|
|
8
9
|
}
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
+
import { path } from '../../Http/Data/Path.js';
|
|
1
2
|
import { FlowRunStats } from '../Model/FlowRunStats.js';
|
|
2
3
|
import { Endpoint } from '../../Service/Endpoint.js';
|
|
3
4
|
export class FlowRunStatsEndpoint extends Endpoint {
|
|
4
5
|
async create(flowRunStats) {
|
|
5
|
-
const url = '/flowruns/'
|
|
6
|
+
const url = path('/flowruns/:flowRunId/stats', { flowRunId: flowRunStats.flowRunId });
|
|
6
7
|
try {
|
|
7
8
|
const result = await this.requestObject(url, flowRunStats, FlowRunStats.parse, 'POST');
|
|
8
9
|
const createdFlowRunStat = result.getData();
|
|
@@ -10,7 +10,13 @@ export class LoadAllHelper {
|
|
|
10
10
|
firstPagination.startingAfter = lastRef;
|
|
11
11
|
const data = await call(firstPagination);
|
|
12
12
|
const records = data.getData();
|
|
13
|
-
//
|
|
13
|
+
// An empty page that still claims hasMore cannot be paged past: the cursor advances from
|
|
14
|
+
// the last record, so the next call would repeat this one forever. The server contradicted
|
|
15
|
+
// itself — say so rather than spin.
|
|
16
|
+
if (records.length === 0 && data.hasMore) {
|
|
17
|
+
throw new Error('loadAll stopped after ' + totalResult.length + ' records: the API reported more results but returned an empty page, so paging cannot continue.');
|
|
18
|
+
}
|
|
19
|
+
// Spread one page at a time (bounded by `limit`), so the argument count stays small.
|
|
14
20
|
if (totalResult.length + records.length > 50_000) {
|
|
15
21
|
throw new Error('loadAll exceeded 50,000 records (' + (totalResult.length + records.length) + '). This method is not intended for large datasets.');
|
|
16
22
|
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Build a request path from a template, encoding every value that goes into it.
|
|
3
|
+
*
|
|
4
|
+
* path('/data-quality/datasets/:datasetId/scans', {datasetId})
|
|
5
|
+
*
|
|
6
|
+
* Ids are opaque strings supplied by the caller. Concatenating them straight into a URL means a
|
|
7
|
+
* value containing `/`, `?` or `#` silently changes which endpoint is called; an empty one produces
|
|
8
|
+
* a path that quietly addresses the collection instead of the item. Encoding here makes the request
|
|
9
|
+
* mean what it says, and an empty value an error rather than a surprise.
|
|
10
|
+
*/
|
|
11
|
+
export declare function path(template: string, parameters?: Record<string, string | number>): string;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Build a request path from a template, encoding every value that goes into it.
|
|
3
|
+
*
|
|
4
|
+
* path('/data-quality/datasets/:datasetId/scans', {datasetId})
|
|
5
|
+
*
|
|
6
|
+
* Ids are opaque strings supplied by the caller. Concatenating them straight into a URL means a
|
|
7
|
+
* value containing `/`, `?` or `#` silently changes which endpoint is called; an empty one produces
|
|
8
|
+
* a path that quietly addresses the collection instead of the item. Encoding here makes the request
|
|
9
|
+
* mean what it says, and an empty value an error rather than a surprise.
|
|
10
|
+
*/
|
|
11
|
+
export function path(template, parameters = {}) {
|
|
12
|
+
const used = new Set();
|
|
13
|
+
const built = template.replace(/:([A-Za-z][A-Za-z0-9_]*)/g, (_match, name) => {
|
|
14
|
+
if (!Object.prototype.hasOwnProperty.call(parameters, name)) {
|
|
15
|
+
throw new Error('Unable to build path "' + template + '": no value for ":' + name + '"');
|
|
16
|
+
}
|
|
17
|
+
used.add(name);
|
|
18
|
+
const value = String(parameters[name]);
|
|
19
|
+
if (value === '') {
|
|
20
|
+
throw new Error('Unable to build path "' + template + '": ":' + name + '" is empty');
|
|
21
|
+
}
|
|
22
|
+
return encodeURIComponent(value);
|
|
23
|
+
});
|
|
24
|
+
// A value with no matching placeholder is a typo that would otherwise vanish silently.
|
|
25
|
+
for (const name of Object.keys(parameters)) {
|
|
26
|
+
if (!used.has(name)) {
|
|
27
|
+
throw new Error('Unable to build path "' + template + '": no placeholder for "' + name + '"');
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
return built;
|
|
31
|
+
}
|
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
import { HttpClientRequest } from './HttpClientRequest.js';
|
|
2
2
|
import { HttpClientResponse } from './HttpClientResponse.js';
|
|
3
3
|
export declare class HttpClient {
|
|
4
|
-
|
|
4
|
+
/**
|
|
5
|
+
* Overall budget for one request, in milliseconds. Matches the Stripe SDKs (80s), which is
|
|
6
|
+
* generous enough for a large payload and bounded enough that an unresponsive API surfaces as an
|
|
7
|
+
* error instead of hanging the caller. `fetch` applies no timeout of its own in the browser, and
|
|
8
|
+
* only bounds response headers in Node.
|
|
9
|
+
*/
|
|
10
|
+
static readonly DEFAULT_TIMEOUT_MS: number;
|
|
11
|
+
static request(request: HttpClientRequest, timeoutMs?: number): Promise<HttpClientResponse>;
|
|
5
12
|
}
|
package/dist/Http/HttpClient.js
CHANGED
|
@@ -1,11 +1,21 @@
|
|
|
1
1
|
import { HttpClientResponse } from './HttpClientResponse.js';
|
|
2
2
|
import { ClientError } from './ClientError.js';
|
|
3
3
|
export class HttpClient {
|
|
4
|
-
|
|
4
|
+
/**
|
|
5
|
+
* Overall budget for one request, in milliseconds. Matches the Stripe SDKs (80s), which is
|
|
6
|
+
* generous enough for a large payload and bounded enough that an unresponsive API surfaces as an
|
|
7
|
+
* error instead of hanging the caller. `fetch` applies no timeout of its own in the browser, and
|
|
8
|
+
* only bounds response headers in Node.
|
|
9
|
+
*/
|
|
10
|
+
static DEFAULT_TIMEOUT_MS = 80_000;
|
|
11
|
+
static async request(request, timeoutMs = HttpClient.DEFAULT_TIMEOUT_MS) {
|
|
5
12
|
const init = {
|
|
6
13
|
method: request.method,
|
|
7
14
|
headers: request.headers,
|
|
8
15
|
};
|
|
16
|
+
if (timeoutMs > 0) {
|
|
17
|
+
init.signal = AbortSignal.timeout(timeoutMs);
|
|
18
|
+
}
|
|
9
19
|
// Node's fetch (undici) throws TypeError when GET/HEAD carry a body. Axios used to silently drop it,
|
|
10
20
|
// so callers may still set body on GET — skip it here instead of propagating a confusing network error.
|
|
11
21
|
const method = request.method.toUpperCase();
|
|
@@ -48,6 +58,16 @@ export class HttpClient {
|
|
|
48
58
|
if (error instanceof ClientError) {
|
|
49
59
|
throw error;
|
|
50
60
|
}
|
|
61
|
+
// AbortSignal.timeout rejects with a TimeoutError DOMException, whose message ("The
|
|
62
|
+
// operation was aborted due to timeout") says nothing about what was being called. Name
|
|
63
|
+
// the url and the budget instead.
|
|
64
|
+
//
|
|
65
|
+
// Matched on `name` rather than `instanceof`: a DOMException raised in another realm — a
|
|
66
|
+
// test runner's VM context, an iframe — is not an instance of this realm's Error, so an
|
|
67
|
+
// instanceof check passes locally and quietly fails everywhere else.
|
|
68
|
+
if (typeof error === 'object' && error !== null && error.name === 'TimeoutError') {
|
|
69
|
+
throw new ClientError('Request to `' + request.getFullUrl() + '` timed out after ' + timeoutMs + 'ms');
|
|
70
|
+
}
|
|
51
71
|
throw ClientError.fromError(error);
|
|
52
72
|
}
|
|
53
73
|
}
|
|
@@ -7,5 +7,7 @@ export declare class OAuthClientOptions {
|
|
|
7
7
|
redirectUri: string;
|
|
8
8
|
scopes: string[];
|
|
9
9
|
state: string;
|
|
10
|
+
/** Overall budget for one request, in milliseconds. Set 0 to disable (not recommended). */
|
|
11
|
+
timeoutMs: number;
|
|
10
12
|
constructor(apiEndpoint: string, clientId?: string | null, clientSecret?: string | null);
|
|
11
13
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { HttpClient } from './HttpClient.js';
|
|
1
2
|
export class OAuthClientOptions {
|
|
2
3
|
apiEndpoint;
|
|
3
4
|
clientId;
|
|
@@ -7,6 +8,8 @@ export class OAuthClientOptions {
|
|
|
7
8
|
redirectUri = 'https://example.com/auth/github/callback';
|
|
8
9
|
scopes = [];
|
|
9
10
|
state = '';
|
|
11
|
+
/** Overall budget for one request, in milliseconds. Set 0 to disable (not recommended). */
|
|
12
|
+
timeoutMs = HttpClient.DEFAULT_TIMEOUT_MS;
|
|
10
13
|
constructor(apiEndpoint,
|
|
11
14
|
// Mutable so client credentials can be updated in place (see OAuthClient.setClientCredentials)
|
|
12
15
|
// without recreating the client and losing its token.
|
|
@@ -49,6 +49,13 @@ export declare class OAuthClient implements ITransport {
|
|
|
49
49
|
setParseErrorHandler(handler: ParseErrorHandler | null): void;
|
|
50
50
|
reportParseError(message: string, context: Record<string, unknown>): void;
|
|
51
51
|
private defaultHeaders;
|
|
52
|
+
/**
|
|
53
|
+
* A copy, not the live object. Returning the internal map let callers mutate it by accident: a
|
|
54
|
+
* request assigned it and then set its own headers, so `Authorization` (and `Attlaz-API-Version`)
|
|
55
|
+
* were written into the shared defaults and sent on every later request — including the ones that
|
|
56
|
+
* deliberately pass `signWithOauthToken: false` (password reset, email confirmation, invite
|
|
57
|
+
* lookup, health). {@link addDefaultHeader} is the only way to add a real default.
|
|
58
|
+
*/
|
|
52
59
|
getDefaultHeaders(): Headers;
|
|
53
60
|
private initDefaultHeaders;
|
|
54
61
|
addDefaultHeader(header: string, value: string): void;
|
|
@@ -156,11 +156,31 @@ export class OAuthClient {
|
|
|
156
156
|
* server's HTTP status and, when the body is JSON, its structured error message.
|
|
157
157
|
*/
|
|
158
158
|
async requestToken(params) {
|
|
159
|
-
|
|
159
|
+
// The token endpoint bypasses HttpClient, so it does not inherit its timeout. Without one an
|
|
160
|
+
// unresponsive token endpoint hangs authenticate()/refreshToken() forever — and that is the
|
|
161
|
+
// one call every client makes before it can do anything else.
|
|
162
|
+
const timeoutMs = this.options.timeoutMs;
|
|
163
|
+
const init = {
|
|
160
164
|
method: 'POST',
|
|
161
165
|
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
|
|
162
166
|
body: new URLSearchParams(params).toString(),
|
|
163
|
-
}
|
|
167
|
+
};
|
|
168
|
+
if (timeoutMs > 0) {
|
|
169
|
+
init.signal = AbortSignal.timeout(timeoutMs);
|
|
170
|
+
}
|
|
171
|
+
const tokenUrl = this.getApiEndpointUrl(this.options.accessTokenUri);
|
|
172
|
+
let response;
|
|
173
|
+
try {
|
|
174
|
+
response = await fetch(tokenUrl, init);
|
|
175
|
+
}
|
|
176
|
+
catch (error) {
|
|
177
|
+
// Matched on `name`, not instanceof: a DOMException from another realm (a test runner's VM
|
|
178
|
+
// context, an iframe) is not an instance of this realm's Error. Same reasoning as HttpClient.
|
|
179
|
+
if (typeof error === 'object' && error !== null && error.name === 'TimeoutError') {
|
|
180
|
+
throw new ClientError('Token request to `' + tokenUrl + '` timed out after ' + timeoutMs + 'ms');
|
|
181
|
+
}
|
|
182
|
+
throw ClientError.fromError(error);
|
|
183
|
+
}
|
|
164
184
|
if (!response.ok) {
|
|
165
185
|
const clientError = new ClientError(response.statusText || 'Token request failed', response.status);
|
|
166
186
|
// The token endpoint bypasses HttpClient (and authenticate() bypasses Endpoint.toApiError),
|
|
@@ -208,7 +228,7 @@ export class OAuthClient {
|
|
|
208
228
|
console.debug('[OAuthClient] Request: ' + requestData.method.toUpperCase() + ' ' + requestData.getFullUrl(), { headers: requestData.headers });
|
|
209
229
|
}
|
|
210
230
|
try {
|
|
211
|
-
const response = await HttpClient.request(requestData);
|
|
231
|
+
const response = await HttpClient.request(requestData, this.options.timeoutMs);
|
|
212
232
|
return response.body;
|
|
213
233
|
}
|
|
214
234
|
catch (error) {
|
|
@@ -258,8 +278,15 @@ export class OAuthClient {
|
|
|
258
278
|
console.error(message, context);
|
|
259
279
|
}
|
|
260
280
|
defaultHeaders = {};
|
|
281
|
+
/**
|
|
282
|
+
* A copy, not the live object. Returning the internal map let callers mutate it by accident: a
|
|
283
|
+
* request assigned it and then set its own headers, so `Authorization` (and `Attlaz-API-Version`)
|
|
284
|
+
* were written into the shared defaults and sent on every later request — including the ones that
|
|
285
|
+
* deliberately pass `signWithOauthToken: false` (password reset, email confirmation, invite
|
|
286
|
+
* lookup, health). {@link addDefaultHeader} is the only way to add a real default.
|
|
287
|
+
*/
|
|
261
288
|
getDefaultHeaders() {
|
|
262
|
-
return this.defaultHeaders;
|
|
289
|
+
return { ...this.defaultHeaders };
|
|
263
290
|
}
|
|
264
291
|
initDefaultHeaders() {
|
|
265
292
|
const userAgentInfo = {
|
|
@@ -11,7 +11,11 @@ export declare class LogEndpoint extends Endpoint {
|
|
|
11
11
|
getLogs(logQuery: LogQuery): Promise<CollectionResult<Log>>;
|
|
12
12
|
getCursoredLogEntries(logStreamId: LogStreamId, pagination: CursorPagination | null, filter: FilterNode | null): Promise<CollectionResult<Log>>;
|
|
13
13
|
save(log: Log): Promise<Log>;
|
|
14
|
-
|
|
14
|
+
/**
|
|
15
|
+
* The stream id was missing here: the path was built with the literal text `:streamId`, so every
|
|
16
|
+
* call requested `/logstreams/:streamId/logs/<id>` and could never have matched the route.
|
|
17
|
+
*/
|
|
18
|
+
delete(logStreamId: string, logId: string): Promise<boolean>;
|
|
15
19
|
clear(logStreamId: LogStreamId): Promise<boolean>;
|
|
16
20
|
getInformation(logStreamId: LogStreamId): Promise<LogStreamInformation | null>;
|
|
17
21
|
getByProject(projectId: string, pagination?: CursorPagination | null): Promise<CollectionResult<LogStream>>;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { path } from '../../Http/Data/Path.js';
|
|
1
2
|
import { QueryString } from '../../Http/Data/QueryString.js';
|
|
2
3
|
import { Log } from '../Model/Log.js';
|
|
3
4
|
import { LogStream } from '../Model/LogStream.js';
|
|
@@ -36,12 +37,13 @@ export class LogEndpoint extends Endpoint {
|
|
|
36
37
|
const strTags = arrTags.join(',');
|
|
37
38
|
arrQuery.push('tags=' + strTags);
|
|
38
39
|
}
|
|
39
|
-
const cmd = '/logstreams/'
|
|
40
|
+
const cmd = path('/logstreams/:logStreamId/logs/', { logStreamId: logQuery.logStreamId.toString() })
|
|
41
|
+
+ '?' + arrQuery.join('&');
|
|
40
42
|
const result = await this.requestCollection(cmd, Log.parse);
|
|
41
43
|
return result;
|
|
42
44
|
}
|
|
43
45
|
async getCursoredLogEntries(logStreamId, pagination, filter) {
|
|
44
|
-
const queryString = new QueryString('/logstreams/'
|
|
46
|
+
const queryString = new QueryString(path('/logstreams/:logStreamId/logs', { logStreamId: logStreamId.toString() }));
|
|
45
47
|
queryString.addPagination(pagination);
|
|
46
48
|
if (filter !== null && filter !== undefined) {
|
|
47
49
|
queryString.set('filter', JSON.stringify(filter));
|
|
@@ -51,7 +53,7 @@ export class LogEndpoint extends Endpoint {
|
|
|
51
53
|
}
|
|
52
54
|
async save(log) {
|
|
53
55
|
try {
|
|
54
|
-
const cmd = '/logstreams/'
|
|
56
|
+
const cmd = path('/logstreams/:logStream/logs', { logStream: log.logStream.toString() });
|
|
55
57
|
const result = await this.requestObject(cmd, log, Log.parse, 'POST');
|
|
56
58
|
const updatedLogEntry = result.getData();
|
|
57
59
|
if (updatedLogEntry === null) {
|
|
@@ -66,8 +68,12 @@ export class LogEndpoint extends Endpoint {
|
|
|
66
68
|
throw error;
|
|
67
69
|
}
|
|
68
70
|
}
|
|
69
|
-
|
|
70
|
-
|
|
71
|
+
/**
|
|
72
|
+
* The stream id was missing here: the path was built with the literal text `:streamId`, so every
|
|
73
|
+
* call requested `/logstreams/:streamId/logs/<id>` and could never have matched the route.
|
|
74
|
+
*/
|
|
75
|
+
async delete(logStreamId, logId) {
|
|
76
|
+
const cmd = path('/logstreams/:logStreamId/logs/:logId', { logStreamId, logId });
|
|
71
77
|
try {
|
|
72
78
|
const parser = (raw) => ({ deleted: raw.deleted });
|
|
73
79
|
const result = await this.requestObject(cmd, null, parser, 'DELETE');
|
|
@@ -86,7 +92,7 @@ export class LogEndpoint extends Endpoint {
|
|
|
86
92
|
}
|
|
87
93
|
}
|
|
88
94
|
async clear(logStreamId) {
|
|
89
|
-
const cmd = '/logstreams/'
|
|
95
|
+
const cmd = path('/logstreams/:logStreamId/clear', { logStreamId: logStreamId.toString() });
|
|
90
96
|
try {
|
|
91
97
|
const parser = (raw) => ({ cleared: raw.cleared });
|
|
92
98
|
const result = await this.requestObject(cmd, null, parser, 'POST');
|
|
@@ -106,7 +112,7 @@ export class LogEndpoint extends Endpoint {
|
|
|
106
112
|
}
|
|
107
113
|
async getInformation(logStreamId) {
|
|
108
114
|
try {
|
|
109
|
-
const url = '/logstreams/'
|
|
115
|
+
const url = path('/logstreams/:logStreamId/info', { logStreamId: logStreamId.toString() });
|
|
110
116
|
const result = await this.requestObject(url, null, LogStreamInformation.parse);
|
|
111
117
|
return result.getData();
|
|
112
118
|
}
|
|
@@ -118,7 +124,7 @@ export class LogEndpoint extends Endpoint {
|
|
|
118
124
|
}
|
|
119
125
|
}
|
|
120
126
|
async getByProject(projectId, pagination = null) {
|
|
121
|
-
const queryString = new QueryString('projects/'
|
|
127
|
+
const queryString = new QueryString(path('projects/:projectId/logstreams', { projectId }));
|
|
122
128
|
queryString.addPagination(pagination);
|
|
123
129
|
const parser = (raw) => new LogStream(new LogStreamId(raw.id), raw.name);
|
|
124
130
|
const result = await this.requestCollection(queryString, parser);
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { path } from '../../Http/Data/Path.js';
|
|
1
2
|
import { QueryString } from '../../Http/Data/QueryString.js';
|
|
2
3
|
import { Endpoint } from '../../Service/Endpoint.js';
|
|
3
4
|
import { Competitor } from '../Model/Competitor.js';
|
|
@@ -7,17 +8,17 @@ import { Competitor } from '../Model/Competitor.js';
|
|
|
7
8
|
*/
|
|
8
9
|
export class CompetitorEndpoint extends Endpoint {
|
|
9
10
|
async getByCatalog(catalogId, pagination = null) {
|
|
10
|
-
const queryString = new QueryString('/pulse/catalogs/'
|
|
11
|
+
const queryString = new QueryString(path('/pulse/catalogs/:catalogId/competing-vendors', { catalogId: catalogId.toString() }));
|
|
11
12
|
queryString.addPagination(pagination);
|
|
12
13
|
return await this.requestCollection(queryString, Competitor.parse);
|
|
13
14
|
}
|
|
14
15
|
async getById(competitorId) {
|
|
15
|
-
const result = await this.requestObject('/pulse/competing-vendors
|
|
16
|
+
const result = await this.requestObject(path('/pulse/competing-vendors/:competitorId', { competitorId }), null, Competitor.parse, 'GET');
|
|
16
17
|
return result.getData();
|
|
17
18
|
}
|
|
18
19
|
/** Start watching a vendor as a competitor of this catalog. */
|
|
19
20
|
async add(catalogId, vendorId) {
|
|
20
|
-
const result = await this.requestObject('/pulse/catalogs/'
|
|
21
|
+
const result = await this.requestObject(path('/pulse/catalogs/:catalogId/competing-vendors', { catalogId: catalogId.toString() }), { vendor: vendorId }, Competitor.parse, 'POST');
|
|
21
22
|
return result.getData();
|
|
22
23
|
}
|
|
23
24
|
}
|
|
@@ -32,5 +32,6 @@ export declare class CrawlJobEndpoint extends Endpoint {
|
|
|
32
32
|
markPagesParsed(crawlJobId: string, urls: string[]): Promise<void>;
|
|
33
33
|
/** Mark pages as failed (terminal, e.g. blocked/unfetchable). */
|
|
34
34
|
markPagesFailed(crawlJobId: string, urls: string[]): Promise<void>;
|
|
35
|
+
/** @param suffix a literal trailing segment, e.g. `/pages/crawled` — not caller data. */
|
|
35
36
|
private postUrls;
|
|
36
37
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { path } from '../../Http/Data/Path.js';
|
|
1
2
|
import { QueryString } from '../../Http/Data/QueryString.js';
|
|
2
3
|
import { CrawlJob } from '../Model/CrawlJob.js';
|
|
3
4
|
import { Endpoint } from '../../Service/Endpoint.js';
|
|
@@ -18,7 +19,7 @@ export class CrawlJobEndpoint extends Endpoint {
|
|
|
18
19
|
}
|
|
19
20
|
/** Update a crawl job's status ('started', 'finished', 'cancelled'). */
|
|
20
21
|
async updateStatus(crawlJobId, status) {
|
|
21
|
-
const result = await this.requestObject('/pulse/crawl-jobs
|
|
22
|
+
const result = await this.requestObject(path('/pulse/crawl-jobs/:crawlJobId', { crawlJobId }), { status }, CrawlJob.parse, 'PATCH');
|
|
22
23
|
const job = result.getData();
|
|
23
24
|
if (job === null) {
|
|
24
25
|
throw new Error('Unable to update crawl job: empty response');
|
|
@@ -27,7 +28,7 @@ export class CrawlJobEndpoint extends Endpoint {
|
|
|
27
28
|
}
|
|
28
29
|
/** A vendor's crawl jobs (newest first), each with progress (`total` / `processed`). */
|
|
29
30
|
async getByVendor(vendorId, pagination = null) {
|
|
30
|
-
const queryString = new QueryString('/pulse/vendors/'
|
|
31
|
+
const queryString = new QueryString(path('/pulse/vendors/:vendorId/crawl-jobs', { vendorId }));
|
|
31
32
|
queryString.addPagination(pagination);
|
|
32
33
|
return await this.requestCollection(queryString, CrawlJob.parse);
|
|
33
34
|
}
|
|
@@ -38,13 +39,13 @@ export class CrawlJobEndpoint extends Endpoint {
|
|
|
38
39
|
* and returns the jobs of their vendors.
|
|
39
40
|
*/
|
|
40
41
|
async getByCatalog(catalogId, pagination = null) {
|
|
41
|
-
const queryString = new QueryString('/pulse/catalogs/'
|
|
42
|
+
const queryString = new QueryString(path('/pulse/catalogs/:catalogId/crawl-jobs', { catalogId: catalogId.toString() }));
|
|
42
43
|
queryString.addPagination(pagination);
|
|
43
44
|
return await this.requestCollection(queryString, CrawlJob.parse);
|
|
44
45
|
}
|
|
45
46
|
/** The crawl job with this id, or null. */
|
|
46
47
|
async getById(crawlJobId) {
|
|
47
|
-
const result = await this.requestObject('/pulse/crawl-jobs
|
|
48
|
+
const result = await this.requestObject(path('/pulse/crawl-jobs/:crawlJobId', { crawlJobId }), null, CrawlJob.parse, 'GET');
|
|
48
49
|
return result.getData();
|
|
49
50
|
}
|
|
50
51
|
/** Register the pages this crawl will process (idempotent server-side). */
|
|
@@ -63,10 +64,11 @@ export class CrawlJobEndpoint extends Endpoint {
|
|
|
63
64
|
async markPagesFailed(crawlJobId, urls) {
|
|
64
65
|
await this.postUrls(crawlJobId, '/pages/failed', urls);
|
|
65
66
|
}
|
|
66
|
-
|
|
67
|
+
/** @param suffix a literal trailing segment, e.g. `/pages/crawled` — not caller data. */
|
|
68
|
+
async postUrls(crawlJobId, suffix, urls) {
|
|
67
69
|
if (urls.length === 0) {
|
|
68
70
|
return;
|
|
69
71
|
}
|
|
70
|
-
await this.requestObject('/pulse/crawl-jobs
|
|
72
|
+
await this.requestObject(path('/pulse/crawl-jobs/:crawlJobId', { crawlJobId }) + suffix, { urls }, (raw) => raw, 'POST');
|
|
71
73
|
}
|
|
72
74
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { path } from '../../Http/Data/Path.js';
|
|
1
2
|
import { QueryString } from '../../Http/Data/QueryString.js';
|
|
2
3
|
import { Endpoint } from '../../Service/Endpoint.js';
|
|
3
4
|
import { IndexJob } from '../Model/IndexJob.js';
|
|
@@ -9,23 +10,23 @@ import { VendorStatus } from '../Model/VendorStatus.js';
|
|
|
9
10
|
export class IndexJobEndpoint extends Endpoint {
|
|
10
11
|
/** Index jobs across every competitor of a catalog, newest first. */
|
|
11
12
|
async getByCatalog(catalogId, pagination = null) {
|
|
12
|
-
const queryString = new QueryString('/pulse/catalogs/'
|
|
13
|
+
const queryString = new QueryString(path('/pulse/catalogs/:catalogId/index-jobs', { catalogId: catalogId.toString() }));
|
|
13
14
|
queryString.addPagination(pagination);
|
|
14
15
|
return await this.requestCollection(queryString, IndexJob.parse);
|
|
15
16
|
}
|
|
16
17
|
/** Index jobs of one competitor. */
|
|
17
18
|
async getByVendor(catalogId, vendorId, pagination = null) {
|
|
18
|
-
const queryString = new QueryString('/pulse/catalogs/'
|
|
19
|
+
const queryString = new QueryString(path('/pulse/catalogs/:catalogId/vendors/:vendorId/index-jobs', { catalogId: catalogId.toString(), vendorId }));
|
|
19
20
|
queryString.addPagination(pagination);
|
|
20
21
|
return await this.requestCollection(queryString, IndexJob.parse);
|
|
21
22
|
}
|
|
22
23
|
/** Queue a re-index of a competitor's products, so later matching sees current data. */
|
|
23
24
|
async requestReindex(catalogId, vendorId) {
|
|
24
|
-
await this.requestObject('/pulse/catalogs/'
|
|
25
|
+
await this.requestObject(path('/pulse/catalogs/:catalogId/vendors/:vendorId/reindex', { catalogId: catalogId.toString(), vendorId }), {}, (raw) => raw, 'POST');
|
|
25
26
|
}
|
|
26
27
|
/** How fresh a competitor's index and matches are, plus any match job running right now. */
|
|
27
28
|
async getVendorStatus(catalogId, vendorId) {
|
|
28
|
-
const result = await this.requestObject('/pulse/catalogs/'
|
|
29
|
+
const result = await this.requestObject(path('/pulse/catalogs/:catalogId/vendors/:vendorId/status', { catalogId: catalogId.toString(), vendorId }), null, VendorStatus.parse, 'GET');
|
|
29
30
|
return result.getData();
|
|
30
31
|
}
|
|
31
32
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { path } from '../../Http/Data/Path.js';
|
|
1
2
|
import { QueryString } from '../../Http/Data/QueryString.js';
|
|
2
3
|
import { Endpoint } from '../../Service/Endpoint.js';
|
|
3
4
|
import { PriceAlertConfig } from '../Model/PriceAlertConfig.js';
|
|
@@ -7,27 +8,27 @@ import { PriceAlertEvent } from '../Model/PriceAlertEvent.js';
|
|
|
7
8
|
*/
|
|
8
9
|
export class PriceAlertEndpoint extends Endpoint {
|
|
9
10
|
async getConfigs(catalogId, pagination = null) {
|
|
10
|
-
const queryString = new QueryString('/pulse/catalogs/'
|
|
11
|
+
const queryString = new QueryString(path('/pulse/catalogs/:catalogId/price-alert-configs', { catalogId: catalogId.toString() }));
|
|
11
12
|
queryString.addPagination(pagination);
|
|
12
13
|
return await this.requestCollection(queryString, PriceAlertConfig.parse);
|
|
13
14
|
}
|
|
14
15
|
async getConfig(alertConfigId) {
|
|
15
|
-
const result = await this.requestObject('/pulse/price-alert-configs
|
|
16
|
+
const result = await this.requestObject(path('/pulse/price-alert-configs/:alertConfigId', { alertConfigId }), null, PriceAlertConfig.parse, 'GET');
|
|
16
17
|
return result.getData();
|
|
17
18
|
}
|
|
18
19
|
async createConfig(catalogId, data) {
|
|
19
|
-
const result = await this.requestObject('/pulse/catalogs/'
|
|
20
|
+
const result = await this.requestObject(path('/pulse/catalogs/:catalogId/price-alert-configs', { catalogId: catalogId.toString() }), data, PriceAlertConfig.parse, 'POST');
|
|
20
21
|
return result.getData();
|
|
21
22
|
}
|
|
22
23
|
async updateConfig(alertConfigId, data) {
|
|
23
|
-
const result = await this.requestObject('/pulse/price-alert-configs
|
|
24
|
+
const result = await this.requestObject(path('/pulse/price-alert-configs/:alertConfigId', { alertConfigId }), data, PriceAlertConfig.parse, 'PATCH');
|
|
24
25
|
return result.getData();
|
|
25
26
|
}
|
|
26
27
|
async deleteConfig(alertConfigId) {
|
|
27
|
-
await this.requestObject('/pulse/price-alert-configs
|
|
28
|
+
await this.requestObject(path('/pulse/price-alert-configs/:alertConfigId', { alertConfigId }), null, (raw) => raw, 'DELETE');
|
|
28
29
|
}
|
|
29
30
|
async getEvents(alertConfigId, pagination = null) {
|
|
30
|
-
const queryString = new QueryString('/pulse/price-alert-configs/'
|
|
31
|
+
const queryString = new QueryString(path('/pulse/price-alert-configs/:alertConfigId/events', { alertConfigId }));
|
|
31
32
|
queryString.addPagination(pagination);
|
|
32
33
|
return await this.requestCollection(queryString, PriceAlertEvent.parse);
|
|
33
34
|
}
|
|
@@ -36,7 +37,7 @@ export class PriceAlertEndpoint extends Endpoint {
|
|
|
36
37
|
* when from the session, so the request carries no body.
|
|
37
38
|
*/
|
|
38
39
|
async acknowledgeEvent(alertEventId) {
|
|
39
|
-
const result = await this.requestObject('/pulse/price-alert-events
|
|
40
|
+
const result = await this.requestObject(path('/pulse/price-alert-events/:alertEventId', { alertEventId }), {}, PriceAlertEvent.parse, 'PATCH');
|
|
40
41
|
return result.getData();
|
|
41
42
|
}
|
|
42
43
|
}
|