@volter/twin-calcom 0.1.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.
Files changed (40) hide show
  1. package/LICENSE +202 -0
  2. package/README.md +90 -0
  3. package/client/calcom-mirror.css +29 -0
  4. package/client/calcom-mirror.tsx +125 -0
  5. package/dist/client/calcom-mirror.bundle.js +321 -0
  6. package/dist/client/calcom-mirror.css +29 -0
  7. package/dist/client/calcom-mirror.d.ts +13 -0
  8. package/dist/client/calcom-mirror.js +61 -0
  9. package/dist/client/calcom-mirror.tsx +125 -0
  10. package/dist/src/calcom-budget.d.ts +52 -0
  11. package/dist/src/calcom-budget.js +145 -0
  12. package/dist/src/calcom-capabilities.d.ts +3 -0
  13. package/dist/src/calcom-capabilities.js +521 -0
  14. package/dist/src/calcom-conformance.d.ts +15 -0
  15. package/dist/src/calcom-conformance.js +86 -0
  16. package/dist/src/calcom-connector.d.ts +90 -0
  17. package/dist/src/calcom-connector.js +229 -0
  18. package/dist/src/calcom-mirror-ui.d.ts +23 -0
  19. package/dist/src/calcom-mirror-ui.js +100 -0
  20. package/dist/src/calcom-perform-harness.d.ts +5 -0
  21. package/dist/src/calcom-perform-harness.js +29 -0
  22. package/dist/src/calcom-server.d.ts +14 -0
  23. package/dist/src/calcom-server.js +31 -0
  24. package/dist/src/calcom-twin.d.ts +16 -0
  25. package/dist/src/calcom-twin.js +718 -0
  26. package/dist/src/cli.d.ts +2 -0
  27. package/dist/src/cli.js +31 -0
  28. package/dist/src/index.d.ts +11 -0
  29. package/dist/src/index.js +69 -0
  30. package/package.json +72 -0
  31. package/src/calcom-budget.ts +171 -0
  32. package/src/calcom-capabilities.ts +529 -0
  33. package/src/calcom-conformance.ts +92 -0
  34. package/src/calcom-connector.ts +258 -0
  35. package/src/calcom-mirror-ui.ts +110 -0
  36. package/src/calcom-perform-harness.ts +24 -0
  37. package/src/calcom-server.ts +39 -0
  38. package/src/calcom-twin.ts +675 -0
  39. package/src/cli.ts +29 -0
  40. package/src/index.ts +101 -0
