@medalsocial/sdk 1.7.0 → 1.8.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 +38 -0
- package/dist/openapi/medal-social.openapi.json +686 -0
- package/dist/pilot/index.d.mts +2 -2
- package/dist/pilot/index.d.ts +2 -2
- package/dist/src/index.d.mts +230 -3
- package/dist/src/index.d.ts +230 -3
- package/dist/src/index.js +144 -19
- package/dist/src/index.js.map +1 -1
- package/dist/src/index.mjs +143 -19
- package/dist/src/index.mjs.map +1 -1
- package/dist/src/openapi.generated.d.mts +473 -0
- package/dist/src/openapi.generated.d.ts +473 -0
- package/dist/src/openapi.generated.js.map +1 -1
- package/openapi/medal-social.openapi.yaml +446 -0
- package/package.json +1 -1
- package/skills/client/SKILL.md +2 -0
- package/skills/resources/SKILL.md +50 -2
package/dist/src/index.mjs
CHANGED
|
@@ -35,17 +35,21 @@ var BaseClient = class {
|
|
|
35
35
|
this.config = config;
|
|
36
36
|
}
|
|
37
37
|
/** Execute an authenticated GET request and return the parsed JSON body. */
|
|
38
|
-
async get(path, params) {
|
|
38
|
+
async get(path, params, options) {
|
|
39
39
|
const url = this.buildUrl(path, params);
|
|
40
|
-
return this.request(url, { method: "GET" });
|
|
40
|
+
return this.request(url, { method: "GET", headers: options?.headers });
|
|
41
41
|
}
|
|
42
42
|
/** Execute an authenticated POST request with a JSON body. */
|
|
43
43
|
async post(path, body, options) {
|
|
44
|
-
return this.request(
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
44
|
+
return this.request(
|
|
45
|
+
this.buildUrl(path),
|
|
46
|
+
{
|
|
47
|
+
method: "POST",
|
|
48
|
+
headers: this.writeHeaders(options),
|
|
49
|
+
body: body !== void 0 ? JSON.stringify(body) : void 0
|
|
50
|
+
},
|
|
51
|
+
options?.retry
|
|
52
|
+
);
|
|
49
53
|
}
|
|
50
54
|
/**
|
|
51
55
|
* Execute a POST that must never execute twice, guaranteeing an
|
|
@@ -72,21 +76,33 @@ var BaseClient = class {
|
|
|
72
76
|
}
|
|
73
77
|
/** Execute an authenticated PATCH request with a JSON body. */
|
|
74
78
|
async patch(path, body, options) {
|
|
75
|
-
return this.request(
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
79
|
+
return this.request(
|
|
80
|
+
this.buildUrl(path),
|
|
81
|
+
{
|
|
82
|
+
method: "PATCH",
|
|
83
|
+
headers: this.writeHeaders(options),
|
|
84
|
+
body: JSON.stringify(body)
|
|
85
|
+
},
|
|
86
|
+
options?.retry
|
|
87
|
+
);
|
|
80
88
|
}
|
|
81
89
|
/** Execute an authenticated DELETE request. */
|
|
82
90
|
async delete(path, options) {
|
|
83
|
-
return this.request(
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
91
|
+
return this.request(
|
|
92
|
+
this.buildUrl(path),
|
|
93
|
+
{
|
|
94
|
+
method: "DELETE",
|
|
95
|
+
headers: this.writeHeaders(options)
|
|
96
|
+
},
|
|
97
|
+
options?.retry
|
|
98
|
+
);
|
|
87
99
|
}
|
|
88
100
|
writeHeaders(options) {
|
|
89
|
-
const headers = {
|
|
101
|
+
const headers = {};
|
|
102
|
+
for (const [key, value] of Object.entries(options?.headers ?? {})) {
|
|
103
|
+
headers[key.toLowerCase()] = value;
|
|
104
|
+
}
|
|
105
|
+
headers["content-type"] = "application/json";
|
|
90
106
|
if (options?.idempotencyKey) {
|
|
91
107
|
headers["idempotency-key"] = options.idempotencyKey;
|
|
92
108
|
}
|
|
@@ -106,8 +122,8 @@ var BaseClient = class {
|
|
|
106
122
|
}
|
|
107
123
|
return url.toString();
|
|
108
124
|
}
|
|
109
|
-
async request(url, init) {
|
|
110
|
-
const maxAttempts = 3;
|
|
125
|
+
async request(url, init, retry = true) {
|
|
126
|
+
const maxAttempts = retry ? 3 : 1;
|
|
111
127
|
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
|
|
112
128
|
const headers = new Headers(init.headers);
|
|
113
129
|
headers.set("authorization", `Bearer ${this.config.token}`);
|
|
@@ -881,6 +897,111 @@ var Helpdesk = class {
|
|
|
881
897
|
}
|
|
882
898
|
};
|
|
883
899
|
|
|
900
|
+
// src/resources/portal.ts
|
|
901
|
+
function withSession(session) {
|
|
902
|
+
return { headers: { "x-portal-session": session } };
|
|
903
|
+
}
|
|
904
|
+
var ONCE = { retry: false };
|
|
905
|
+
var PortalLogin = class {
|
|
906
|
+
constructor(client) {
|
|
907
|
+
this.client = client;
|
|
908
|
+
}
|
|
909
|
+
client;
|
|
910
|
+
/**
|
|
911
|
+
* E-mail a one-time code to the address.
|
|
912
|
+
*
|
|
913
|
+
* Always 202 `{ status: "sent" }` — enumeration-safe: `"sent"` does not
|
|
914
|
+
* confirm that the address belongs to a contact. Rate-limited per address
|
|
915
|
+
* and per caller (`429 RATE_LIMITED`).
|
|
916
|
+
*/
|
|
917
|
+
async start(input) {
|
|
918
|
+
return this.client.post("/api/v1/portal/login/start", input);
|
|
919
|
+
}
|
|
920
|
+
/**
|
|
921
|
+
* Exchange the e-mailed code for a session.
|
|
922
|
+
*
|
|
923
|
+
* `session_token` is a bearer credential for ONE contact — keep it in an
|
|
924
|
+
* HttpOnly cookie on the site's server. A wrong, burned or expired code all
|
|
925
|
+
* answer `401 PORTAL_CODE_INVALID`; the three are not distinguished, so the
|
|
926
|
+
* response is not an oracle for which codes exist.
|
|
927
|
+
*/
|
|
928
|
+
async verify(input) {
|
|
929
|
+
return this.client.post("/api/v1/portal/login/verify", input, ONCE);
|
|
930
|
+
}
|
|
931
|
+
};
|
|
932
|
+
var Portal = class {
|
|
933
|
+
constructor(client) {
|
|
934
|
+
this.client = client;
|
|
935
|
+
this.login = new PortalLogin(client);
|
|
936
|
+
}
|
|
937
|
+
client;
|
|
938
|
+
/** E-mail one-time-code login: `start` sends the code, `verify` exchanges it. */
|
|
939
|
+
login;
|
|
940
|
+
/**
|
|
941
|
+
* Revoke the session. Resolves to `undefined` (the route answers 204).
|
|
942
|
+
*
|
|
943
|
+
* Not keyed: revoking twice reaches the same state — the second call answers
|
|
944
|
+
* `401 PORTAL_SESSION_INVALID`, which is the outcome you wanted anyway.
|
|
945
|
+
*/
|
|
946
|
+
async logout(session) {
|
|
947
|
+
await this.client.post("/api/v1/portal/logout", void 0, {
|
|
948
|
+
...withSession(session),
|
|
949
|
+
...ONCE
|
|
950
|
+
});
|
|
951
|
+
}
|
|
952
|
+
/** The signed-in contact's own profile. */
|
|
953
|
+
async me(session) {
|
|
954
|
+
return this.client.get("/api/v1/portal/me", void 0, withSession(session));
|
|
955
|
+
}
|
|
956
|
+
/**
|
|
957
|
+
* Update the signed-in contact's profile. Only the supplied fields change;
|
|
958
|
+
* `phone: null` clears the number and `family` replaces the whole list.
|
|
959
|
+
* `marketing_consent` records a `marketing_email` consent decision with
|
|
960
|
+
* source `portal`. Returns the profile as it is after the change.
|
|
961
|
+
*/
|
|
962
|
+
/**
|
|
963
|
+
* A profile patch is not idempotency-keyed on the server and a `marketing_consent`
|
|
964
|
+
* change records a dated consent event, so a retry after a committed-but-lost
|
|
965
|
+
* response would repeat that event: sent exactly once, like the other writes.
|
|
966
|
+
*/
|
|
967
|
+
async updateMe(session, patch) {
|
|
968
|
+
return this.client.patch("/api/v1/portal/me", patch, { ...withSession(session), ...ONCE });
|
|
969
|
+
}
|
|
970
|
+
/**
|
|
971
|
+
* The contact's bookings split into `upcoming` and `past`. An upcoming
|
|
972
|
+
* booking that is still inside the workspace's policy windows carries
|
|
973
|
+
* `manage_token` and `can_manage: true`; use the token to open the site's
|
|
974
|
+
* manage page (`medal.bookings.manage.*`).
|
|
975
|
+
*/
|
|
976
|
+
async myBookings(session) {
|
|
977
|
+
return this.client.get("/api/v1/portal/me/bookings", void 0, withSession(session));
|
|
978
|
+
}
|
|
979
|
+
/**
|
|
980
|
+
* Everything the workspace holds about the contact — profile, family,
|
|
981
|
+
* consents and bookings — as one JSON document (GDPR Art. 15). Synchronous,
|
|
982
|
+
* unlike `medal.gdpr.requestExport()`, which exports the whole workspace.
|
|
983
|
+
*
|
|
984
|
+
* Not keyed: a read-only snapshot, so a retried call costs nothing and
|
|
985
|
+
* duplicates nothing.
|
|
986
|
+
*/
|
|
987
|
+
async exportMyData(session) {
|
|
988
|
+
return this.client.post("/api/v1/portal/me/export", void 0, withSession(session));
|
|
989
|
+
}
|
|
990
|
+
/**
|
|
991
|
+
* Erase the contact (GDPR Art. 17). Resolves to `undefined` (the route
|
|
992
|
+
* answers 204); the session is revoked as part of the deletion.
|
|
993
|
+
*
|
|
994
|
+
* Not keyed: deletion is terminal, so a retry meets a revoked session and
|
|
995
|
+
* answers `401 PORTAL_SESSION_INVALID` rather than deleting anything else.
|
|
996
|
+
*/
|
|
997
|
+
async deleteMe(session) {
|
|
998
|
+
await this.client.post("/api/v1/portal/me/delete", void 0, {
|
|
999
|
+
...withSession(session),
|
|
1000
|
+
...ONCE
|
|
1001
|
+
});
|
|
1002
|
+
}
|
|
1003
|
+
};
|
|
1004
|
+
|
|
884
1005
|
// src/resources/posts.ts
|
|
885
1006
|
var Posts = class {
|
|
886
1007
|
constructor(client) {
|
|
@@ -1186,6 +1307,7 @@ var Medal = class {
|
|
|
1186
1307
|
deals;
|
|
1187
1308
|
gdpr;
|
|
1188
1309
|
helpdesk;
|
|
1310
|
+
portal;
|
|
1189
1311
|
posts;
|
|
1190
1312
|
scan;
|
|
1191
1313
|
webhooks;
|
|
@@ -1215,6 +1337,7 @@ var Medal = class {
|
|
|
1215
1337
|
this.deals = new Deals(client);
|
|
1216
1338
|
this.gdpr = new Gdpr(client);
|
|
1217
1339
|
this.helpdesk = new Helpdesk(client, confirmer);
|
|
1340
|
+
this.portal = new Portal(client);
|
|
1218
1341
|
this.posts = new Posts(client);
|
|
1219
1342
|
this.scan = new Scan(client);
|
|
1220
1343
|
this.webhooks = new Webhooks(client, confirmer);
|
|
@@ -1241,6 +1364,7 @@ export {
|
|
|
1241
1364
|
Helpdesk,
|
|
1242
1365
|
Medal,
|
|
1243
1366
|
MedalApiError,
|
|
1367
|
+
Portal,
|
|
1244
1368
|
Posts,
|
|
1245
1369
|
Scan,
|
|
1246
1370
|
WebhookVerificationError,
|