@ai-matrx/meet 0.7.7 → 0.7.9
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/CHANGELOG.md +51 -0
- package/dist/index.cjs +145 -56
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +80 -50
- package/dist/index.d.ts +80 -50
- package/dist/index.js +145 -56
- package/dist/index.js.map +1 -1
- package/dist/react.cjs +842 -706
- package/dist/react.cjs.map +1 -1
- package/dist/react.d.cts +1 -1
- package/dist/react.d.ts +1 -1
- package/dist/react.js +818 -682
- package/dist/react.js.map +1 -1
- package/dist/styles.css +18 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,8 +1,59 @@
|
|
|
1
1
|
# Changelog — `@ai-matrx/meet`
|
|
2
2
|
|
|
3
|
+
## 0.7.9
|
|
4
|
+
### (next patch)
|
|
5
|
+
|
|
6
|
+
- **Fix — a database refusal reads as a sentence for a person** (verifier, 2026-09-27, the
|
|
7
|
+
class behind raw toast text): `normalizeMeetError`'s `message` was
|
|
8
|
+
"meet.x: denied by the database (42501: …)" with a remedy about RLS and service-role
|
|
9
|
+
clients, and hosts render `message` + `remedy` in toasts. Now our RPC's own sentence
|
|
10
|
+
(`RAISE EXCEPTION 'Only the host …'`) is the message; Postgres wording, SQLSTATEs and class
|
|
11
|
+
names become a plain sentence ("You don't have access to do that in this meeting.", "This
|
|
12
|
+
meeting changed a moment ago…", "The server could not be reached."); the raw error stays on
|
|
13
|
+
`cause`. `SERVER_FAILED_SENTENCE` / `isRawServerText` now live in `core/errors.ts`
|
|
14
|
+
(still re-exported from the root).
|
|
15
|
+
- **Consumer action:** none.
|
|
16
|
+
|
|
17
|
+
## 0.7.8
|
|
18
|
+
### (next patch)
|
|
19
|
+
|
|
20
|
+
- **Fix — a refusal never reaches a person as a Python class name** (verifier, 2026-09-27): a
|
|
21
|
+
host's toast read "Internal server error: UnsupportedClientFeatureError". `readServerRefusal`
|
|
22
|
+
now skips raw server text (`Internal server error: …`, a bare `…Error` class, a snake_case
|
|
23
|
+
code) and falls through to the body's `user_message`, or to `SERVER_FAILED_SENTENCE`. The
|
|
24
|
+
three hand-copied refusal builders (`in-room.ts`, `management.ts`, `after.ts`) collapse into
|
|
25
|
+
ONE exported `refusalFromResponse(response, operation, fallbackRemedy)`, whose `message` is
|
|
26
|
+
the server's sentence — no `meet.x:` operation prefix — and whose `remedy` is the server's.
|
|
27
|
+
- **Fix — a refused Remove / Make host keeps its pane open WITH the sentence** : the confirm
|
|
28
|
+
pane now shows the server's refusal inline (`role="alert"`) with its buttons live; before it
|
|
29
|
+
stayed up silently.
|
|
30
|
+
- **Fix — every per-person menu offers "Message privately"**: a tile's menu (Room stage and a
|
|
31
|
+
host layout's strip, e.g. the Board) now opens the private chat through the store
|
|
32
|
+
(`snapshot.privateChatRequest`, answered by the one `ControlBar`); before only the People
|
|
33
|
+
panel could, so two menus for one person disagreed.
|
|
34
|
+
- **Fix — attendance is per PERSON, never per join**: an export listed the same attendee twice
|
|
35
|
+
under "attended". `attendanceReport` merges a person's joins (account = one person across
|
|
36
|
+
devices and rejoins; an accountless guest's rejoin, which gets a fresh `guest:<random>`
|
|
37
|
+
identity, is matched by the typed name) into one row — first arrival, last departure, total
|
|
38
|
+
time with overlaps counted once, and a new `joins` count. `notesDocument`'s "Attended" line
|
|
39
|
+
and the record view's "Who attended" use the new exported `uniqueAttendees` / `attendeeKey`.
|
|
40
|
+
- **Consumer action:** none (a consumer counting `bundle.attendees` itself should count
|
|
41
|
+
`uniqueAttendees(...)` instead).
|
|
42
|
+
|
|
3
43
|
## 0.7.7
|
|
4
44
|
### Meet wave 3: after the meeting
|
|
5
45
|
|
|
46
|
+
- **Fix — the room header on a phone** (2026-09-27, 390px): the header wraps into rows and
|
|
47
|
+
each host control stays one line; before, the title read "Hollo…" and "End meeting for
|
|
48
|
+
everyone" stacked into four underlined words.
|
|
49
|
+
- **Fix — a removed participant reads the server's sentence, not "invalid token: revoked"**
|
|
50
|
+
(2026-09-27, live room): a server-side disconnect now invalidates the cached room token, so
|
|
51
|
+
the next Join mints again and shows "A host removed you from this meeting."
|
|
52
|
+
- **Fix — a host's per-person menu opens beside its button** (2026-09-27, live room): the
|
|
53
|
+
popover was hidden but IN FLOW on its first frame, so the anchor it measured was button +
|
|
54
|
+
menu and it opened a full menu-height lower — Make host, Report and Remove from meeting were
|
|
55
|
+
below the fold. It is now fixed-positioned from the first frame, re-placed when the layout
|
|
56
|
+
moves, and pinned + scrollable when neither side of the button holds it.
|
|
6
57
|
- **Fix — the waiting room for people from another organization and for denied guests**
|
|
7
58
|
(2026-09-27, verified in a real room): a signed-in link-follower now knocks as `user:<id>`, the
|
|
8
59
|
identity the server's lobby row carries — before, the host saw two entries and admitting one
|
package/dist/index.cjs
CHANGED
|
@@ -84,6 +84,7 @@ __export(src_exports, {
|
|
|
84
84
|
attendanceCsv: () => attendanceCsv,
|
|
85
85
|
attendanceReport: () => attendanceReport,
|
|
86
86
|
attendanceTotals: () => attendanceTotals,
|
|
87
|
+
attendeeKey: () => attendeeKey,
|
|
87
88
|
callInviteAction: () => callInviteAction,
|
|
88
89
|
callInviteText: () => callInviteText,
|
|
89
90
|
callStateLabel: () => callStateLabel,
|
|
@@ -187,6 +188,7 @@ __export(src_exports, {
|
|
|
187
188
|
summarizeMeetingRecordRestrictions: () => summarizeMeetingRecordRestrictions,
|
|
188
189
|
transcriptDocument: () => transcriptDocument,
|
|
189
190
|
unavailableFrom: () => unavailableFrom,
|
|
191
|
+
uniqueAttendees: () => uniqueAttendees,
|
|
190
192
|
userTopic: () => userTopic,
|
|
191
193
|
wasRefused: () => wasRefused,
|
|
192
194
|
wrapUpStatus: () => wrapUpStatus
|
|
@@ -218,6 +220,20 @@ var MeetError = class extends Error {
|
|
|
218
220
|
return this.code === "permission-denied" || this.code === "device-not-found" || this.code === "device-in-use" || this.code === "insecure-context";
|
|
219
221
|
}
|
|
220
222
|
};
|
|
223
|
+
var SERVER_FAILED_SENTENCE = "The server hit an unexpected problem and nothing was changed.";
|
|
224
|
+
function isRawServerText(value) {
|
|
225
|
+
const text3 = value.trim();
|
|
226
|
+
return /^internal server error\b/i.test(text3) || /^[A-Z][A-Za-z0-9]*(Error|Exception)$/.test(text3) || /^[a-z][a-z0-9]*(_[a-z0-9]+)+$/.test(text3);
|
|
227
|
+
}
|
|
228
|
+
function humanDatabaseSentence(message) {
|
|
229
|
+
const text3 = message.trim();
|
|
230
|
+
if (text3.length === 0 || isRawServerText(text3)) return null;
|
|
231
|
+
if (/permission denied for|violates|relation "|does not exist|syntax error|column "|jwt|pgrst|duplicate key|null value in/i.test(
|
|
232
|
+
text3
|
|
233
|
+
))
|
|
234
|
+
return null;
|
|
235
|
+
return text3;
|
|
236
|
+
}
|
|
221
237
|
var FORBIDDEN_CODES = /* @__PURE__ */ new Set(["42501", "PGRST301", "PGRST302"]);
|
|
222
238
|
var NOT_FOUND_CODES = /* @__PURE__ */ new Set(["PGRST116", "PGRST205"]);
|
|
223
239
|
var CONFLICT_CODES = /* @__PURE__ */ new Set(["23505", "40001", "55000"]);
|
|
@@ -245,8 +261,8 @@ function normalizeMeetError(error, operation) {
|
|
|
245
261
|
if (code !== void 0 && FORBIDDEN_CODES.has(code)) {
|
|
246
262
|
return new MeetError(
|
|
247
263
|
"forbidden",
|
|
248
|
-
|
|
249
|
-
"
|
|
264
|
+
humanDatabaseSentence(message) ?? "You don't have access to do that in this meeting.",
|
|
265
|
+
"Ask the meeting's host to do it, or to give you access.",
|
|
250
266
|
error
|
|
251
267
|
);
|
|
252
268
|
}
|
|
@@ -261,15 +277,16 @@ function normalizeMeetError(error, operation) {
|
|
|
261
277
|
if (code !== void 0 && CONFLICT_CODES.has(code)) {
|
|
262
278
|
return new MeetError(
|
|
263
279
|
"conflict",
|
|
264
|
-
|
|
265
|
-
"
|
|
280
|
+
humanDatabaseSentence(message) ?? "This meeting changed a moment ago, so nothing was saved.",
|
|
281
|
+
"Reload to see the latest, then try again.",
|
|
266
282
|
error
|
|
267
283
|
);
|
|
268
284
|
}
|
|
285
|
+
const hint = error?.hint;
|
|
269
286
|
return new MeetError(
|
|
270
287
|
"transport",
|
|
271
|
-
|
|
272
|
-
|
|
288
|
+
/failed to fetch|networkerror|load failed|network request failed/i.test(message) ? "The server could not be reached." : humanDatabaseSentence(message) ?? SERVER_FAILED_SENTENCE,
|
|
289
|
+
typeof hint === "string" && humanDatabaseSentence(hint) !== null ? hint.trim() : "Nothing was changed \u2014 retry in a moment; if it keeps happening, reload the page.",
|
|
273
290
|
error
|
|
274
291
|
);
|
|
275
292
|
}
|
|
@@ -677,6 +694,24 @@ function readText(data) {
|
|
|
677
694
|
}
|
|
678
695
|
return "";
|
|
679
696
|
}
|
|
697
|
+
async function refusalFromResponse(response, operation, fallbackRemedy) {
|
|
698
|
+
let body = null;
|
|
699
|
+
try {
|
|
700
|
+
body = await response.json();
|
|
701
|
+
} catch {
|
|
702
|
+
body = null;
|
|
703
|
+
}
|
|
704
|
+
const said = readServerRefusal(body);
|
|
705
|
+
const code = response.status === 403 || response.status === 401 ? "forbidden" : response.status === 404 ? "not-found" : response.status === 409 ? "conflict" : "transport";
|
|
706
|
+
const error = new MeetError(
|
|
707
|
+
code,
|
|
708
|
+
said?.reason ?? SERVER_FAILED_SENTENCE,
|
|
709
|
+
said !== null && said.remedy.length > 0 ? said.remedy : fallbackRemedy
|
|
710
|
+
);
|
|
711
|
+
error.operation = operation;
|
|
712
|
+
error.status = response.status;
|
|
713
|
+
return error;
|
|
714
|
+
}
|
|
680
715
|
function readServerRefusal(body) {
|
|
681
716
|
if (typeof body === "string") {
|
|
682
717
|
return body.trim().length === 0 ? null : { reason: body.trim(), remedy: "" };
|
|
@@ -695,7 +730,8 @@ function readServerRefusal(body) {
|
|
|
695
730
|
return messages.length === 0 ? null : { reason: messages.join("; "), remedy: "" };
|
|
696
731
|
}
|
|
697
732
|
if (typeof detail === "object" && detail !== null) return readServerRefusal(detail);
|
|
698
|
-
const
|
|
733
|
+
const humanOrNull = (value) => typeof value === "string" && value.trim().length > 0 && !isRawServerText(value) ? value.trim() : null;
|
|
734
|
+
const reason = humanOrNull(row["reason"]) ?? humanOrNull(row["message"]) ?? humanOrNull(row["user_message"]) ?? (typeof detail === "string" ? humanOrNull(detail) : null) ?? (typeof row["message"] === "string" || typeof row["error"] === "string" || typeof detail === "string" ? SERVER_FAILED_SENTENCE : null);
|
|
699
735
|
if (reason === null) return null;
|
|
700
736
|
const remedy = typeof row["remedy"] === "string" ? row["remedy"] : "";
|
|
701
737
|
if (remedy.length > 0) return { reason, remedy };
|
|
@@ -3378,6 +3414,7 @@ var EMPTY = {
|
|
|
3378
3414
|
spotlight: null,
|
|
3379
3415
|
moderationNotice: null,
|
|
3380
3416
|
actionNotice: null,
|
|
3417
|
+
privateChatRequest: null,
|
|
3381
3418
|
effects: DEFAULT_EFFECTS,
|
|
3382
3419
|
transcript: [],
|
|
3383
3420
|
notes: [],
|
|
@@ -4068,9 +4105,55 @@ function ms(iso) {
|
|
|
4068
4105
|
const at = new Date(iso).getTime();
|
|
4069
4106
|
return Number.isNaN(at) ? null : at;
|
|
4070
4107
|
}
|
|
4108
|
+
function attendeeKey(person, names = {}) {
|
|
4109
|
+
if (person.userId !== null) return `user:${person.userId}`;
|
|
4110
|
+
if (person.isAgent) return `agent:${person.identity}`;
|
|
4111
|
+
const name = displayNameFor(names, person.identity, person.displayName).trim().toLowerCase();
|
|
4112
|
+
return name.length > 0 ? `guest-name:${name}` : `identity:${person.identity}`;
|
|
4113
|
+
}
|
|
4114
|
+
function uniqueAttendees(attendees, names = {}) {
|
|
4115
|
+
const byKey = /* @__PURE__ */ new Map();
|
|
4116
|
+
for (const person of attendees) {
|
|
4117
|
+
const key = attendeeKey(person, names);
|
|
4118
|
+
const kept = byKey.get(key);
|
|
4119
|
+
if (kept === void 0) {
|
|
4120
|
+
byKey.set(key, person);
|
|
4121
|
+
continue;
|
|
4122
|
+
}
|
|
4123
|
+
const keptJoin = ms(kept.joinedAt);
|
|
4124
|
+
const join = ms(person.joinedAt);
|
|
4125
|
+
if (join !== null && (keptJoin === null || join < keptJoin)) byKey.set(key, person);
|
|
4126
|
+
}
|
|
4127
|
+
return [...byKey.values()];
|
|
4128
|
+
}
|
|
4129
|
+
var KIND_RANK = {
|
|
4130
|
+
host: 0,
|
|
4131
|
+
cohost: 1,
|
|
4132
|
+
member: 2,
|
|
4133
|
+
"signed-in guest": 3,
|
|
4134
|
+
guest: 4,
|
|
4135
|
+
assistant: 5
|
|
4136
|
+
};
|
|
4137
|
+
function coveredMs(intervals) {
|
|
4138
|
+
const sorted = [...intervals].sort((a, b) => a[0] - b[0]);
|
|
4139
|
+
let total = 0;
|
|
4140
|
+
let from = -Infinity;
|
|
4141
|
+
let to = -Infinity;
|
|
4142
|
+
for (const [start, end] of sorted) {
|
|
4143
|
+
if (start > to) {
|
|
4144
|
+
if (to > from) total += to - from;
|
|
4145
|
+
from = start;
|
|
4146
|
+
to = end;
|
|
4147
|
+
} else if (end > to) {
|
|
4148
|
+
to = end;
|
|
4149
|
+
}
|
|
4150
|
+
}
|
|
4151
|
+
if (to > from) total += to - from;
|
|
4152
|
+
return total;
|
|
4153
|
+
}
|
|
4071
4154
|
function attendanceReport(meeting, attendees, names = {}) {
|
|
4072
4155
|
const end = ms(meeting.endedAt);
|
|
4073
|
-
const
|
|
4156
|
+
const perJoin = attendees.map((person) => {
|
|
4074
4157
|
const joined = ms(person.joinedAt);
|
|
4075
4158
|
const left = ms(person.leftAt);
|
|
4076
4159
|
const until = left ?? end;
|
|
@@ -4085,17 +4168,45 @@ function attendanceReport(meeting, attendees, names = {}) {
|
|
|
4085
4168
|
leftAt: person.leftAt,
|
|
4086
4169
|
durationMs: duration,
|
|
4087
4170
|
durationToEnd: duration !== null && left === null,
|
|
4088
|
-
admission: person.admissionState
|
|
4171
|
+
admission: person.admissionState,
|
|
4172
|
+
joins: 1
|
|
4089
4173
|
};
|
|
4090
4174
|
});
|
|
4091
|
-
const
|
|
4092
|
-
|
|
4093
|
-
|
|
4094
|
-
|
|
4095
|
-
|
|
4096
|
-
|
|
4097
|
-
|
|
4098
|
-
};
|
|
4175
|
+
const groups = /* @__PURE__ */ new Map();
|
|
4176
|
+
attendees.forEach((person, index) => {
|
|
4177
|
+
const key = attendeeKey(person, names);
|
|
4178
|
+
const group = groups.get(key) ?? { rows: [], people: [] };
|
|
4179
|
+
group.rows.push(perJoin[index]);
|
|
4180
|
+
group.people.push(person);
|
|
4181
|
+
groups.set(key, group);
|
|
4182
|
+
});
|
|
4183
|
+
const rows = [...groups.values()].map(({ rows: joins }) => {
|
|
4184
|
+
if (joins.length === 1) return joins[0];
|
|
4185
|
+
const came = joins.filter((row) => row.joinedAt !== null);
|
|
4186
|
+
const first = [...came].sort((a, b) => (ms(a.joinedAt) ?? 0) - (ms(b.joinedAt) ?? 0))[0] ?? joins[0];
|
|
4187
|
+
const kind = joins.reduce(
|
|
4188
|
+
(best, row) => KIND_RANK[row.kind] < KIND_RANK[best] ? row.kind : best,
|
|
4189
|
+
first.kind
|
|
4190
|
+
);
|
|
4191
|
+
const open = came.some((row) => row.leftAt === null);
|
|
4192
|
+
const lastLeave = came.reduce((latest, row) => {
|
|
4193
|
+
const left = ms(row.leftAt);
|
|
4194
|
+
return left !== null && (latest === null || left > latest) ? left : latest;
|
|
4195
|
+
}, null);
|
|
4196
|
+
const intervals = came.flatMap((row) => {
|
|
4197
|
+
const joined = ms(row.joinedAt);
|
|
4198
|
+
return joined !== null && row.durationMs !== null ? [[joined, joined + row.durationMs]] : [];
|
|
4199
|
+
});
|
|
4200
|
+
return {
|
|
4201
|
+
...first,
|
|
4202
|
+
kind,
|
|
4203
|
+
leftAt: open ? null : lastLeave === null ? null : new Date(lastLeave).toISOString(),
|
|
4204
|
+
durationMs: intervals.length === 0 ? null : coveredMs(intervals),
|
|
4205
|
+
durationToEnd: came.some((row) => row.durationToEnd),
|
|
4206
|
+
joins: came.length === 0 ? joins.length : came.length
|
|
4207
|
+
};
|
|
4208
|
+
});
|
|
4209
|
+
const rank = KIND_RANK;
|
|
4099
4210
|
return rows.sort((a, b) => {
|
|
4100
4211
|
if (rank[a.kind] !== rank[b.kind]) return rank[a.kind] - rank[b.kind];
|
|
4101
4212
|
return (ms(a.joinedAt) ?? Number.MAX_SAFE_INTEGER) - (ms(b.joinedAt) ?? Number.MAX_SAFE_INTEGER);
|
|
@@ -4253,7 +4364,10 @@ function bullet(note) {
|
|
|
4253
4364
|
function notesDocument(bundle, options = {}) {
|
|
4254
4365
|
const out = [`# ${bundle.meeting.title}`, ""];
|
|
4255
4366
|
if (options.when) out.push(`_${options.when}_`, "");
|
|
4256
|
-
const people =
|
|
4367
|
+
const people = uniqueAttendees(
|
|
4368
|
+
bundle.attendees.filter((person) => !person.isAgent && person.joinedAt !== null),
|
|
4369
|
+
bundle.names
|
|
4370
|
+
).map((person) => displayNameFor(bundle.names, person.identity, person.displayName));
|
|
4257
4371
|
if (people.length > 0) out.push(`**Attended:** ${people.join(", ")}`, "");
|
|
4258
4372
|
out.push("## Summary", "", bundle.summary?.text.trim() || "No summary was written.", "");
|
|
4259
4373
|
out.push("## Decisions", "");
|
|
@@ -4317,19 +4431,8 @@ async function loadMeetingChat(api, meetingId, roomToken = null) {
|
|
|
4317
4431
|
refusal: null
|
|
4318
4432
|
};
|
|
4319
4433
|
}
|
|
4320
|
-
|
|
4321
|
-
|
|
4322
|
-
try {
|
|
4323
|
-
body = await response.json();
|
|
4324
|
-
} catch {
|
|
4325
|
-
body = null;
|
|
4326
|
-
}
|
|
4327
|
-
const said = readServerRefusal(body);
|
|
4328
|
-
return new MeetError(
|
|
4329
|
-
response.status === 403 || response.status === 401 ? "forbidden" : response.status === 404 ? "not-found" : response.status === 409 ? "conflict" : "transport",
|
|
4330
|
-
`${operation}: ${said?.reason ?? `the server answered ${response.status}`}`,
|
|
4331
|
-
said?.remedy || "Nothing was sent. Try again."
|
|
4332
|
-
);
|
|
4434
|
+
function refusalOf(response, operation) {
|
|
4435
|
+
return refusalFromResponse(response, operation, "Nothing was sent. Try again.");
|
|
4333
4436
|
}
|
|
4334
4437
|
function asRecipient(row) {
|
|
4335
4438
|
const sources = Array.isArray(row["sources"]) ? row["sources"] : [];
|
|
@@ -4390,18 +4493,11 @@ async function sendFollowUp(api, meetingId, input) {
|
|
|
4390
4493
|
}
|
|
4391
4494
|
|
|
4392
4495
|
// src/core/management.ts
|
|
4393
|
-
|
|
4394
|
-
|
|
4395
|
-
|
|
4396
|
-
|
|
4397
|
-
|
|
4398
|
-
body = null;
|
|
4399
|
-
}
|
|
4400
|
-
const said = readServerRefusal(body);
|
|
4401
|
-
return new MeetError(
|
|
4402
|
-
response.status === 403 || response.status === 401 ? "forbidden" : response.status === 404 ? "not-found" : response.status === 409 ? "conflict" : "transport",
|
|
4403
|
-
`${operation}: ${said?.reason ?? `the server answered ${response.status}`}`,
|
|
4404
|
-
said?.remedy || "The meeting itself is saved \u2014 only the telling failed. Try again; the call is idempotent."
|
|
4496
|
+
function refusal(response, operation) {
|
|
4497
|
+
return refusalFromResponse(
|
|
4498
|
+
response,
|
|
4499
|
+
operation,
|
|
4500
|
+
"The meeting itself is saved \u2014 only the telling failed. Try again; the call is idempotent."
|
|
4405
4501
|
);
|
|
4406
4502
|
}
|
|
4407
4503
|
function count(body, key) {
|
|
@@ -4727,6 +4823,10 @@ function createRoomEngine(options) {
|
|
|
4727
4823
|
}
|
|
4728
4824
|
},
|
|
4729
4825
|
disconnected(reason) {
|
|
4826
|
+
if (current !== null) {
|
|
4827
|
+
tokens.invalidate(current.roomName);
|
|
4828
|
+
current = null;
|
|
4829
|
+
}
|
|
4730
4830
|
store.patch({ phase: "left" });
|
|
4731
4831
|
options.onLeft?.(reason);
|
|
4732
4832
|
}
|
|
@@ -5029,19 +5129,8 @@ function createInRoomClient(options) {
|
|
|
5029
5129
|
const token = options.resolveRoomToken();
|
|
5030
5130
|
return token === null ? void 0 : { [ROOM_TOKEN_HEADER]: token };
|
|
5031
5131
|
}
|
|
5032
|
-
|
|
5033
|
-
|
|
5034
|
-
try {
|
|
5035
|
-
body = await response.json();
|
|
5036
|
-
} catch {
|
|
5037
|
-
body = null;
|
|
5038
|
-
}
|
|
5039
|
-
const said = readServerRefusal(body);
|
|
5040
|
-
return new MeetError(
|
|
5041
|
-
response.status === 403 || response.status === 401 ? "forbidden" : response.status === 404 ? "not-found" : response.status === 409 ? "conflict" : "transport",
|
|
5042
|
-
said?.reason ?? `${operation}: the server answered ${response.status}`,
|
|
5043
|
-
said?.remedy !== void 0 && said.remedy.length > 0 ? said.remedy : remedy
|
|
5044
|
-
);
|
|
5132
|
+
function refusal2(response, operation, remedy) {
|
|
5133
|
+
return refusalFromResponse(response, operation, remedy);
|
|
5045
5134
|
}
|
|
5046
5135
|
return {
|
|
5047
5136
|
async moderate(request) {
|