@medalsocial/sdk 1.7.0 → 1.9.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 +63 -0
- package/dist/openapi/medal-social.openapi.json +1842 -258
- package/dist/pilot/index.d.mts +2 -2
- package/dist/pilot/index.d.ts +2 -2
- package/dist/src/index.d.mts +418 -3
- package/dist/src/index.d.ts +418 -3
- package/dist/src/index.js +205 -19
- package/dist/src/index.js.map +1 -1
- package/dist/src/index.mjs +204 -19
- package/dist/src/index.mjs.map +1 -1
- package/dist/src/openapi.generated.d.mts +912 -18
- package/dist/src/openapi.generated.d.ts +912 -18
- package/dist/src/openapi.generated.js.map +1 -1
- package/openapi/medal-social.openapi.yaml +1024 -43
- package/package.json +1 -1
- package/skills/client/SKILL.md +2 -0
- package/skills/resources/SKILL.md +53 -2
package/dist/src/index.js
CHANGED
|
@@ -35,6 +35,7 @@ __export(src_exports, {
|
|
|
35
35
|
Helpdesk: () => Helpdesk,
|
|
36
36
|
Medal: () => Medal,
|
|
37
37
|
MedalApiError: () => MedalApiError,
|
|
38
|
+
Portal: () => Portal,
|
|
38
39
|
Posts: () => Posts,
|
|
39
40
|
Scan: () => Scan,
|
|
40
41
|
WebhookVerificationError: () => WebhookVerificationError,
|
|
@@ -83,17 +84,21 @@ var BaseClient = class {
|
|
|
83
84
|
this.config = config;
|
|
84
85
|
}
|
|
85
86
|
/** Execute an authenticated GET request and return the parsed JSON body. */
|
|
86
|
-
async get(path, params) {
|
|
87
|
+
async get(path, params, options) {
|
|
87
88
|
const url = this.buildUrl(path, params);
|
|
88
|
-
return this.request(url, { method: "GET" });
|
|
89
|
+
return this.request(url, { method: "GET", headers: options?.headers });
|
|
89
90
|
}
|
|
90
91
|
/** Execute an authenticated POST request with a JSON body. */
|
|
91
92
|
async post(path, body, options) {
|
|
92
|
-
return this.request(
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
93
|
+
return this.request(
|
|
94
|
+
this.buildUrl(path),
|
|
95
|
+
{
|
|
96
|
+
method: "POST",
|
|
97
|
+
headers: this.writeHeaders(options),
|
|
98
|
+
body: body !== void 0 ? JSON.stringify(body) : void 0
|
|
99
|
+
},
|
|
100
|
+
options?.retry
|
|
101
|
+
);
|
|
97
102
|
}
|
|
98
103
|
/**
|
|
99
104
|
* Execute a POST that must never execute twice, guaranteeing an
|
|
@@ -120,21 +125,33 @@ var BaseClient = class {
|
|
|
120
125
|
}
|
|
121
126
|
/** Execute an authenticated PATCH request with a JSON body. */
|
|
122
127
|
async patch(path, body, options) {
|
|
123
|
-
return this.request(
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
+
return this.request(
|
|
129
|
+
this.buildUrl(path),
|
|
130
|
+
{
|
|
131
|
+
method: "PATCH",
|
|
132
|
+
headers: this.writeHeaders(options),
|
|
133
|
+
body: JSON.stringify(body)
|
|
134
|
+
},
|
|
135
|
+
options?.retry
|
|
136
|
+
);
|
|
128
137
|
}
|
|
129
138
|
/** Execute an authenticated DELETE request. */
|
|
130
139
|
async delete(path, options) {
|
|
131
|
-
return this.request(
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
140
|
+
return this.request(
|
|
141
|
+
this.buildUrl(path),
|
|
142
|
+
{
|
|
143
|
+
method: "DELETE",
|
|
144
|
+
headers: this.writeHeaders(options)
|
|
145
|
+
},
|
|
146
|
+
options?.retry
|
|
147
|
+
);
|
|
135
148
|
}
|
|
136
149
|
writeHeaders(options) {
|
|
137
|
-
const headers = {
|
|
150
|
+
const headers = {};
|
|
151
|
+
for (const [key, value] of Object.entries(options?.headers ?? {})) {
|
|
152
|
+
headers[key.toLowerCase()] = value;
|
|
153
|
+
}
|
|
154
|
+
headers["content-type"] = "application/json";
|
|
138
155
|
if (options?.idempotencyKey) {
|
|
139
156
|
headers["idempotency-key"] = options.idempotencyKey;
|
|
140
157
|
}
|
|
@@ -154,8 +171,8 @@ var BaseClient = class {
|
|
|
154
171
|
}
|
|
155
172
|
return url.toString();
|
|
156
173
|
}
|
|
157
|
-
async request(url, init) {
|
|
158
|
-
const maxAttempts = 3;
|
|
174
|
+
async request(url, init, retry = true) {
|
|
175
|
+
const maxAttempts = retry ? 3 : 1;
|
|
159
176
|
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
|
|
160
177
|
const headers = new Headers(init.headers);
|
|
161
178
|
headers.set("authorization", `Bearer ${this.config.token}`);
|
|
@@ -356,14 +373,75 @@ var BookingsManage = class {
|
|
|
356
373
|
);
|
|
357
374
|
}
|
|
358
375
|
};
|
|
376
|
+
var BookingsPersons = class {
|
|
377
|
+
constructor(client) {
|
|
378
|
+
this.client = client;
|
|
379
|
+
}
|
|
380
|
+
client;
|
|
381
|
+
/** Persons a contact books for. Active-only unless `include_inactive`. */
|
|
382
|
+
async list(contactId, options) {
|
|
383
|
+
const params = { contact_id: contactId };
|
|
384
|
+
if (options?.include_inactive !== void 0) {
|
|
385
|
+
params.include_inactive = String(options.include_inactive);
|
|
386
|
+
}
|
|
387
|
+
return this.client.get("/api/v1/bookings/persons", params);
|
|
388
|
+
}
|
|
389
|
+
/** Add a person under a contact. */
|
|
390
|
+
async create(input, options) {
|
|
391
|
+
return this.client.postOnce("/api/v1/bookings/persons", input, options);
|
|
392
|
+
}
|
|
393
|
+
};
|
|
394
|
+
var BookingsRelations = class {
|
|
395
|
+
constructor(client) {
|
|
396
|
+
this.client = client;
|
|
397
|
+
}
|
|
398
|
+
client;
|
|
399
|
+
/** Relations a contact holds, split into outgoing and incoming. */
|
|
400
|
+
async list(contactId) {
|
|
401
|
+
return this.client.get("/api/v1/bookings/relations", { contact_id: contactId });
|
|
402
|
+
}
|
|
403
|
+
/** Create a relation from one contact to another. */
|
|
404
|
+
async create(input, options) {
|
|
405
|
+
return this.client.postOnce("/api/v1/bookings/relations", input, options);
|
|
406
|
+
}
|
|
407
|
+
};
|
|
408
|
+
var BookingsEvents = class {
|
|
409
|
+
constructor(client) {
|
|
410
|
+
this.client = client;
|
|
411
|
+
}
|
|
412
|
+
client;
|
|
413
|
+
/** Arrangementer in a date range (`yyyy-mm-dd`, inclusive). */
|
|
414
|
+
async list(options) {
|
|
415
|
+
const params = { from: options.from, to: options.to };
|
|
416
|
+
if (options.status) params.status = options.status;
|
|
417
|
+
return this.client.get("/api/v1/bookings/events", params);
|
|
418
|
+
}
|
|
419
|
+
/** Get an arrangement by ID. */
|
|
420
|
+
async get(id) {
|
|
421
|
+
return this.client.get(`/api/v1/bookings/events/${encodeURIComponent(id)}`);
|
|
422
|
+
}
|
|
423
|
+
/** Create an arrangement from a template. */
|
|
424
|
+
async create(input, options) {
|
|
425
|
+
return this.client.postOnce("/api/v1/bookings/events", input, options);
|
|
426
|
+
}
|
|
427
|
+
};
|
|
359
428
|
var Bookings = class {
|
|
360
429
|
constructor(client) {
|
|
361
430
|
this.client = client;
|
|
362
431
|
this.manage = new BookingsManage(client);
|
|
432
|
+
this.persons = new BookingsPersons(client);
|
|
433
|
+
this.relations = new BookingsRelations(client);
|
|
434
|
+
this.events = new BookingsEvents(client);
|
|
363
435
|
}
|
|
364
436
|
client;
|
|
365
437
|
/** Customer-side actions addressed by manage token. */
|
|
366
438
|
manage;
|
|
439
|
+
/** Persons a contact books for — children, pets, employees. */
|
|
440
|
+
persons;
|
|
441
|
+
/** Directional relations between contacts. */
|
|
442
|
+
relations;
|
|
443
|
+
/** Arrangementer — scheduled group sessions bookings register against. */
|
|
444
|
+
events;
|
|
367
445
|
/** List the bookable service catalogue. Active-only unless asked otherwise. */
|
|
368
446
|
async listServices(options) {
|
|
369
447
|
const params = {};
|
|
@@ -929,6 +1007,111 @@ var Helpdesk = class {
|
|
|
929
1007
|
}
|
|
930
1008
|
};
|
|
931
1009
|
|
|
1010
|
+
// src/resources/portal.ts
|
|
1011
|
+
function withSession(session) {
|
|
1012
|
+
return { headers: { "x-portal-session": session } };
|
|
1013
|
+
}
|
|
1014
|
+
var ONCE = { retry: false };
|
|
1015
|
+
var PortalLogin = class {
|
|
1016
|
+
constructor(client) {
|
|
1017
|
+
this.client = client;
|
|
1018
|
+
}
|
|
1019
|
+
client;
|
|
1020
|
+
/**
|
|
1021
|
+
* E-mail a one-time code to the address.
|
|
1022
|
+
*
|
|
1023
|
+
* Always 202 `{ status: "sent" }` — enumeration-safe: `"sent"` does not
|
|
1024
|
+
* confirm that the address belongs to a contact. Rate-limited per address
|
|
1025
|
+
* and per caller (`429 RATE_LIMITED`).
|
|
1026
|
+
*/
|
|
1027
|
+
async start(input) {
|
|
1028
|
+
return this.client.post("/api/v1/portal/login/start", input);
|
|
1029
|
+
}
|
|
1030
|
+
/**
|
|
1031
|
+
* Exchange the e-mailed code for a session.
|
|
1032
|
+
*
|
|
1033
|
+
* `session_token` is a bearer credential for ONE contact — keep it in an
|
|
1034
|
+
* HttpOnly cookie on the site's server. A wrong, burned or expired code all
|
|
1035
|
+
* answer `401 PORTAL_CODE_INVALID`; the three are not distinguished, so the
|
|
1036
|
+
* response is not an oracle for which codes exist.
|
|
1037
|
+
*/
|
|
1038
|
+
async verify(input) {
|
|
1039
|
+
return this.client.post("/api/v1/portal/login/verify", input, ONCE);
|
|
1040
|
+
}
|
|
1041
|
+
};
|
|
1042
|
+
var Portal = class {
|
|
1043
|
+
constructor(client) {
|
|
1044
|
+
this.client = client;
|
|
1045
|
+
this.login = new PortalLogin(client);
|
|
1046
|
+
}
|
|
1047
|
+
client;
|
|
1048
|
+
/** E-mail one-time-code login: `start` sends the code, `verify` exchanges it. */
|
|
1049
|
+
login;
|
|
1050
|
+
/**
|
|
1051
|
+
* Revoke the session. Resolves to `undefined` (the route answers 204).
|
|
1052
|
+
*
|
|
1053
|
+
* Not keyed: revoking twice reaches the same state — the second call answers
|
|
1054
|
+
* `401 PORTAL_SESSION_INVALID`, which is the outcome you wanted anyway.
|
|
1055
|
+
*/
|
|
1056
|
+
async logout(session) {
|
|
1057
|
+
await this.client.post("/api/v1/portal/logout", void 0, {
|
|
1058
|
+
...withSession(session),
|
|
1059
|
+
...ONCE
|
|
1060
|
+
});
|
|
1061
|
+
}
|
|
1062
|
+
/** The signed-in contact's own profile. */
|
|
1063
|
+
async me(session) {
|
|
1064
|
+
return this.client.get("/api/v1/portal/me", void 0, withSession(session));
|
|
1065
|
+
}
|
|
1066
|
+
/**
|
|
1067
|
+
* Update the signed-in contact's profile. Only the supplied fields change;
|
|
1068
|
+
* `phone: null` clears the number and `family` replaces the whole list.
|
|
1069
|
+
* `marketing_consent` records a `marketing_email` consent decision with
|
|
1070
|
+
* source `portal`. Returns the profile as it is after the change.
|
|
1071
|
+
*/
|
|
1072
|
+
/**
|
|
1073
|
+
* A profile patch is not idempotency-keyed on the server and a `marketing_consent`
|
|
1074
|
+
* change records a dated consent event, so a retry after a committed-but-lost
|
|
1075
|
+
* response would repeat that event: sent exactly once, like the other writes.
|
|
1076
|
+
*/
|
|
1077
|
+
async updateMe(session, patch) {
|
|
1078
|
+
return this.client.patch("/api/v1/portal/me", patch, { ...withSession(session), ...ONCE });
|
|
1079
|
+
}
|
|
1080
|
+
/**
|
|
1081
|
+
* The contact's bookings split into `upcoming` and `past`. An upcoming
|
|
1082
|
+
* booking that is still inside the workspace's policy windows carries
|
|
1083
|
+
* `manage_token` and `can_manage: true`; use the token to open the site's
|
|
1084
|
+
* manage page (`medal.bookings.manage.*`).
|
|
1085
|
+
*/
|
|
1086
|
+
async myBookings(session) {
|
|
1087
|
+
return this.client.get("/api/v1/portal/me/bookings", void 0, withSession(session));
|
|
1088
|
+
}
|
|
1089
|
+
/**
|
|
1090
|
+
* Everything the workspace holds about the contact — profile, family,
|
|
1091
|
+
* consents and bookings — as one JSON document (GDPR Art. 15). Synchronous,
|
|
1092
|
+
* unlike `medal.gdpr.requestExport()`, which exports the whole workspace.
|
|
1093
|
+
*
|
|
1094
|
+
* Not keyed: a read-only snapshot, so a retried call costs nothing and
|
|
1095
|
+
* duplicates nothing.
|
|
1096
|
+
*/
|
|
1097
|
+
async exportMyData(session) {
|
|
1098
|
+
return this.client.post("/api/v1/portal/me/export", void 0, withSession(session));
|
|
1099
|
+
}
|
|
1100
|
+
/**
|
|
1101
|
+
* Erase the contact (GDPR Art. 17). Resolves to `undefined` (the route
|
|
1102
|
+
* answers 204); the session is revoked as part of the deletion.
|
|
1103
|
+
*
|
|
1104
|
+
* Not keyed: deletion is terminal, so a retry meets a revoked session and
|
|
1105
|
+
* answers `401 PORTAL_SESSION_INVALID` rather than deleting anything else.
|
|
1106
|
+
*/
|
|
1107
|
+
async deleteMe(session) {
|
|
1108
|
+
await this.client.post("/api/v1/portal/me/delete", void 0, {
|
|
1109
|
+
...withSession(session),
|
|
1110
|
+
...ONCE
|
|
1111
|
+
});
|
|
1112
|
+
}
|
|
1113
|
+
};
|
|
1114
|
+
|
|
932
1115
|
// src/resources/posts.ts
|
|
933
1116
|
var Posts = class {
|
|
934
1117
|
constructor(client) {
|
|
@@ -1234,6 +1417,7 @@ var Medal = class {
|
|
|
1234
1417
|
deals;
|
|
1235
1418
|
gdpr;
|
|
1236
1419
|
helpdesk;
|
|
1420
|
+
portal;
|
|
1237
1421
|
posts;
|
|
1238
1422
|
scan;
|
|
1239
1423
|
webhooks;
|
|
@@ -1263,6 +1447,7 @@ var Medal = class {
|
|
|
1263
1447
|
this.deals = new Deals(client);
|
|
1264
1448
|
this.gdpr = new Gdpr(client);
|
|
1265
1449
|
this.helpdesk = new Helpdesk(client, confirmer);
|
|
1450
|
+
this.portal = new Portal(client);
|
|
1266
1451
|
this.posts = new Posts(client);
|
|
1267
1452
|
this.scan = new Scan(client);
|
|
1268
1453
|
this.webhooks = new Webhooks(client, confirmer);
|
|
@@ -1290,6 +1475,7 @@ var src_default = Medal;
|
|
|
1290
1475
|
Helpdesk,
|
|
1291
1476
|
Medal,
|
|
1292
1477
|
MedalApiError,
|
|
1478
|
+
Portal,
|
|
1293
1479
|
Posts,
|
|
1294
1480
|
Scan,
|
|
1295
1481
|
WebhookVerificationError,
|