@adobe/spacecat-shared-project-engine-client 1.18.1 → 1.19.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/README.md +25 -5
- package/package.json +2 -2
- package/src/client.js +1 -1
- package/src/generated/types.ts +178 -0
- package/src/index.d.ts +13 -1
- package/src/rest-transport.js +9 -1
package/README.md
CHANGED
|
@@ -47,8 +47,9 @@ const { data, error } = await client.GET('/v1/countries');
|
|
|
47
47
|
|
|
48
48
|
The spec is a **vendored file** — `spec/projectengine_swagger_public.yaml` — kept under
|
|
49
49
|
version control. Semrush only provides the file (no endpoint access in the near term), and
|
|
50
|
-
it's **Swagger 2.0** (no v3/v3.1 on offer). The vendored file is **never
|
|
51
|
-
|
|
50
|
+
it's **Swagger 2.0** (no v3/v3.1 on offer). The vendored file is **never hand-authored** — the only
|
|
51
|
+
thing that ever lands in it is what Semrush ships; where it diverges from the live API, a
|
|
52
|
+
generation-time overlay corrects the converted artifact instead (see
|
|
52
53
|
[Spec corrections](#spec-corrections)). Refresh is **manual**: drop in the newer file, re-run
|
|
53
54
|
`npm run generate`, and review the diff. A committed checksum lock
|
|
54
55
|
(`spec/projectengine_swagger_public.yaml.sha256`) is verified by `npm run spec:verify` (wired into
|
|
@@ -56,6 +57,18 @@ diverges from the live API, a generation-time overlay corrects the converted art
|
|
|
56
57
|
explicitly regenerated with `npm run spec:lock` and reviewed. A true live-drift contract test
|
|
57
58
|
against Semrush remains blocked on endpoint access.
|
|
58
59
|
|
|
60
|
+
Semrush sometimes delivers a **delta** instead of a whole document — a short YAML carrying only the
|
|
61
|
+
paths a release added. Splice those paths into the vendored file verbatim, in sorted position and in
|
|
62
|
+
the file's own block style (sequences flush with their key), leaving every other byte untouched, then
|
|
63
|
+
re-lock. Nothing is hand-authored, so the review evidence is a deep-compare of the spliced paths
|
|
64
|
+
against the delivered YAML:
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
node -e "const y=require('js-yaml'),f=require('fs');
|
|
68
|
+
const a=y.load(f.readFileSync('<delivered>.yaml','utf8')),b=y.load(f.readFileSync('spec/projectengine_swagger_public.yaml','utf8'));
|
|
69
|
+
for (const p of Object.keys(a.paths)) console.log(p, JSON.stringify(a.paths[p])===JSON.stringify(b.paths[p]));"
|
|
70
|
+
```
|
|
71
|
+
|
|
59
72
|
Both scripts use a **package-root-relative** path and assume the working directory is this
|
|
60
73
|
package root — always invoke them via `npm run spec:verify` / `npm run spec:lock`, which npm
|
|
61
74
|
runs from the package root, rather than calling `shasum -c` by hand from the monorepo root or a
|
|
@@ -101,13 +114,20 @@ pip install datamodel-code-generator
|
|
|
101
114
|
|
|
102
115
|
## Spec corrections
|
|
103
116
|
|
|
104
|
-
The vendored swagger diverges from the live API in
|
|
117
|
+
The vendored swagger diverges from the live API in a number of places. A small OpenAPI Overlay
|
|
105
118
|
(`spec/overlays/corrections.yaml`), applied to the converted OAS3 artifact at generation time by
|
|
106
|
-
`scripts/apply-overlay.mjs`, corrects them; the vendored
|
|
107
|
-
|
|
119
|
+
`scripts/apply-overlay.mjs`, corrects them; no correction is ever written into the vendored
|
|
120
|
+
`spec/projectengine_swagger_public.yaml`.
|
|
108
121
|
|
|
109
122
|
- **CR1 — missing endpoint.** Adds `GET /v1/ai_models` (the live global model catalog), which is
|
|
110
123
|
absent from the upstream swagger.
|
|
124
|
+
- **CR23 — missing response field.** Adds `is_paused` to `model.ProjectResponse`. The swagger
|
|
125
|
+
delta that shipped `pause`/`resume` added the two action paths but left the response schema
|
|
126
|
+
alone, so the generated type had no way to express whether a project is paused. Live returns the
|
|
127
|
+
key on every project read.
|
|
128
|
+
- **CR24 — missing status.** Declares the `404` that `pause`/`resume` return for an unknown project
|
|
129
|
+
id. Live pause is idempotent (a second pause is another `202`); only `resume` uses the declared
|
|
130
|
+
`409`, and it does so with `{"message": "project is not paused"}`.
|
|
111
131
|
- **CR2 — auth.** The spec models a required `Auth-Data-Jwt` header, but the live API authenticates
|
|
112
132
|
on `Authorization: Bearer <IMS>` only — Semrush accepts the IMS bearer directly. The overlay
|
|
113
133
|
removes `Auth-Data-Jwt` from every operation and adds an `imsBearer` security scheme.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@adobe/spacecat-shared-project-engine-client",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.19.0",
|
|
4
4
|
"description": "Shared modules of the Spacecat Services - Semrush Project Engine client and generated types",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "src/index.js",
|
|
@@ -63,7 +63,7 @@
|
|
|
63
63
|
"c8": "11.0.0",
|
|
64
64
|
"chai": "6.2.2",
|
|
65
65
|
"counterfact": "2.14.0",
|
|
66
|
-
"js-yaml": "4.3.
|
|
66
|
+
"js-yaml": "4.3.1",
|
|
67
67
|
"mocha": "11.7.6",
|
|
68
68
|
"mocha-multi-reporters": "1.5.1",
|
|
69
69
|
"openapi-typescript": "7.13.0",
|
package/src/client.js
CHANGED
|
@@ -28,7 +28,7 @@ import { createRetryingFetch, toTokenGetter } from './internal.js';
|
|
|
28
28
|
/**
|
|
29
29
|
* @typedef {object} SerenityProjectEngineApiClientOptions
|
|
30
30
|
* @property {string} baseUrl Base URL of the Project Engine API — the origin of
|
|
31
|
-
* `SEMRUSH_PROJECTS_BASE_URL` (e.g. `https://
|
|
31
|
+
* `SEMRUSH_PROJECTS_BASE_URL` (e.g. `https://www.semrush.com`), or the Counterfact
|
|
32
32
|
* mock's origin for E2E / local dev. Only `protocol//host` is used; any path is dropped and the
|
|
33
33
|
* client appends the fixed `/enterprise/projects/api` prefix itself, matching the deployed
|
|
34
34
|
* api-service transport (`rest-transport.js`).
|
package/src/generated/types.ts
CHANGED
|
@@ -883,6 +883,26 @@ export interface paths {
|
|
|
883
883
|
patch?: never;
|
|
884
884
|
trace?: never;
|
|
885
885
|
};
|
|
886
|
+
"/v1/workspaces/{id}/projects/{project_id}/pause": {
|
|
887
|
+
parameters: {
|
|
888
|
+
query?: never;
|
|
889
|
+
header?: never;
|
|
890
|
+
path?: never;
|
|
891
|
+
cookie?: never;
|
|
892
|
+
};
|
|
893
|
+
get?: never;
|
|
894
|
+
put?: never;
|
|
895
|
+
/**
|
|
896
|
+
* pause a project
|
|
897
|
+
* @description pause an AIO project: prompt limits are released and data collection stops while configuration and historical data are preserved
|
|
898
|
+
*/
|
|
899
|
+
post: operations["projects-pause-project"];
|
|
900
|
+
delete?: never;
|
|
901
|
+
options?: never;
|
|
902
|
+
head?: never;
|
|
903
|
+
patch?: never;
|
|
904
|
+
trace?: never;
|
|
905
|
+
};
|
|
886
906
|
"/v1/workspaces/{id}/projects/{project_id}/publish": {
|
|
887
907
|
parameters: {
|
|
888
908
|
query?: never;
|
|
@@ -903,6 +923,26 @@ export interface paths {
|
|
|
903
923
|
patch?: never;
|
|
904
924
|
trace?: never;
|
|
905
925
|
};
|
|
926
|
+
"/v1/workspaces/{id}/projects/{project_id}/resume": {
|
|
927
|
+
parameters: {
|
|
928
|
+
query?: never;
|
|
929
|
+
header?: never;
|
|
930
|
+
path?: never;
|
|
931
|
+
cookie?: never;
|
|
932
|
+
};
|
|
933
|
+
get?: never;
|
|
934
|
+
put?: never;
|
|
935
|
+
/**
|
|
936
|
+
* resume a paused project
|
|
937
|
+
* @description resume a paused AIO project: re-consumes prompt limits (subject to the same quota check as publishing) and data collection continues
|
|
938
|
+
*/
|
|
939
|
+
post: operations["projects-resume-project"];
|
|
940
|
+
delete?: never;
|
|
941
|
+
options?: never;
|
|
942
|
+
head?: never;
|
|
943
|
+
patch?: never;
|
|
944
|
+
trace?: never;
|
|
945
|
+
};
|
|
906
946
|
"/v1/workspaces/{id}/projects/{project_id}/segments": {
|
|
907
947
|
parameters: {
|
|
908
948
|
query?: never;
|
|
@@ -2385,6 +2425,8 @@ export interface components {
|
|
|
2385
2425
|
/** @description enum: aio,mfour,ci */
|
|
2386
2426
|
type?: string;
|
|
2387
2427
|
updated_at?: string;
|
|
2428
|
+
/** @description whether the project is paused: prompt limits released and data collection stopped, configuration and historical data preserved */
|
|
2429
|
+
is_paused: boolean;
|
|
2388
2430
|
};
|
|
2389
2431
|
"model.ProjectUpdateRequest": {
|
|
2390
2432
|
brand_name_display?: string;
|
|
@@ -5790,6 +5832,74 @@ export interface operations {
|
|
|
5790
5832
|
};
|
|
5791
5833
|
};
|
|
5792
5834
|
};
|
|
5835
|
+
"projects-pause-project": {
|
|
5836
|
+
parameters: {
|
|
5837
|
+
query?: never;
|
|
5838
|
+
header?: never;
|
|
5839
|
+
path: {
|
|
5840
|
+
/** @description workspace ID */
|
|
5841
|
+
id: string;
|
|
5842
|
+
/** @description project ID */
|
|
5843
|
+
project_id: string;
|
|
5844
|
+
};
|
|
5845
|
+
cookie?: never;
|
|
5846
|
+
};
|
|
5847
|
+
requestBody?: never;
|
|
5848
|
+
responses: {
|
|
5849
|
+
/** @description Accepted */
|
|
5850
|
+
202: {
|
|
5851
|
+
headers: {
|
|
5852
|
+
[name: string]: unknown;
|
|
5853
|
+
};
|
|
5854
|
+
content?: never;
|
|
5855
|
+
};
|
|
5856
|
+
/** @description Unauthorized */
|
|
5857
|
+
401: {
|
|
5858
|
+
headers: {
|
|
5859
|
+
[name: string]: unknown;
|
|
5860
|
+
};
|
|
5861
|
+
content: {
|
|
5862
|
+
"application/json": components["schemas"]["http_server.BasicResponse"];
|
|
5863
|
+
};
|
|
5864
|
+
};
|
|
5865
|
+
/** @description Forbidden */
|
|
5866
|
+
403: {
|
|
5867
|
+
headers: {
|
|
5868
|
+
[name: string]: unknown;
|
|
5869
|
+
};
|
|
5870
|
+
content: {
|
|
5871
|
+
"application/json": components["schemas"]["http_server.BasicResponse"];
|
|
5872
|
+
};
|
|
5873
|
+
};
|
|
5874
|
+
/** @description Not Found */
|
|
5875
|
+
404: {
|
|
5876
|
+
headers: {
|
|
5877
|
+
[name: string]: unknown;
|
|
5878
|
+
};
|
|
5879
|
+
content: {
|
|
5880
|
+
"application/json": components["schemas"]["http_server.BasicResponse"];
|
|
5881
|
+
};
|
|
5882
|
+
};
|
|
5883
|
+
/** @description Conflict */
|
|
5884
|
+
409: {
|
|
5885
|
+
headers: {
|
|
5886
|
+
[name: string]: unknown;
|
|
5887
|
+
};
|
|
5888
|
+
content: {
|
|
5889
|
+
"application/json": components["schemas"]["http_server.BasicResponse"];
|
|
5890
|
+
};
|
|
5891
|
+
};
|
|
5892
|
+
/** @description Internal Server Error */
|
|
5893
|
+
500: {
|
|
5894
|
+
headers: {
|
|
5895
|
+
[name: string]: unknown;
|
|
5896
|
+
};
|
|
5897
|
+
content: {
|
|
5898
|
+
"application/json": components["schemas"]["http_server.BasicResponse"];
|
|
5899
|
+
};
|
|
5900
|
+
};
|
|
5901
|
+
};
|
|
5902
|
+
};
|
|
5793
5903
|
"projects-publish-project": {
|
|
5794
5904
|
parameters: {
|
|
5795
5905
|
query?: never;
|
|
@@ -5840,6 +5950,74 @@ export interface operations {
|
|
|
5840
5950
|
};
|
|
5841
5951
|
};
|
|
5842
5952
|
};
|
|
5953
|
+
"projects-resume-project": {
|
|
5954
|
+
parameters: {
|
|
5955
|
+
query?: never;
|
|
5956
|
+
header?: never;
|
|
5957
|
+
path: {
|
|
5958
|
+
/** @description workspace ID */
|
|
5959
|
+
id: string;
|
|
5960
|
+
/** @description project ID */
|
|
5961
|
+
project_id: string;
|
|
5962
|
+
};
|
|
5963
|
+
cookie?: never;
|
|
5964
|
+
};
|
|
5965
|
+
requestBody?: never;
|
|
5966
|
+
responses: {
|
|
5967
|
+
/** @description Accepted */
|
|
5968
|
+
202: {
|
|
5969
|
+
headers: {
|
|
5970
|
+
[name: string]: unknown;
|
|
5971
|
+
};
|
|
5972
|
+
content?: never;
|
|
5973
|
+
};
|
|
5974
|
+
/** @description Unauthorized */
|
|
5975
|
+
401: {
|
|
5976
|
+
headers: {
|
|
5977
|
+
[name: string]: unknown;
|
|
5978
|
+
};
|
|
5979
|
+
content: {
|
|
5980
|
+
"application/json": components["schemas"]["http_server.BasicResponse"];
|
|
5981
|
+
};
|
|
5982
|
+
};
|
|
5983
|
+
/** @description Forbidden */
|
|
5984
|
+
403: {
|
|
5985
|
+
headers: {
|
|
5986
|
+
[name: string]: unknown;
|
|
5987
|
+
};
|
|
5988
|
+
content: {
|
|
5989
|
+
"application/json": components["schemas"]["http_server.BasicResponse"];
|
|
5990
|
+
};
|
|
5991
|
+
};
|
|
5992
|
+
/** @description Not Found */
|
|
5993
|
+
404: {
|
|
5994
|
+
headers: {
|
|
5995
|
+
[name: string]: unknown;
|
|
5996
|
+
};
|
|
5997
|
+
content: {
|
|
5998
|
+
"application/json": components["schemas"]["http_server.BasicResponse"];
|
|
5999
|
+
};
|
|
6000
|
+
};
|
|
6001
|
+
/** @description Conflict */
|
|
6002
|
+
409: {
|
|
6003
|
+
headers: {
|
|
6004
|
+
[name: string]: unknown;
|
|
6005
|
+
};
|
|
6006
|
+
content: {
|
|
6007
|
+
"application/json": components["schemas"]["http_server.BasicResponse"];
|
|
6008
|
+
};
|
|
6009
|
+
};
|
|
6010
|
+
/** @description Internal Server Error */
|
|
6011
|
+
500: {
|
|
6012
|
+
headers: {
|
|
6013
|
+
[name: string]: unknown;
|
|
6014
|
+
};
|
|
6015
|
+
content: {
|
|
6016
|
+
"application/json": components["schemas"]["http_server.BasicResponse"];
|
|
6017
|
+
};
|
|
6018
|
+
};
|
|
6019
|
+
};
|
|
6020
|
+
};
|
|
5843
6021
|
"project-list-segments": {
|
|
5844
6022
|
parameters: {
|
|
5845
6023
|
query?: {
|
package/src/index.d.ts
CHANGED
|
@@ -111,7 +111,7 @@ type TransportData<P extends keyof paths, M extends keyof paths[P]> =
|
|
|
111
111
|
| null;
|
|
112
112
|
|
|
113
113
|
/**
|
|
114
|
-
* Intent-named facade over {@link SerenityProjectEngineApiClient}. Wraps the
|
|
114
|
+
* Intent-named facade over {@link SerenityProjectEngineApiClient}. Wraps the 34 in-spec
|
|
115
115
|
* Project Engine operations spacecat-api-service consumes behind verb+resource methods, so
|
|
116
116
|
* consumers depend on this seam rather than the raw client's literal path strings. Each method
|
|
117
117
|
* is THIN: it forwards the caller's openapi-fetch `init` to the underlying client and resolves
|
|
@@ -157,6 +157,18 @@ export interface SerenityProjectEngineTransport {
|
|
|
157
157
|
TransportInit<'/v1/workspaces/{id}/projects/{project_id}/publish', 'post'>
|
|
158
158
|
>
|
|
159
159
|
): Promise<TransportData<'/v1/workspaces/{id}/projects/{project_id}/publish', 'post'>>;
|
|
160
|
+
/** POST /v1/workspaces/{id}/projects/{project_id}/pause — projects-pause-project */
|
|
161
|
+
pauseProject(
|
|
162
|
+
...init: TransportInitParam<
|
|
163
|
+
TransportInit<'/v1/workspaces/{id}/projects/{project_id}/pause', 'post'>
|
|
164
|
+
>
|
|
165
|
+
): Promise<TransportData<'/v1/workspaces/{id}/projects/{project_id}/pause', 'post'>>;
|
|
166
|
+
/** POST /v1/workspaces/{id}/projects/{project_id}/resume — projects-resume-project */
|
|
167
|
+
resumeProject(
|
|
168
|
+
...init: TransportInitParam<
|
|
169
|
+
TransportInit<'/v1/workspaces/{id}/projects/{project_id}/resume', 'post'>
|
|
170
|
+
>
|
|
171
|
+
): Promise<TransportData<'/v1/workspaces/{id}/projects/{project_id}/resume', 'post'>>;
|
|
160
172
|
|
|
161
173
|
/** GET /v1/workspaces/{id}/projects/{project_id}/ai_models — ai-list-models */
|
|
162
174
|
listAiModels(
|
package/src/rest-transport.js
CHANGED
|
@@ -22,7 +22,7 @@ import { ProjectEngineApiError } from './errors.js';
|
|
|
22
22
|
|
|
23
23
|
/**
|
|
24
24
|
* Intent-named facade over the raw {@link createSerenityProjectEngineApiClient} openapi-fetch
|
|
25
|
-
* client. It wraps ONLY the
|
|
25
|
+
* client. It wraps ONLY the 34 in-spec Project Engine operations that spacecat-api-service
|
|
26
26
|
* consumes, behind verb+resource method names, so consumers depend on this seam rather than the
|
|
27
27
|
* raw client and its literal path strings. Each method is THIN: it forwards the caller's
|
|
28
28
|
* openapi-fetch `init` (params.path/query, body) to `client.<METHOD>('<literal path>', init)` and
|
|
@@ -119,6 +119,14 @@ export function createSerenityProjectEngineTransport(options) {
|
|
|
119
119
|
publishProject(init) {
|
|
120
120
|
return unwrap('POST', client.POST('/v1/workspaces/{id}/projects/{project_id}/publish', init));
|
|
121
121
|
},
|
|
122
|
+
/** POST /v1/workspaces/{id}/projects/{project_id}/pause — projects-pause-project */
|
|
123
|
+
pauseProject(init) {
|
|
124
|
+
return unwrap('POST', client.POST('/v1/workspaces/{id}/projects/{project_id}/pause', init));
|
|
125
|
+
},
|
|
126
|
+
/** POST /v1/workspaces/{id}/projects/{project_id}/resume — projects-resume-project */
|
|
127
|
+
resumeProject(init) {
|
|
128
|
+
return unwrap('POST', client.POST('/v1/workspaces/{id}/projects/{project_id}/resume', init));
|
|
129
|
+
},
|
|
122
130
|
|
|
123
131
|
// ─── /v1 AI models + benchmarks ───────────────────────────────────────────
|
|
124
132
|
/** GET /v1/workspaces/{id}/projects/{project_id}/ai_models — ai-list-models */
|