package/src/cli.ts ADDED
@@ -0,0 +1,29 @@
1
+ #!/usr/bin/env node
2
+ import { keepProcessAlive } from '@volter/world-core/lifecycle';
3
+ // world-calcom CLI: serve the Cal.com v2 API twin, the mirror UI, or run conformance.
4
+ import { hasFlag, optionValue } from '@volter/world-core/args';
5
+ import { createCalcomTwinServer } from './calcom-server.ts';
6
+ import { createCalcomMirrorServer } from './calcom-mirror-ui.ts';
7
+
8
+ const [cmd, ...rest] = process.argv.slice(2);
9
+ const port = Number(optionValue(rest, '--port', '0')) || undefined;
10
+ const root = optionValue(rest, '--root') || undefined;
11
+ const readOnly = hasFlag(rest, '--read-only'); // a twin accepts writes unless started read-only
12
+
13
+ if (cmd === 'serve') {
14
+ const s = await createCalcomTwinServer({ readOnly, ...(root ? { root } : {}), ...(port ? { port } : {}) });
15
+ process.stdout.write(`calcom twin (v2 API)${readOnly ? ' [read-only]' : ''} at http://127.0.0.1:${s.port}\n`);
16
+ await keepProcessAlive();
17
+ } else if (cmd === 'mirror') {
18
+ const s = await createCalcomMirrorServer({ ...(root ? { root } : {}), ...(port ? { port } : {}) });
19
+ process.stdout.write(`calcom mirror UI (dashboard) at http://127.0.0.1:${s.port}\n`);
20
+ await keepProcessAlive();
21
+ } else if (cmd === 'conformance') {
22
+ // dev-only; lazy so the bin runs without @volter/world-tooling in the runtime graph
23
+ const { checkCalcomConformance } = await import('./calcom-conformance.ts');
24
+ const report = checkCalcomConformance({ ...(root ? { root } : {}) });
25
+ process.stdout.write(`${JSON.stringify(report, null, 2)}\n`);
26
+ if (!report.ok) process.exitCode = 1;
27
+ } else {
28
+ process.stdout.write('Usage: world-calcom serve|mirror|conformance [--port N] [--root DIR] [--read-only]\n');
29
+ }
package/src/index.ts ADDED
@@ -0,0 +1,101 @@
1
+ // @volter/twin-calcom — the Cal.com twin (one vendor, one package), built on the shared
2
+ // @volter/world-core kernel. REST (v2) transport, spec-faithful `{ status, data }` envelope,
3
+ // stateful bookings/event-types/schedules/teams/webhooks, and a React dashboard mirror.
4
+ // Auth is a faked-locally Bearer API key — there is NO JWT / JWKS / webhook signing
5
+ // (Cal.com's API auth is a plain bearer `cal_…` key). Conformance tooling lives in
6
+ // @volter/world-tooling (a dev dependency) — not shipped in the runtime API.
7
+ export { handleCalcomTwinRequest, TWIN_API_VERSION, RESOURCE_TYPES } from './calcom-twin.ts';
8
+ export type { CalcomRequest, CalcomResponse } from './calcom-twin.ts';
9
+ export { createCalcomTwinFetch, createCalcomTwinServer, type CalcomTwinFetchOptions } from './calcom-server.ts';
10
+ export {
11
+ calcomRequestForAction,
12
+ liveCalcomExecute,
13
+ mapBooking,
14
+ mapEventType,
15
+ pullCalcomAll,
16
+ pullCalcomBookings,
17
+ pullCalcomEventTypes,
18
+ syncCalcomFromReal,
19
+ } from './calcom-connector.ts';
20
+ export type { CalcomExecute, LiveCalcomOptions } from './calcom-connector.ts';
21
+ // The client-side rate budget — the fail-closed backstop `liveCalcomExecute` routes every live
22
+ // request through. The MECHANISM is the kernel's shared, vendor-agnostic `RateBudget`; what lives
23
+ // here is Cal.com's DECLARATION (window/ceiling/per-endpoint weights) plus the vendor-bound
24
+ // bindings. Exported so an operator can inspect spend (`snapshot`) and so a caller can catch
25
+ // `CalcomBudgetError` by type; there is deliberately no export that disables the guard.
26
+ export {
27
+ CALCOM_BUDGET_CEILING,
28
+ CALCOM_BUDGET_MAX_RETRY_AFTER_S,
29
+ CALCOM_BUDGET_WINDOW_MS,
30
+ CALCOM_CALL_WEIGHTS,
31
+ CALCOM_RATE_BUDGET,
32
+ CalcomBudget,
33
+ CalcomBudgetError,
34
+ calcomBudgetPath,
35
+ calcomCallWeight,
36
+ } from './calcom-budget.ts';
37
+ export type { CalcomBudgetErrorKind, CalcomBudgetOptions, CalcomBudgetReservation, CalcomBudgetSnapshot } from './calcom-budget.ts';
38
+ export {
39
+ attendeeLabel,
40
+ bookingTone,
41
+ buildCalcomMirrorClient,
42
+ calcomMirrorHtml,
43
+ createCalcomMirrorServer,
44
+ formatWindow,
45
+ } from './calcom-mirror-ui.ts';
46
+ export type { CalcomRow } from './calcom-mirror-ui.ts';
47
+
48
+ // Registry descriptor: the pack self-describes so tooling can discover it.
49
+ import { registerPack, type TwinPack } from '@volter/world-core';
50
+ import { CALCOM_RATE_BUDGET as RATE_BUDGET } from './calcom-budget.ts';
51
+ import { performCalcomAction, syncCalcomFromRemote } from './calcom-connector.ts';
52
+
53
+ export const pack: TwinPack = {
54
+ vendor: 'calcom',
55
+ // PROTOCOL 2 (docs/contributing/architecture.md#protocol-2-the-pack-is-a-plugin): the pack is a plugin — its wire, its tree, and its half of the real
56
+ // state system: perform one entry against Cal.com v2, refresh the root from it. Moved 2026-09-08.
57
+ protocol: '2',
58
+ refresh: { every: '5m', webhook: true, onDemand: { atMost: '30s' } },
59
+ stateSystem: { perform: performCalcomAction, refresh: syncCalcomFromRemote },
60
+ // the round trip: an event type, then a booking of it — the two things a scheduling account is made of
61
+ // the round trip is ONE write — an event type. A booking would have to name an event type, and the only
62
+ // one it could name statically is the twin's implicit default (7001), which is not the subject the kernel
63
+ // adopts; the reference trip below is where a booking gets made, against the event type this created.
64
+ roundTrip: { method: 'POST', path: '/v2/event-types', body: { title: 'Round trip', slug: 'round-trip', lengthInMinutes: 30 }, headers: { authorization: 'Bearer round-trip', 'cal-api-version': '2024-06-14' } },
65
+ // rule 5: a booking names the event type it is a booking OF; when the head adopts Cal.com's id for the
66
+ // event type, the kernel resolves the booking's field first
67
+ referenceTrip: { method: 'POST', path: '/v2/bookings', body: { start: '2026-09-09T11:00:00.000Z', eventTypeId: '{{evtId}}', attendee: { name: 'Round Trip', email: 'round@trip.test', timeZone: 'UTC' } }, headers: { authorization: 'Bearer round-trip', 'cal-api-version': '2024-08-13' } },
68
+ references: [{
69
+ type: 'booking', to: 'event_type',
70
+ key: (f: Record<string, unknown>) => (f.eventTypeId === undefined || f.eventTypeId === null ? undefined : `evt_${String(f.eventTypeId)}`),
71
+ adopt: (_f: Record<string, unknown>, vendorId: string) => ({ eventTypeId: vendorId.replace(/^evt_/, '') }),
72
+ }],
73
+ parityOrigin: 'http://twin',
74
+ shapeParity: 'held',
75
+ // The SAME object calcom-budget.ts declares at module load — one source of truth, so registering
76
+ // the pack and importing the connector can never arm two different ceilings.
77
+ rateBudget: RATE_BUDGET,
78
+ transport: 'rest',
79
+ archetype: 'crud',
80
+ bin: 'world-calcom',
81
+ resources: ['booking', 'event_type', 'schedule', 'team', 'membership', 'webhook', 'slot'],
82
+ specSource: 'cal.com/docs/api-reference/v2 (hand-authored from the published v2 reference)',
83
+ description: 'Cal.com v2 REST twin — { status, data } envelope, stateful bookings/event-types/schedules/teams/webhooks, dashboard mirror.',
84
+ // Adoption + interception, moved off the central maps unchanged (descriptor-first back-migration, adding-a-twin.md §3,
85
+ // 2026-08-31). Both credential-env spellings the vendor uses — CALCOM_* and the
86
+ // shorter CAL_* — stem here; there is no npm client to claim (Cal.com integrations call the v2
87
+ // REST surface directly), so `sdks` is deliberately absent rather than invented.
88
+ adoption: {
89
+ // Cal.com ships no Python SDK and no community client exists. The `Calcom` distribution on
90
+ // PyPI is an unrelated mathematics package - claiming it would map a maths dependency onto a
91
+ // scheduling twin.
92
+ pypi: [],
93
+ envStems: ['CALCOM', 'CAL'],
94
+ },
95
+ hosts: [{ host: 'api.cal.com' }],
96
+ // A scheduling client calls api.cal.com/v2/… — the dev proxy forwards '/v2/' to the twin
97
+ // and strips the absolute host so calls come back same-origin.
98
+ browserRouting: { apiPathPrefix: '/v2/', loaderHost: 'https://api.cal.com' },
99
+ };
100
+ // registered at import: the kernel learns the pack's state system (protocol 2)
101
+ registerPack(pack);