@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
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Maps low-level Blazeo / calendar-client errors to actionable copy for this sample.
|
|
3
|
+
*/
|
|
4
|
+
export function mapBlazeoDemoError(message) {
|
|
5
|
+
const m = String(message ?? "");
|
|
6
|
+
if (
|
|
7
|
+
/Model env requires baseUrl|requires baseUrl\. Call configure|baseUrl is missing|Blazeo base URL is not set/i.test(
|
|
8
|
+
m
|
|
9
|
+
)
|
|
10
|
+
) {
|
|
11
|
+
return "Blazeo Base URL is not set for API calls. Enter **Base URL** (and optional Consumer) in the **Blazeo connection** card at the top of this page, or set `blazeoClientConfig` / `VITE_BLAZEO_BASE_URL`.";
|
|
12
|
+
}
|
|
13
|
+
return m;
|
|
14
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { ensureBlazeoHttpReady, initializeAppointmentClient } from "appointment-client";
|
|
2
|
+
import { configure } from "@blazeo.com/calendar-client";
|
|
3
|
+
|
|
4
|
+
function normalizeBase(u) {
|
|
5
|
+
const t = (u ?? "").trim();
|
|
6
|
+
if (!t) return "";
|
|
7
|
+
return t.replace(/\/+$/, "");
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Applies Base URL from the connection card. With Vite `resolve.alias` pointing
|
|
12
|
+
* `@blazeo.com/calendar-client` at one file, `configure` here matches `CalendarModel`'s store.
|
|
13
|
+
* `initializeAppointmentClient` + `ensureBlazeoHttpReady` keep `appointment-client` helpers aligned.
|
|
14
|
+
*/
|
|
15
|
+
export function pushBlazeoConnection(effective) {
|
|
16
|
+
const baseUrl = normalizeBase(effective?.baseUrl ?? "");
|
|
17
|
+
if (!baseUrl) return;
|
|
18
|
+
const consumer = (effective?.consumer ?? "").trim() || undefined;
|
|
19
|
+
const cfg = { baseUrl, ...(consumer ? { consumer } : {}) };
|
|
20
|
+
initializeAppointmentClient(cfg);
|
|
21
|
+
configure(cfg);
|
|
22
|
+
ensureBlazeoHttpReady(cfg);
|
|
23
|
+
}
|
package/sample/src/main.jsx
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import { applyBlazeoClientConfig } from "appointment-client";
|
|
2
1
|
import { StrictMode } from "react";
|
|
3
2
|
import { createRoot } from "react-dom/client";
|
|
4
3
|
import { App } from "./App2.jsx";
|
|
4
|
+
import { bootstrapBlazeoClient } from "./blazeoBootstrap.js";
|
|
5
5
|
import "./style.css";
|
|
6
6
|
|
|
7
|
-
/**
|
|
8
|
-
|
|
7
|
+
/** Blazeo: `blazeoClientDefaults.ts` + optional `VITE_BLAZEO_*` (.env) → `configure()` for calendar-client. */
|
|
8
|
+
bootstrapBlazeoClient();
|
|
9
9
|
|
|
10
10
|
const rootEl = document.getElementById("app");
|
|
11
11
|
if (!rootEl) {
|
package/sample/vite.config.js
CHANGED
|
@@ -1,10 +1,23 @@
|
|
|
1
1
|
import react from "@vitejs/plugin-react";
|
|
2
2
|
import { defineConfig, loadEnv } from "vite";
|
|
3
3
|
import path from "path";
|
|
4
|
+
import fs from "fs";
|
|
4
5
|
import { fileURLToPath } from "url";
|
|
5
6
|
|
|
6
7
|
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
7
8
|
|
|
9
|
+
/** Single physical entry for `@blazeo.com/calendar-client` (hoisted or nested under `file:..` parent). */
|
|
10
|
+
function calendarClientEntry() {
|
|
11
|
+
const candidates = [
|
|
12
|
+
path.resolve(__dirname, "node_modules/@blazeo.com/calendar-client/dist/index.mjs"),
|
|
13
|
+
path.resolve(__dirname, "../node_modules/@blazeo.com/calendar-client/dist/index.mjs"),
|
|
14
|
+
];
|
|
15
|
+
for (const p of candidates) {
|
|
16
|
+
if (fs.existsSync(p)) return p;
|
|
17
|
+
}
|
|
18
|
+
return candidates[0];
|
|
19
|
+
}
|
|
20
|
+
|
|
8
21
|
export default defineConfig(({ mode }) => {
|
|
9
22
|
const env = loadEnv(mode, path.resolve(__dirname, "."), "");
|
|
10
23
|
const proxyTarget = (env.VITE_DEV_PROXY_TARGET ?? "").trim().replace(/\/+$/, "");
|
|
@@ -26,13 +39,14 @@ export default defineConfig(({ mode }) => {
|
|
|
26
39
|
plugins: [react()],
|
|
27
40
|
/** Ensure one instance so `configure()` and models share the same store. */
|
|
28
41
|
resolve: {
|
|
29
|
-
|
|
42
|
+
// `file:..` appointment-client is symlinked; `true` can resolve the same dep twice → two `getConfig()` stores.
|
|
43
|
+
preserveSymlinks: false,
|
|
30
44
|
dedupe: ["@blazeo.com/calendar-client", "mobx", "mobx-state-tree"],
|
|
31
45
|
alias: {
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
),
|
|
46
|
+
// Ensure Vite/Rollup can always resolve the local workspace package.
|
|
47
|
+
// (Avoids `Failed to resolve import "appointment-client"` during dev/build.)
|
|
48
|
+
"appointment-client": path.resolve(__dirname, "../dist/index.js"),
|
|
49
|
+
"@blazeo.com/calendar-client": calendarClientEntry(),
|
|
36
50
|
},
|
|
37
51
|
},
|
|
38
52
|
optimizeDeps: {
|
|
@@ -37,14 +37,19 @@ function coerceMemberId(v: unknown): number | string | null {
|
|
|
37
37
|
* Canonical member id used in both `members[].id` and `openingHours[].member`.
|
|
38
38
|
*/
|
|
39
39
|
function resolveParticipantMemberId(calPart: Record<string, any>): number | string {
|
|
40
|
-
|
|
41
|
-
if (n != null && typeof n === "number" && !Number.isNaN(n)) return n;
|
|
40
|
+
// Prefer the participantId GUID when available — it is the stable cross-endpoint identifier.
|
|
42
41
|
const sid = pick<string>(calPart, "participantId", "ParticipantId", "participant_id");
|
|
43
42
|
if (sid != null && String(sid).trim() !== "") {
|
|
44
43
|
const t = String(sid).trim();
|
|
45
44
|
if (/^\d+$/.test(t)) return Number(t);
|
|
46
45
|
return t;
|
|
47
46
|
}
|
|
47
|
+
// Fall back to id — accepts both numeric and string (e.g. a GUID stored as id).
|
|
48
|
+
const n = pick<number | string | null>(calPart, "id", "Id");
|
|
49
|
+
if (n != null) {
|
|
50
|
+
if (typeof n === "number" && !Number.isNaN(n)) return n;
|
|
51
|
+
if (typeof n === "string" && n.trim() !== "") return n.trim();
|
|
52
|
+
}
|
|
48
53
|
return "";
|
|
49
54
|
}
|
|
50
55
|
|
|
@@ -56,6 +61,7 @@ export interface UnifiedCalendarMember {
|
|
|
56
61
|
status: number | null;
|
|
57
62
|
/** Full row from Participants/GetInfo (plain object). */
|
|
58
63
|
participantInfo?: Record<string, unknown> | null;
|
|
64
|
+
__typename?: string;
|
|
59
65
|
}
|
|
60
66
|
|
|
61
67
|
export interface UnifiedParticipantWithHours extends UnifiedCalendarMember {
|
|
@@ -63,13 +69,20 @@ export interface UnifiedParticipantWithHours extends UnifiedCalendarMember {
|
|
|
63
69
|
}
|
|
64
70
|
|
|
65
71
|
export interface UnifiedOpeningHourRow {
|
|
72
|
+
id?: number | string;
|
|
73
|
+
createdOn?: string;
|
|
74
|
+
modifiedOn?: string;
|
|
66
75
|
member: number | string;
|
|
76
|
+
openingHourId?: string;
|
|
77
|
+
calendarId?: string;
|
|
78
|
+
participantId?: string;
|
|
67
79
|
days: string[];
|
|
68
80
|
startHour: number;
|
|
69
81
|
startMinute: number;
|
|
70
82
|
endHour: number;
|
|
71
83
|
endMinute: number;
|
|
72
84
|
off: boolean;
|
|
85
|
+
__typename?: string;
|
|
73
86
|
}
|
|
74
87
|
|
|
75
88
|
function dayOrderIndex(d: string): number {
|
|
@@ -253,6 +266,7 @@ export function buildUnifiedCalendarView(
|
|
|
253
266
|
email: email ?? null,
|
|
254
267
|
status: deriveMemberStatus({}, inf),
|
|
255
268
|
participantInfo: participantInfoPlain,
|
|
269
|
+
__typename: "Member",
|
|
256
270
|
});
|
|
257
271
|
}
|
|
258
272
|
}
|
|
@@ -277,13 +291,20 @@ export function buildUnifiedCalendarView(
|
|
|
277
291
|
const off = Boolean(pick(row, "off", "Off"));
|
|
278
292
|
|
|
279
293
|
openingHours.push({
|
|
294
|
+
id: pick(row, "id", "Id") ?? 0,
|
|
295
|
+
createdOn: pick(row, "createdOn", "CreatedOn", "created_on") ?? "0001-01-01T00:00:00.000Z",
|
|
296
|
+
modifiedOn: pick(row, "modifiedOn", "ModifiedOn", "modified_on") ?? "0001-01-01T00:00:00.000Z",
|
|
280
297
|
member: memberId,
|
|
298
|
+
openingHourId: pick(row, "openingHourId", "OpeningHourId", "opening_hour_id") ?? "",
|
|
299
|
+
calendarId: pick(row, "calendarId", "CalendarId", "calendar_id") ?? "",
|
|
300
|
+
participantId: pick(row, "participantId", "ParticipantId", "participant_id") ?? "",
|
|
281
301
|
days,
|
|
282
302
|
startHour,
|
|
283
303
|
startMinute,
|
|
284
304
|
endHour,
|
|
285
305
|
endMinute,
|
|
286
306
|
off,
|
|
307
|
+
__typename: "OpeningHour",
|
|
287
308
|
});
|
|
288
309
|
}
|
|
289
310
|
|
|
@@ -294,6 +315,7 @@ export function buildUnifiedCalendarView(
|
|
|
294
315
|
members,
|
|
295
316
|
openingHours,
|
|
296
317
|
participants: buildNestedParticipants(members, openingHours),
|
|
318
|
+
__typename: "Calendar",
|
|
297
319
|
} as UnifiedCalendarView;
|
|
298
320
|
|
|
299
321
|
return view;
|
|
@@ -306,17 +328,23 @@ function buildNestedParticipants(
|
|
|
306
328
|
members: UnifiedCalendarMember[],
|
|
307
329
|
openingHours: UnifiedOpeningHourRow[]
|
|
308
330
|
): UnifiedParticipantWithHours[] {
|
|
309
|
-
|
|
310
|
-
|
|
331
|
+
const nested: UnifiedParticipantWithHours[] = [];
|
|
332
|
+
members.forEach((m) => {
|
|
333
|
+
const hoursForThisMember = openingHours.filter((oh) => {
|
|
311
334
|
const mid = String(oh.member).trim().toLowerCase();
|
|
312
335
|
const pid = String(m.id).trim().toLowerCase();
|
|
313
336
|
return mid === pid;
|
|
314
337
|
});
|
|
315
338
|
// Remove the 'member' field from the nested opening hours as it's redundant.
|
|
316
|
-
const nestedHours =
|
|
317
|
-
|
|
339
|
+
const nestedHours = hoursForThisMember.map(({ member, ...rest }) => ({
|
|
340
|
+
...rest,
|
|
341
|
+
__typename: "OpeningHour"
|
|
342
|
+
}));
|
|
343
|
+
nested.push({
|
|
318
344
|
...m,
|
|
319
345
|
openingHours: nestedHours,
|
|
320
|
-
|
|
346
|
+
__typename: "Member",
|
|
347
|
+
} as UnifiedParticipantWithHours);
|
|
321
348
|
});
|
|
349
|
+
return nested;
|
|
322
350
|
}
|