@blazeo.com/appointment-client 1.0.6 → 1.0.8
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/Appointment-Client/.gitattributes +2 -0
- package/blazeo.com-appointment-client-1.0.8.tgz +0 -0
- package/dist/calendar/buildUnifiedCalendarView.d.ts +8 -0
- package/dist/calendar/buildUnifiedCalendarView.js +29 -8
- package/dist/calendar/fetchCalendarDetails.d.ts +8 -40
- package/dist/calendar/fetchCalendarDetails.js +117 -47
- package/dist/calendar/fetchCalendarWithOpeningHours.d.ts +1 -10
- package/dist/calendar/fetchCalendarWithOpeningHours.js +34 -15
- package/dist/calendar/getAllParticipantOpeningHours.d.ts +4 -1
- package/dist/calendar/getAllParticipantOpeningHours.js +6 -1
- package/dist/calendar/getOpeningHours.d.ts +4 -1
- package/dist/calendar/getOpeningHours.js +2 -2
- package/dist/calendar/getParticipantOpeningHours.js +9 -4
- package/dist/calendar/getParticipants.d.ts +4 -1
- package/dist/calendar/getParticipants.js +6 -1
- package/dist/calendar/mapToDesiredResponse.d.ts +70 -0
- package/dist/calendar/mapToDesiredResponse.js +99 -0
- package/dist/config/applyBlazeoDefaults.js +3 -2
- package/dist/config/blazeoClientDefaults.js +2 -2
- package/dist/config/ensureBlazeoHttpReady.d.ts +17 -0
- package/dist/config/ensureBlazeoHttpReady.js +31 -0
- package/dist/config/initializeAppointmentClient.d.ts +4 -0
- package/dist/config/initializeAppointmentClient.js +9 -3
- package/dist/config/syncBlazeoConnection.d.ts +6 -0
- package/dist/config/syncBlazeoConnection.js +18 -0
- package/dist/index.d.ts +4 -1
- package/dist/index.js +3 -1
- package/package.json +1 -1
- package/sample/.env.example +5 -0
- package/sample/package-lock.json +70 -1
- package/sample/package.json +1 -0
- package/sample/src/AllParticipantOpeningHoursTab.jsx +13 -4
- package/sample/src/App2.jsx +22 -2
- package/sample/src/AvailabilityTab.jsx +8 -3
- package/sample/src/BlazeoConnectionSettings.jsx +16 -15
- package/sample/src/CreateCalendarTab.jsx +23 -6
- package/sample/src/EventTab.jsx +31 -8
- package/sample/src/FetchCalendarTab.jsx +94 -70
- package/sample/src/OpeningHoursTab.jsx +13 -4
- package/sample/src/ParticipantInfoTab.jsx +8 -3
- package/sample/src/ParticipantOpeningHoursTab.jsx +17 -7
- package/sample/src/ParticipantTab.jsx +13 -4
- package/sample/src/blazeoBootstrap.js +30 -0
- package/sample/src/blazeoDemoError.js +14 -0
- package/sample/src/blazeoPushConnection.js +23 -0
- package/sample/src/main.jsx +3 -3
- package/sample/vite.config.js +19 -5
- package/src/calendar/buildUnifiedCalendarView.ts +35 -7
- package/src/calendar/fetchCalendarDetails.ts +318 -226
- package/src/calendar/fetchCalendarWithOpeningHours.ts +130 -99
- package/src/calendar/getAllParticipantOpeningHours.ts +9 -1
- package/src/calendar/getOpeningHours.ts +2 -2
- package/src/calendar/getParticipantOpeningHours.ts +14 -5
- package/src/calendar/getParticipants.ts +9 -1
- package/src/calendar/mapToDesiredResponse.ts +104 -0
- package/src/config/applyBlazeoDefaults.ts +3 -2
- package/src/config/blazeoClientDefaults.ts +2 -2
- package/src/config/ensureBlazeoHttpReady.ts +41 -0
- package/src/config/initializeAppointmentClient.ts +9 -3
- package/src/config/syncBlazeoConnection.ts +19 -0
- package/src/index.ts +7 -1
- package/blazeo.com-appointment-client-1.0.6.tgz +0 -0
|
Binary file
|
|
@@ -6,18 +6,26 @@ export interface UnifiedCalendarMember {
|
|
|
6
6
|
status: number | null;
|
|
7
7
|
/** Full row from Participants/GetInfo (plain object). */
|
|
8
8
|
participantInfo?: Record<string, unknown> | null;
|
|
9
|
+
__typename?: string;
|
|
9
10
|
}
|
|
10
11
|
export interface UnifiedParticipantWithHours extends UnifiedCalendarMember {
|
|
11
12
|
openingHours: UnifiedOpeningHourRow[];
|
|
12
13
|
}
|
|
13
14
|
export interface UnifiedOpeningHourRow {
|
|
15
|
+
id?: number | string;
|
|
16
|
+
createdOn?: string;
|
|
17
|
+
modifiedOn?: string;
|
|
14
18
|
member: number | string;
|
|
19
|
+
openingHourId?: string;
|
|
20
|
+
calendarId?: string;
|
|
21
|
+
participantId?: string;
|
|
15
22
|
days: string[];
|
|
16
23
|
startHour: number;
|
|
17
24
|
startMinute: number;
|
|
18
25
|
endHour: number;
|
|
19
26
|
endMinute: number;
|
|
20
27
|
off: boolean;
|
|
28
|
+
__typename?: string;
|
|
21
29
|
}
|
|
22
30
|
export type UnifiedCalendarView = Record<string, unknown> & {
|
|
23
31
|
members: UnifiedCalendarMember[];
|
|
@@ -40,9 +40,7 @@ function coerceMemberId(v) {
|
|
|
40
40
|
* Canonical member id used in both `members[].id` and `openingHours[].member`.
|
|
41
41
|
*/
|
|
42
42
|
function resolveParticipantMemberId(calPart) {
|
|
43
|
-
|
|
44
|
-
if (n != null && typeof n === "number" && !Number.isNaN(n))
|
|
45
|
-
return n;
|
|
43
|
+
// Prefer the participantId GUID when available — it is the stable cross-endpoint identifier.
|
|
46
44
|
const sid = pick(calPart, "participantId", "ParticipantId", "participant_id");
|
|
47
45
|
if (sid != null && String(sid).trim() !== "") {
|
|
48
46
|
const t = String(sid).trim();
|
|
@@ -50,6 +48,14 @@ function resolveParticipantMemberId(calPart) {
|
|
|
50
48
|
return Number(t);
|
|
51
49
|
return t;
|
|
52
50
|
}
|
|
51
|
+
// Fall back to id — accepts both numeric and string (e.g. a GUID stored as id).
|
|
52
|
+
const n = pick(calPart, "id", "Id");
|
|
53
|
+
if (n != null) {
|
|
54
|
+
if (typeof n === "number" && !Number.isNaN(n))
|
|
55
|
+
return n;
|
|
56
|
+
if (typeof n === "string" && n.trim() !== "")
|
|
57
|
+
return n.trim();
|
|
58
|
+
}
|
|
53
59
|
return "";
|
|
54
60
|
}
|
|
55
61
|
function dayOrderIndex(d) {
|
|
@@ -206,6 +212,7 @@ export function buildUnifiedCalendarView(calendarSnapshot, openingHoursRows, par
|
|
|
206
212
|
email: email ?? null,
|
|
207
213
|
status: deriveMemberStatus({}, inf),
|
|
208
214
|
participantInfo: participantInfoPlain,
|
|
215
|
+
__typename: "Member",
|
|
209
216
|
});
|
|
210
217
|
}
|
|
211
218
|
}
|
|
@@ -227,13 +234,20 @@ export function buildUnifiedCalendarView(calendarSnapshot, openingHoursRows, par
|
|
|
227
234
|
const endMinute = Number(pick(row, "endMinute", "EndMinute", "end_minute") ?? 0) || 0;
|
|
228
235
|
const off = Boolean(pick(row, "off", "Off"));
|
|
229
236
|
openingHours.push({
|
|
237
|
+
id: pick(row, "id", "Id") ?? 0,
|
|
238
|
+
createdOn: pick(row, "createdOn", "CreatedOn", "created_on") ?? "0001-01-01T00:00:00.000Z",
|
|
239
|
+
modifiedOn: pick(row, "modifiedOn", "ModifiedOn", "modified_on") ?? "0001-01-01T00:00:00.000Z",
|
|
230
240
|
member: memberId,
|
|
241
|
+
openingHourId: pick(row, "openingHourId", "OpeningHourId", "opening_hour_id") ?? "",
|
|
242
|
+
calendarId: pick(row, "calendarId", "CalendarId", "calendar_id") ?? "",
|
|
243
|
+
participantId: pick(row, "participantId", "ParticipantId", "participant_id") ?? "",
|
|
231
244
|
days,
|
|
232
245
|
startHour,
|
|
233
246
|
startMinute,
|
|
234
247
|
endHour,
|
|
235
248
|
endMinute,
|
|
236
249
|
off,
|
|
250
|
+
__typename: "OpeningHour",
|
|
237
251
|
});
|
|
238
252
|
}
|
|
239
253
|
mergeOpeningHoursBySlot(openingHours);
|
|
@@ -242,6 +256,7 @@ export function buildUnifiedCalendarView(calendarSnapshot, openingHoursRows, par
|
|
|
242
256
|
members,
|
|
243
257
|
openingHours,
|
|
244
258
|
participants: buildNestedParticipants(members, openingHours),
|
|
259
|
+
__typename: "Calendar",
|
|
245
260
|
};
|
|
246
261
|
return view;
|
|
247
262
|
}
|
|
@@ -249,17 +264,23 @@ export function buildUnifiedCalendarView(calendarSnapshot, openingHoursRows, par
|
|
|
249
264
|
* Groups opening hours into their respective participant objects.
|
|
250
265
|
*/
|
|
251
266
|
function buildNestedParticipants(members, openingHours) {
|
|
252
|
-
|
|
253
|
-
|
|
267
|
+
const nested = [];
|
|
268
|
+
members.forEach((m) => {
|
|
269
|
+
const hoursForThisMember = openingHours.filter((oh) => {
|
|
254
270
|
const mid = String(oh.member).trim().toLowerCase();
|
|
255
271
|
const pid = String(m.id).trim().toLowerCase();
|
|
256
272
|
return mid === pid;
|
|
257
273
|
});
|
|
258
274
|
// Remove the 'member' field from the nested opening hours as it's redundant.
|
|
259
|
-
const nestedHours =
|
|
260
|
-
|
|
275
|
+
const nestedHours = hoursForThisMember.map(({ member, ...rest }) => ({
|
|
276
|
+
...rest,
|
|
277
|
+
__typename: "OpeningHour"
|
|
278
|
+
}));
|
|
279
|
+
nested.push({
|
|
261
280
|
...m,
|
|
262
281
|
openingHours: nestedHours,
|
|
263
|
-
|
|
282
|
+
__typename: "Member",
|
|
283
|
+
});
|
|
264
284
|
});
|
|
285
|
+
return nested;
|
|
265
286
|
}
|
|
@@ -25,49 +25,17 @@ export declare function fetchCalendarDetails(calendarId: string, options?: {
|
|
|
25
25
|
includeUnifiedCalendarView?: boolean;
|
|
26
26
|
/** Prefer all-participant opening hours for **`calendarView`** when the API returns rows (default `true`). */
|
|
27
27
|
preferAllParticipantOpeningHours?: boolean;
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
openingHours: any[];
|
|
33
|
-
participants: any[];
|
|
34
|
-
participantsInfo: any;
|
|
35
|
-
allParticipantOpeningHours: any[] | null;
|
|
36
|
-
embeddedFromGet: any[];
|
|
37
|
-
fromCalendarGet: boolean;
|
|
38
|
-
fromParticipantApi: boolean;
|
|
39
|
-
participantOpeningHoursResponse: any;
|
|
40
|
-
rawGet: any;
|
|
41
|
-
meta: {
|
|
42
|
-
ok: false;
|
|
43
|
-
reason: string;
|
|
44
|
-
};
|
|
45
|
-
} | {
|
|
46
|
-
calendar: any;
|
|
47
|
-
cal: any;
|
|
48
|
-
calendarView: UnifiedCalendarView | null;
|
|
49
|
-
openingHours: any[];
|
|
50
|
-
participants: any[];
|
|
51
|
-
participantsInfo: unknown;
|
|
52
|
-
allParticipantOpeningHours: any[] | null;
|
|
53
|
-
embeddedFromGet: any[];
|
|
54
|
-
fromCalendarGet: boolean;
|
|
55
|
-
fromParticipantApi: boolean;
|
|
56
|
-
participantOpeningHoursResponse: any;
|
|
57
|
-
meta: {
|
|
58
|
-
calendarViewMemberCount?: number | undefined;
|
|
59
|
-
calendarViewOpeningHourCount?: number | undefined;
|
|
60
|
-
ok: true;
|
|
61
|
-
/** `calendarView.openingHours` came from OpeningHours/All/Get */
|
|
62
|
-
calendarViewUsedAllParticipantOpeningHours: boolean;
|
|
63
|
-
reason?: undefined;
|
|
64
|
-
};
|
|
65
|
-
rawGet?: undefined;
|
|
66
|
-
}>;
|
|
28
|
+
/** Optional; applied with `resolveBlazeoConnection` so `CalendarModel.get` sees `baseUrl` without prior global `configure`. */
|
|
29
|
+
baseUrl?: string;
|
|
30
|
+
consumer?: string;
|
|
31
|
+
}): Promise<any>;
|
|
67
32
|
/**
|
|
68
33
|
* Single return value only: unified calendar **`calendarView`** —
|
|
69
34
|
* snapshot fields plus **`members`** (with **`participantInfo`**) plus **`openingHours`**
|
|
70
35
|
* (prefers all-participant opening hours when available). Same shape as `fetchCalendarDetails().calendarView`.
|
|
71
36
|
* Returns **`null`** if the calendar cannot be loaded (`CalendarModel.get`).
|
|
72
37
|
*/
|
|
73
|
-
export declare function fetchCalendarBundle(calendarId: string
|
|
38
|
+
export declare function fetchCalendarBundle(calendarId: string, connection?: {
|
|
39
|
+
baseUrl?: string;
|
|
40
|
+
consumer?: string;
|
|
41
|
+
}): Promise<UnifiedCalendarView | null>;
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { CalendarModel } from "@blazeo.com/calendar-client";
|
|
2
|
-
import {
|
|
2
|
+
import { ensureBlazeoHttpReady } from "../config/ensureBlazeoHttpReady.js";
|
|
3
3
|
import { unwrapCalendarGetData, pickOpeningHoursArrayFromCalendarPayload, normalizeParticipantOpeningHoursResponse, } from "./fetchCalendarWithOpeningHours.js";
|
|
4
4
|
import { buildUnifiedCalendarView } from "./buildUnifiedCalendarView.js";
|
|
5
|
+
import { mapToDesiredCalendarResponse } from "./mapToDesiredResponse.js";
|
|
5
6
|
/**
|
|
6
7
|
* Normalizes the REST envelope from `calendar.getParticipantOpeningHours()`
|
|
7
8
|
* (`GET /Calendar/Participant/OpeningHours/Get`) into a plain row array.
|
|
@@ -83,21 +84,37 @@ function unwrapModelList(raw) {
|
|
|
83
84
|
* Server still performs multiple HTTP calls; on the client, **`calendarView`** is returned as **one object**.
|
|
84
85
|
*/
|
|
85
86
|
export async function fetchCalendarDetails(calendarId, options = {}) {
|
|
86
|
-
const { includeParticipantsInfo = false, includeUnifiedCalendarView = true, preferAllParticipantOpeningHours = true, } = options;
|
|
87
|
+
const { includeParticipantsInfo = false, includeUnifiedCalendarView = true, preferAllParticipantOpeningHours = true, baseUrl: optBaseUrl, consumer: optConsumer, } = options;
|
|
88
|
+
const conn = ensureBlazeoHttpReady({ baseUrl: optBaseUrl, consumer: optConsumer });
|
|
89
|
+
if (!conn.ok) {
|
|
90
|
+
return {
|
|
91
|
+
calendar: null,
|
|
92
|
+
cal: null,
|
|
93
|
+
calendarView: null,
|
|
94
|
+
openingHours: [],
|
|
95
|
+
participants: [],
|
|
96
|
+
participantsInfo: null,
|
|
97
|
+
allParticipantOpeningHours: null,
|
|
98
|
+
embeddedFromGet: [],
|
|
99
|
+
fromCalendarGet: false,
|
|
100
|
+
fromParticipantApi: false,
|
|
101
|
+
participantOpeningHoursResponse: null,
|
|
102
|
+
rawGet: null,
|
|
103
|
+
meta: { ok: false, reason: "missing_base_url", detail: conn.error },
|
|
104
|
+
};
|
|
105
|
+
}
|
|
87
106
|
const fetchParticipantsInfo = includeParticipantsInfo || includeUnifiedCalendarView;
|
|
88
107
|
const fetchAllHours = includeUnifiedCalendarView && preferAllParticipantOpeningHours;
|
|
89
|
-
// Calendar: `GET /Calendar/Get` is used
|
|
90
|
-
const
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
]);
|
|
94
|
-
if (cal == null) {
|
|
108
|
+
// Calendar: `GET /Calendar/Get` is used to get the raw data first.
|
|
109
|
+
const rawRes = await CalendarModel.getRaw(calendarId);
|
|
110
|
+
const payload = unwrapCalendarGetData(rawRes);
|
|
111
|
+
if (!payload) {
|
|
95
112
|
return {
|
|
96
113
|
calendar: null,
|
|
97
114
|
cal: null,
|
|
98
115
|
calendarView: null,
|
|
99
116
|
openingHours: [],
|
|
100
|
-
participants:
|
|
117
|
+
participants: null,
|
|
101
118
|
participantsInfo: null,
|
|
102
119
|
allParticipantOpeningHours: null,
|
|
103
120
|
embeddedFromGet: [],
|
|
@@ -108,7 +125,9 @@ export async function fetchCalendarDetails(calendarId, options = {}) {
|
|
|
108
125
|
meta: { ok: false, reason: "calendar_not_found" },
|
|
109
126
|
};
|
|
110
127
|
}
|
|
111
|
-
|
|
128
|
+
// Build the model instance manually to ensure the environment is correctly set.
|
|
129
|
+
// The static CalendarModel.get in calendar-client has a bug where it wraps env in { env: ... }.
|
|
130
|
+
const cal = CalendarModel.create({ ...payload, calendarId }, { baseUrl: conn.baseUrl, consumer: conn.consumer });
|
|
112
131
|
const embedded = pickOpeningHoursArrayFromCalendarPayload(payload) ?? [];
|
|
113
132
|
let participantOpeningHoursResponse = null;
|
|
114
133
|
let resolved = embedded.length > 0 ? embedded : null;
|
|
@@ -124,17 +143,70 @@ export async function fetchCalendarDetails(calendarId, options = {}) {
|
|
|
124
143
|
const participantsViaGetPromise = includeUnifiedCalendarView && typeof getCalPart === "function"
|
|
125
144
|
? getCalPart.call(CalendarModel, calendarId)
|
|
126
145
|
: Promise.resolve(null);
|
|
127
|
-
const [
|
|
128
|
-
|
|
146
|
+
const [participantsRaw, participantsViaGet, participantsInfoRaw, allHoursRaw] = await Promise.all([
|
|
147
|
+
cal.getParticipants(),
|
|
129
148
|
participantsViaGetPromise,
|
|
130
|
-
fetchParticipantsInfo ?
|
|
131
|
-
fetchAllHours ?
|
|
149
|
+
fetchParticipantsInfo ? cal.getParticipantsInfo() : Promise.resolve(null),
|
|
150
|
+
fetchAllHours ? cal.getAllParticipantOpeningHours() : Promise.resolve(null),
|
|
132
151
|
]);
|
|
133
|
-
const
|
|
134
|
-
const
|
|
135
|
-
|
|
136
|
-
const
|
|
137
|
-
|
|
152
|
+
const participantList = mergeParticipantSnapshots(unwrapModelList(participantsRaw), unwrapModelList(participantsViaGet));
|
|
153
|
+
const infoList = unwrapModelList(participantsInfoRaw);
|
|
154
|
+
// Merge participantList and infoList to ensure we have all members
|
|
155
|
+
const mergedParticipantsMap = new Map();
|
|
156
|
+
// Prefer the participantId GUID; fall back to numeric id.
|
|
157
|
+
const getAnyId = (obj) => obj.participantId ?? obj.ParticipantId ?? obj.participant_id ?? obj.id ?? obj.Id;
|
|
158
|
+
// 1. Add from standard list
|
|
159
|
+
participantList.forEach((p) => {
|
|
160
|
+
const id = getAnyId(p);
|
|
161
|
+
if (id) {
|
|
162
|
+
mergedParticipantsMap.set(String(id).toLowerCase(), {
|
|
163
|
+
id: id,
|
|
164
|
+
name: p.name ?? p.Name ?? p.alias ?? p.Alias ?? "Member",
|
|
165
|
+
email: p.email ?? p.Email,
|
|
166
|
+
status: p.status ?? p.Status ?? 0,
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
});
|
|
170
|
+
// 2. Add from info list (fallback/enrich)
|
|
171
|
+
infoList.forEach((i) => {
|
|
172
|
+
const id = getAnyId(i);
|
|
173
|
+
if (!id)
|
|
174
|
+
return;
|
|
175
|
+
const key = String(id).toLowerCase();
|
|
176
|
+
const existing = mergedParticipantsMap.get(key);
|
|
177
|
+
if (!existing) {
|
|
178
|
+
mergedParticipantsMap.set(key, {
|
|
179
|
+
id: id,
|
|
180
|
+
name: i.alias || i.Alias || i.name || i.Name || "Member",
|
|
181
|
+
email: i.email || i.Email,
|
|
182
|
+
status: i.status ?? i.Status ?? (i.isApproved ? 1 : 0),
|
|
183
|
+
});
|
|
184
|
+
}
|
|
185
|
+
else {
|
|
186
|
+
// Enrich existing with email/name if missing
|
|
187
|
+
if (!existing.email)
|
|
188
|
+
existing.email = i.email || i.Email;
|
|
189
|
+
if (!existing.name || existing.name === "Member") {
|
|
190
|
+
existing.name = i.alias || i.Alias || i.name || i.Name || existing.name;
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
});
|
|
194
|
+
// 3. Synthetic Fallback: If openingHours reference a member we don't have, add them.
|
|
195
|
+
openingHours.forEach((oh) => {
|
|
196
|
+
const mid = oh.member ?? oh.Member ?? oh.participantId ?? oh.ParticipantId;
|
|
197
|
+
if (mid) {
|
|
198
|
+
const key = String(mid).toLowerCase();
|
|
199
|
+
if (!mergedParticipantsMap.has(key)) {
|
|
200
|
+
mergedParticipantsMap.set(key, {
|
|
201
|
+
id: mid,
|
|
202
|
+
name: "Member",
|
|
203
|
+
email: null,
|
|
204
|
+
status: 0,
|
|
205
|
+
});
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
});
|
|
209
|
+
const finalParticipantList = Array.from(mergedParticipantsMap.values());
|
|
138
210
|
const allParticipantOpeningHours = fetchAllHours ? normalizeAllParticipantOpeningHoursResult(allHoursRaw) : null;
|
|
139
211
|
const openingHoursForUnifiedView = includeUnifiedCalendarView &&
|
|
140
212
|
preferAllParticipantOpeningHours &&
|
|
@@ -142,37 +214,34 @@ export async function fetchCalendarDetails(calendarId, options = {}) {
|
|
|
142
214
|
allParticipantOpeningHours.length > 0
|
|
143
215
|
? allParticipantOpeningHours
|
|
144
216
|
: openingHours;
|
|
145
|
-
const
|
|
146
|
-
? buildUnifiedCalendarView(
|
|
217
|
+
const calendarViewRaw = includeUnifiedCalendarView
|
|
218
|
+
? buildUnifiedCalendarView(payload, openingHoursForUnifiedView, finalParticipantList, infoList)
|
|
147
219
|
: null;
|
|
220
|
+
const calendarView = calendarViewRaw ? mapToDesiredCalendarResponse(calendarViewRaw, calendarViewRaw.openingHours, calendarViewRaw.members) : null;
|
|
148
221
|
const unifiedUsedAllEndpoint = includeUnifiedCalendarView &&
|
|
149
222
|
preferAllParticipantOpeningHours &&
|
|
150
223
|
allParticipantOpeningHours != null &&
|
|
151
224
|
allParticipantOpeningHours.length > 0;
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
? {
|
|
170
|
-
calendarViewMemberCount: calendarView.members.length,
|
|
171
|
-
calendarViewOpeningHourCount: calendarView.openingHours.length,
|
|
172
|
-
}
|
|
173
|
-
: {}),
|
|
225
|
+
if (!calendarView)
|
|
226
|
+
return null;
|
|
227
|
+
// Attach metadata as non-enumerable properties so they don't show up in JSON.stringify
|
|
228
|
+
// but are still accessible for debugging if needed.
|
|
229
|
+
Object.defineProperties(calendarView, {
|
|
230
|
+
_cal: { value: cal, enumerable: false },
|
|
231
|
+
_participants: { value: participantList, enumerable: false },
|
|
232
|
+
_openingHours: { value: openingHours, enumerable: false },
|
|
233
|
+
_rawGet: { value: rawRes, enumerable: false },
|
|
234
|
+
_meta: {
|
|
235
|
+
value: {
|
|
236
|
+
ok: true,
|
|
237
|
+
calendarViewUsedAllParticipantOpeningHours: unifiedUsedAllEndpoint,
|
|
238
|
+
calendarViewMemberCount: calendarView.members.length,
|
|
239
|
+
calendarViewOpeningHourCount: calendarView.openingHours.length,
|
|
240
|
+
},
|
|
241
|
+
enumerable: false
|
|
174
242
|
},
|
|
175
|
-
};
|
|
243
|
+
});
|
|
244
|
+
return calendarView;
|
|
176
245
|
}
|
|
177
246
|
/**
|
|
178
247
|
* Single return value only: unified calendar **`calendarView`** —
|
|
@@ -180,13 +249,14 @@ export async function fetchCalendarDetails(calendarId, options = {}) {
|
|
|
180
249
|
* (prefers all-participant opening hours when available). Same shape as `fetchCalendarDetails().calendarView`.
|
|
181
250
|
* Returns **`null`** if the calendar cannot be loaded (`CalendarModel.get`).
|
|
182
251
|
*/
|
|
183
|
-
export async function fetchCalendarBundle(calendarId) {
|
|
252
|
+
export async function fetchCalendarBundle(calendarId, connection) {
|
|
184
253
|
const d = await fetchCalendarDetails(calendarId, {
|
|
185
254
|
includeUnifiedCalendarView: true,
|
|
186
255
|
includeParticipantsInfo: true,
|
|
187
256
|
preferAllParticipantOpeningHours: true,
|
|
257
|
+
...connection,
|
|
188
258
|
});
|
|
189
|
-
if (!d
|
|
259
|
+
if (!d)
|
|
190
260
|
return null;
|
|
191
|
-
return d
|
|
261
|
+
return d;
|
|
192
262
|
}
|
|
@@ -22,13 +22,4 @@ export declare function normalizeParticipantOpeningHoursResponse(res: any): {
|
|
|
22
22
|
* 1. Prefer rows embedded on **GET /Calendar/Get** (`CalendarModel.getRaw` payload — `@blazeo.com/calendar-client` MST omits them).
|
|
23
23
|
* 2. If missing/empty, calls **`calendar.getParticipantOpeningHours()`** (`GET /Calendar/Participant/OpeningHours/Get`).
|
|
24
24
|
*/
|
|
25
|
-
export declare function fetchCalendarWithOpeningHours(calendarId: string, options?: any): Promise<
|
|
26
|
-
rawGet?: any;
|
|
27
|
-
calendar: any;
|
|
28
|
-
cal: any;
|
|
29
|
-
openingHours: any[];
|
|
30
|
-
embeddedFromGet: any[];
|
|
31
|
-
fromCalendarGet: boolean;
|
|
32
|
-
fromParticipantApi: boolean;
|
|
33
|
-
participantOpeningHoursResponse: any;
|
|
34
|
-
}>;
|
|
25
|
+
export declare function fetchCalendarWithOpeningHours(calendarId: string, options?: any): Promise<any>;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { CalendarModel } from "@blazeo.com/calendar-client";
|
|
2
|
-
import {
|
|
2
|
+
import { resolveBlazeoConnection } from "./createCalendar.js";
|
|
3
|
+
import { mapToDesiredCalendarResponse } from "./mapToDesiredResponse.js";
|
|
3
4
|
/**
|
|
4
5
|
* Unwrap nested REST shapes: `res.data`, `res.Data`, or `res.data.data`.
|
|
5
6
|
*/
|
|
@@ -65,10 +66,23 @@ export function normalizeParticipantOpeningHoursResponse(res) {
|
|
|
65
66
|
* 2. If missing/empty, calls **`calendar.getParticipantOpeningHours()`** (`GET /Calendar/Participant/OpeningHours/Get`).
|
|
66
67
|
*/
|
|
67
68
|
export async function fetchCalendarWithOpeningHours(calendarId, options = {}) {
|
|
68
|
-
const { includeRawGet = false } = options;
|
|
69
|
+
const { includeRawGet = false, baseUrl, consumer } = options;
|
|
70
|
+
const { baseUrl: resolvedBase, consumer: resolvedConsumer } = resolveBlazeoConnection({ baseUrl, consumer });
|
|
69
71
|
const rawRes = await CalendarModel.getRaw(calendarId);
|
|
70
|
-
const cal = await CalendarModel.get(calendarId);
|
|
71
72
|
const payload = unwrapCalendarGetData(rawRes);
|
|
73
|
+
let cal = null;
|
|
74
|
+
if (payload) {
|
|
75
|
+
// Manually create the model instance to fix a bug in calendar-client static get.
|
|
76
|
+
cal = CalendarModel.create({ ...payload, calendarId }, { baseUrl: resolvedBase, consumer: resolvedConsumer });
|
|
77
|
+
}
|
|
78
|
+
if (cal == null) {
|
|
79
|
+
return {
|
|
80
|
+
calendar: null,
|
|
81
|
+
openingHours: [],
|
|
82
|
+
raw: rawRes,
|
|
83
|
+
meta: { ok: false, reason: "calendar_not_found" },
|
|
84
|
+
};
|
|
85
|
+
}
|
|
72
86
|
const embedded = pickOpeningHoursArrayFromCalendarPayload(payload) ?? [];
|
|
73
87
|
let resolved = embedded.length > 0 ? embedded : null;
|
|
74
88
|
let participantRes = null;
|
|
@@ -80,16 +94,21 @@ export async function fetchCalendarWithOpeningHours(calendarId, options = {}) {
|
|
|
80
94
|
resolved = list;
|
|
81
95
|
}
|
|
82
96
|
const openingHours = Array.isArray(resolved) ? resolved : [];
|
|
83
|
-
const
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
97
|
+
const mappedOpeningHours = openingHours.map(oh => ({
|
|
98
|
+
...oh,
|
|
99
|
+
}));
|
|
100
|
+
const rawMembers = payload?.members ?? payload?.Members ?? payload?.participants ?? payload?.Participants;
|
|
101
|
+
const mappedMembers = Array.isArray(rawMembers)
|
|
102
|
+
? rawMembers.map((m) => ({ ...m }))
|
|
103
|
+
: [];
|
|
104
|
+
const calendar = mapToDesiredCalendarResponse(payload, openingHours, mappedMembers);
|
|
105
|
+
if (!calendar)
|
|
106
|
+
return null;
|
|
107
|
+
Object.defineProperties(calendar, {
|
|
108
|
+
_cal: { value: cal, enumerable: false },
|
|
109
|
+
_openingHours: { value: openingHours, enumerable: false },
|
|
110
|
+
_embeddedFromGet: { value: embedded, enumerable: false },
|
|
111
|
+
_rawGet: { value: rawRes, enumerable: false },
|
|
112
|
+
});
|
|
113
|
+
return calendar;
|
|
95
114
|
}
|
|
@@ -2,7 +2,10 @@
|
|
|
2
2
|
* Fetch all participant opening hours for a calendar.
|
|
3
3
|
* Uses `GET /Calendar/Participant/OpeningHours/All/Get`.
|
|
4
4
|
*/
|
|
5
|
-
export declare function getAllParticipantOpeningHours(calendarId: string
|
|
5
|
+
export declare function getAllParticipantOpeningHours(calendarId: string, options?: {
|
|
6
|
+
baseUrl?: string;
|
|
7
|
+
consumer?: string;
|
|
8
|
+
}): Promise<{
|
|
6
9
|
openingHours: any[];
|
|
7
10
|
raw: any[];
|
|
8
11
|
meta: {
|
|
@@ -1,10 +1,15 @@
|
|
|
1
1
|
import { CalendarModel } from "@blazeo.com/calendar-client";
|
|
2
|
+
import { ensureBlazeoHttpReady } from "../config/ensureBlazeoHttpReady.js";
|
|
2
3
|
import { normalizeParticipantOpeningHoursResponse } from "./fetchCalendarWithOpeningHours.js";
|
|
3
4
|
/**
|
|
4
5
|
* Fetch all participant opening hours for a calendar.
|
|
5
6
|
* Uses `GET /Calendar/Participant/OpeningHours/All/Get`.
|
|
6
7
|
*/
|
|
7
|
-
export async function getAllParticipantOpeningHours(calendarId) {
|
|
8
|
+
export async function getAllParticipantOpeningHours(calendarId, options = {}) {
|
|
9
|
+
const ready = ensureBlazeoHttpReady(options);
|
|
10
|
+
if (!ready.ok) {
|
|
11
|
+
throw new Error(ready.error);
|
|
12
|
+
}
|
|
8
13
|
const raw = await CalendarModel.getAllParticipantOpeningHours(calendarId);
|
|
9
14
|
// calendar-client static helper returns either `unknown[] | null` or an envelope depending on version/entrypoint.
|
|
10
15
|
if (Array.isArray(raw)) {
|
|
@@ -2,4 +2,7 @@
|
|
|
2
2
|
* Fetches opening hours for a calendar.
|
|
3
3
|
* Automatically handles embedded calendar-level hours and participant-level fallbacks.
|
|
4
4
|
*/
|
|
5
|
-
export declare function getOpeningHours(calendarId: string
|
|
5
|
+
export declare function getOpeningHours(calendarId: string, options?: {
|
|
6
|
+
baseUrl?: string;
|
|
7
|
+
consumer?: string;
|
|
8
|
+
}): Promise<any>;
|
|
@@ -3,7 +3,7 @@ import { fetchCalendarWithOpeningHours } from "./fetchCalendarWithOpeningHours.j
|
|
|
3
3
|
* Fetches opening hours for a calendar.
|
|
4
4
|
* Automatically handles embedded calendar-level hours and participant-level fallbacks.
|
|
5
5
|
*/
|
|
6
|
-
export async function getOpeningHours(calendarId) {
|
|
7
|
-
const result = await fetchCalendarWithOpeningHours(calendarId);
|
|
6
|
+
export async function getOpeningHours(calendarId, options = {}) {
|
|
7
|
+
const result = await fetchCalendarWithOpeningHours(calendarId, options);
|
|
8
8
|
return result.openingHours;
|
|
9
9
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { CalendarModel } from "@blazeo.com/calendar-client";
|
|
2
|
-
import {
|
|
2
|
+
import { resolveBlazeoConnection } from "./createCalendar.js";
|
|
3
|
+
import { unwrapCalendarGetData, normalizeParticipantOpeningHoursResponse } from "./fetchCalendarWithOpeningHours.js";
|
|
3
4
|
/**
|
|
4
5
|
* Direct wrapper around `calendar.getParticipantOpeningHours()` for a calendar id.
|
|
5
6
|
*
|
|
@@ -8,15 +9,19 @@ import { normalizeParticipantOpeningHoursResponse } from "./fetchCalendarWithOpe
|
|
|
8
9
|
*/
|
|
9
10
|
export async function getParticipantOpeningHours(calendarId, options = {}) {
|
|
10
11
|
try {
|
|
11
|
-
const
|
|
12
|
-
|
|
12
|
+
const { baseUrl, consumer, ...passThrough } = options;
|
|
13
|
+
const { baseUrl: resolvedBase, consumer: resolvedConsumer } = resolveBlazeoConnection({ baseUrl, consumer });
|
|
14
|
+
const rawRes = await CalendarModel.getRaw(calendarId);
|
|
15
|
+
const payload = unwrapCalendarGetData(rawRes);
|
|
16
|
+
if (!payload) {
|
|
13
17
|
return {
|
|
14
18
|
openingHours: [],
|
|
15
19
|
raw: null,
|
|
16
20
|
meta: { ok: false, reason: "calendar_not_found" },
|
|
17
21
|
};
|
|
18
22
|
}
|
|
19
|
-
const
|
|
23
|
+
const cal = CalendarModel.create({ ...payload, calendarId }, { baseUrl: resolvedBase, consumer: resolvedConsumer });
|
|
24
|
+
const raw = await cal.getParticipantOpeningHours({ calendarId, ...(passThrough ?? {}) });
|
|
20
25
|
const { list } = normalizeParticipantOpeningHoursResponse(raw);
|
|
21
26
|
const openingHours = Array.isArray(list) ? list : [];
|
|
22
27
|
return {
|
|
@@ -1,8 +1,13 @@
|
|
|
1
1
|
import { CalendarModel } from "@blazeo.com/calendar-client";
|
|
2
|
+
import { ensureBlazeoHttpReady } from "../config/ensureBlazeoHttpReady.js";
|
|
2
3
|
/**
|
|
3
4
|
* Fetches participants for a calendar.
|
|
4
5
|
*/
|
|
5
|
-
export async function getParticipants(calendarId) {
|
|
6
|
+
export async function getParticipants(calendarId, options = {}) {
|
|
7
|
+
const ready = ensureBlazeoHttpReady(options);
|
|
8
|
+
if (!ready.ok) {
|
|
9
|
+
throw new Error(ready.error);
|
|
10
|
+
}
|
|
6
11
|
const participants = await CalendarModel.getParticipants(calendarId);
|
|
7
12
|
return Array.isArray(participants) ? participants : [];
|
|
8
13
|
}
|