@crvouga/mockingbird-service-google-calendar 1.0.0 → 1.0.1

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 CHANGED
@@ -1,15 +1,18 @@
1
1
  # Changelog — @crvouga/mockingbird-service-google-calendar
2
2
 
3
+ ## 1.0.1 (2026-09-26)
4
+
5
+ ### Fixes and improvements
6
+
7
+ - take the rejected-request byte count from content-length, never by reading the body ([a0e5fb2](https://github.com/crvouga/mockingbird/commit/a0e5fb2fc80ab725c3552b612f3f091fd6c857fb))
8
+ - reject a present body by media type, and log what a rejected request sent ([12e351a](https://github.com/crvouga/mockingbird/commit/12e351aba53cfb7b41e31a7809419455fc2902eb))
9
+
3
10
  ## 1.0.0 (2026-09-24)
4
11
 
5
12
  ### ⚠️ Breaking changes
6
13
 
7
14
  - vendor branding for every service; purge internal mocks and consumer names ([f689534](https://github.com/crvouga/mockingbird/commit/f6895343543550dafcb7d76b426cae7635e03226))
8
15
 
9
- ### Dependencies
10
-
11
- - `@crvouga/mockingbird-service-sqlite`
12
-
13
16
  ## 0.2.0 (2026-09-23)
14
17
 
15
18
  ### Features
@@ -1384,6 +1384,90 @@ var operationMetadata = (operation) => {
1384
1384
 
1385
1385
  // ../core/dist/service.js
1386
1386
  import { Hono } from "hono";
1387
+
1388
+ // ../core/dist/validation.js
1389
+ var requestBodyOf = (context) => {
1390
+ const requestBody = context.operation.operation.requestBody;
1391
+ return requestBody ? deref(context.document, requestBody) : void 0;
1392
+ };
1393
+ var mediaTypeMatches = (accepted, actual) => {
1394
+ const pattern = mediaTypeOf(accepted) ?? accepted.toLowerCase();
1395
+ if (pattern === actual || pattern === "*/*")
1396
+ return true;
1397
+ const [type, subtype] = pattern.split("/");
1398
+ const [actualType, actualSubtype] = actual.split("/");
1399
+ if (type !== actualType && type !== "*")
1400
+ return false;
1401
+ if (subtype === void 0 || subtype === "*")
1402
+ return true;
1403
+ if (subtype.startsWith("*+"))
1404
+ return actualSubtype?.endsWith(subtype.slice(1)) === true;
1405
+ return false;
1406
+ };
1407
+ var acceptedKeyFor = (content, mediaType) => {
1408
+ if (!content || mediaType === void 0)
1409
+ return void 0;
1410
+ const keys = Object.keys(content);
1411
+ return keys.find((key) => mediaTypeOf(key) === mediaType) ?? keys.find((key) => mediaTypeMatches(key, mediaType));
1412
+ };
1413
+ var unsupportedMediaType = (context, options = {}) => {
1414
+ if (context.body.kind === "empty" && options.includeEmpty !== true)
1415
+ return void 0;
1416
+ const content = requestBodyOf(context)?.content;
1417
+ if (!content || Object.keys(content).length === 0)
1418
+ return void 0;
1419
+ const mediaType = mediaTypeOf(context.request.headers.get("content-type"));
1420
+ if (acceptedKeyFor(content, mediaType) !== void 0)
1421
+ return void 0;
1422
+ return { mediaType: mediaType ?? null, accepted: Object.keys(content) };
1423
+ };
1424
+ var recorded = /* @__PURE__ */ new WeakMap();
1425
+ var recordedIssues = (request) => recorded.get(request);
1426
+ var bodyIssues = (context, contentType = "application/json") => {
1427
+ const issues = findBodyIssues(context, contentType);
1428
+ if (issues.length > 0)
1429
+ recorded.set(context.request, issues);
1430
+ return issues;
1431
+ };
1432
+ var findBodyIssues = (context, contentType) => {
1433
+ const resolved = requestBodyOf(context);
1434
+ if (!resolved)
1435
+ return [];
1436
+ const unsupported = unsupportedMediaType(context);
1437
+ if (unsupported) {
1438
+ return [
1439
+ {
1440
+ path: "",
1441
+ kind: "media_type",
1442
+ message: unsupported.mediaType === null ? "request body has no content-type" : `request body media type ${unsupported.mediaType} is not supported`
1443
+ }
1444
+ ];
1445
+ }
1446
+ const key = acceptedKeyFor(resolved.content, mediaTypeOf(context.request.headers.get("content-type"))) ?? contentType;
1447
+ const schema = resolved.content?.[key]?.schema;
1448
+ if (!schema)
1449
+ return [];
1450
+ if (context.body.kind === "invalid") {
1451
+ return [
1452
+ {
1453
+ path: "",
1454
+ kind: "syntax",
1455
+ message: `request body is not valid ${context.body.mediaType}`
1456
+ }
1457
+ ];
1458
+ }
1459
+ const value = context.body.kind === "json" || context.body.kind === "form" || context.body.kind === "text" ? context.body.value : void 0;
1460
+ if (value === void 0) {
1461
+ return resolved.required && context.body.kind === "empty" ? [{ path: "", kind: "required", message: "request body is required" }] : [];
1462
+ }
1463
+ return validateValue(context.document, resolveSchema(context.document, schema), value).map((issue) => ({ path: issue.path.join("."), kind: "schema", message: issue.message }));
1464
+ };
1465
+
1466
+ // ../core/dist/service.js
1467
+ var withIssues = (request, response) => {
1468
+ const issues = response.status >= 400 ? recordedIssues(request) : void 0;
1469
+ return issues && issues.length > 0 ? annotateResponse(response, { issues }) : response;
1470
+ };
1387
1471
  var defineOperations = (handlers) => handlers;
1388
1472
  var OperationRegistryError = class extends Error {
1389
1473
  problems;
@@ -1469,9 +1553,7 @@ var createService = (options) => {
1469
1553
  now
1470
1554
  };
1471
1555
  const short = await options.before?.(context);
1472
- if (short)
1473
- return short;
1474
- return handler(context);
1556
+ return withIssues(request, short ?? await handler(context));
1475
1557
  };
1476
1558
  app.on(operation.method.toUpperCase(), honoPath(operation.path), route);
1477
1559
  }
@@ -1508,7 +1590,7 @@ var restoreNamespace = (sqlite, namespace, snapshot) => {
1508
1590
  };
1509
1591
 
1510
1592
  // ../core/dist/version.js
1511
- var PACKAGE_VERSION = true ? "1.0.0" : UNRELEASED_VERSION;
1593
+ var PACKAGE_VERSION = true ? "1.0.1" : UNRELEASED_VERSION;
1512
1594
 
1513
1595
  // ../core/dist/signing.js
1514
1596
  var encoder = new TextEncoder();
@@ -2268,8 +2350,15 @@ var createRuntime = (options) => {
2268
2350
  const started = monotonicNow();
2269
2351
  const url = new URL(request.url);
2270
2352
  const operationId = operationIdFor(request, url.pathname);
2353
+ const contentLength = request.headers.get("content-length");
2354
+ const received = {
2355
+ contentType: request.headers.get("content-type"),
2356
+ bodyBytes: contentLength !== null && /^\d+$/.test(contentLength) ? Number(contentLength) : null,
2357
+ transferEncoding: request.headers.get("transfer-encoding")
2358
+ };
2271
2359
  const log = (status, faultId, response2) => {
2272
2360
  const noted = response2 ? responseNotes(response2) : void 0;
2361
+ const rejected = status >= 400 && faultId === void 0;
2273
2362
  const entry = {
2274
2363
  service: options.name,
2275
2364
  namespace,
@@ -2281,7 +2370,9 @@ var createRuntime = (options) => {
2281
2370
  unmatched: options.document !== void 0 && operationId === void 0,
2282
2371
  ...faultId !== void 0 ? { faultId } : {},
2283
2372
  ...noted?.ids && Object.keys(noted.ids).length > 0 ? { ids: noted.ids } : {},
2284
- ...noted?.adopted ? { adopted: true } : {}
2373
+ ...noted?.adopted ? { adopted: true } : {},
2374
+ ...rejected ? { request: { ...received } } : {},
2375
+ ...rejected && noted?.issues && noted.issues.length > 0 ? { issues: noted.issues.map((issue) => ({ ...issue })) } : {}
2285
2376
  };
2286
2377
  metrics.record(entry);
2287
2378
  journal.record({ ...entry, at: new Date(clock.now()).toISOString() });
@@ -2488,25 +2579,6 @@ var presetRoutes = (presets, runtime) => ({
2488
2579
  }
2489
2580
  });
2490
2581
 
2491
- // ../core/dist/validation.js
2492
- var bodyIssues = (context, contentType = "application/json") => {
2493
- const requestBody = context.operation.operation.requestBody;
2494
- if (!requestBody)
2495
- return [];
2496
- const resolved = deref(context.document, requestBody);
2497
- const schema = resolved.content?.[contentType]?.schema;
2498
- if (!schema)
2499
- return [];
2500
- const value = context.body.kind === "json" || context.body.kind === "form" ? context.body.value : void 0;
2501
- if (context.body.kind === "invalid") {
2502
- return [{ path: "", message: `request body is not valid ${context.body.mediaType}` }];
2503
- }
2504
- if (value === void 0) {
2505
- return resolved.required ? [{ path: "", message: "request body is required" }] : [];
2506
- }
2507
- return validateValue(context.document, resolveSchema(context.document, schema), value).map((issue) => ({ path: issue.path.join("."), message: issue.message }));
2508
- };
2509
-
2510
2582
  // src/generated/openapi.ts
2511
2583
  var document = JSON.parse(`{"openapi":"3.1.0","info":{"title":"Google Calendar v3 + Google OAuth (Mockingbird subset)","description":"Stateful mock subset of the Google Calendar API v3 (calendarList.list, calendars.insert, events list/get/insert/update/delete/watch, channels.stop) and Google OAuth 2.0 (token, revoke, OpenID userinfo), as \`googleapis\` / \`@googleapis/calendar\` and google-auth-library call them. Trimmed from Google's discovery document to what our EMR calls.\\n","version":"v3","x-mockingbird-upstream":{"note":"Shapes from https://www.googleapis.com/discovery/v1/apis/calendar/v3/rest and https://developers.google.com/identity/protocols/oauth2; consumer (the EMR backend): services/google-calendar-service.ts, business/authorize/authorize.business.ts, routers/v1/webhooks/controller.ts."}},"servers":[{"url":"https://www.googleapis.com"}],"security":[{"bearerAuth":[]}],"paths":{"/token":{"post":{"operationId":"OAuthToken","description":"OAuth 2.0 token endpoint (oauth2.googleapis.com/token): authorization_code and refresh_token grants, form-encoded as google-auth-library sends them.","security":[],"x-mockingbird":{"supported":true,"parity":{"enabled":true,"safe":true}},"requestBody":{"required":true,"content":{"application/x-www-form-urlencoded":{"schema":{"$ref":"#/components/schemas/TokenRequest"}}}},"responses":{"200":{"description":"Tokens","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TokenResponse"}}}},"400":{"description":"invalid_grant / invalid_request / unsupported_grant_type","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OAuthError"}}}},"401":{"description":"invalid_client","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OAuthError"}}}}}}},"/revoke":{"post":{"operationId":"OAuthRevoke","description":"Revoke an access or refresh token (oauth2.googleapis.com/revoke?token=).","security":[],"x-mockingbird":{"supported":true,"parity":{"enabled":true,"safe":true}},"parameters":[{"name":"token","in":"query","required":true,"schema":{"type":"string","examples":["1//mock.cGFyaXR5QGV4YW1wbGUuY29t.0.x"]}}],"responses":{"200":{"description":"Revoked","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"invalid_token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OAuthError"}}}}}}},"/oauth2/v3/userinfo":{"get":{"operationId":"UserInfo","description":"OpenID userinfo for the token's user (www.googleapis.com/oauth2/v3/userinfo).","x-mockingbird":{"supported":true,"parity":{"enabled":true,"safe":true}},"responses":{"200":{"description":"Profile","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserInfo"}}}},"401":{"description":"Invalid token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OAuthError"}}}}}}},"/calendar/v3/users/me/calendarList":{"get":{"operationId":"CalendarListList","description":"The user's calendar list.","x-mockingbird":{"supported":true,"parity":{"enabled":true,"safe":true}},"responses":{"200":{"description":"Calendar list","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CalendarList"}}}},"400":{"description":"Invalid value","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GoogleError"}}}},"401":{"description":"Missing, invalid or expired access token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GoogleError"}}}},"403":{"description":"Rate limit, disabled API or insufficient scopes","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GoogleError"}}}},"429":{"description":"Too many requests","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GoogleError"}}}}},"parameters":[{"name":"maxResults","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":250}},{"name":"pageToken","in":"query","required":false,"schema":{"type":"string","enum":["bogus"]}}]}},"/calendar/v3/calendars":{"post":{"operationId":"CalendarsInsert","description":"Create a secondary calendar.","x-mockingbird":{"supported":true,"parity":{"enabled":true,"safe":false}},"responses":{"200":{"description":"Calendar","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Calendar"}}}},"400":{"description":"Missing summary","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GoogleError"}}}},"401":{"description":"Missing, invalid or expired access token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GoogleError"}}}},"403":{"description":"Rate limit, disabled API or insufficient scopes","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GoogleError"}}}},"429":{"description":"Too many requests","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GoogleError"}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CalendarInput"}}}}}},"/calendar/v3/calendars/{calendarId}/events":{"parameters":[{"name":"calendarId","in":"path","required":true,"schema":{"type":"string","enum":["primary"]},"description":"\`primary\` or a calendar id from calendars.insert / calendarList (parity vocabulary: primary)."}],"get":{"operationId":"EventsList","description":"Events in a calendar: full lists with timeMin/timeMax/q/orderBy, pagination via pageToken, incremental sync via syncToken (410 fullSyncRequired when it is no longer valid).","x-mockingbird":{"supported":true,"parity":{"enabled":true,"safe":true}},"responses":{"200":{"description":"Events","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Events"}}}},"400":{"description":"Invalid parameter combination","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GoogleError"}}}},"401":{"description":"Missing, invalid or expired access token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GoogleError"}}}},"403":{"description":"Rate limit, disabled API or insufficient scopes","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GoogleError"}}}},"404":{"description":"Unknown calendar","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GoogleError"}}}},"410":{"description":"Sync token no longer valid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GoogleError"}}}},"429":{"description":"Too many requests","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GoogleError"}}}}},"parameters":[{"name":"timeMin","in":"query","required":false,"schema":{"type":"string","enum":["2026-01-01T00:00:00Z","2026-10-01T00:00:00Z"]}},{"name":"timeMax","in":"query","required":false,"schema":{"type":"string","enum":["2026-12-31T00:00:00Z","2026-10-02T00:00:00Z"]}},{"name":"maxResults","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":2500}},{"name":"singleEvents","in":"query","required":false,"schema":{"type":"boolean"}},{"name":"orderBy","in":"query","required":false,"schema":{"type":"string","enum":["startTime","updated"]}},{"name":"q","in":"query","required":false,"schema":{"type":"string","enum":["EMR-local-","Standup","nothing"]}},{"name":"showDeleted","in":"query","required":false,"schema":{"type":"boolean"}},{"name":"syncToken","in":"query","required":false,"schema":{"type":"string","enum":["CAESmockinvalid"]}},{"name":"pageToken","in":"query","required":false,"schema":{"type":"string","enum":["bogus"]}}]},"post":{"operationId":"EventsInsert","description":"Create an event.","x-mockingbird":{"supported":true,"parity":{"enabled":true,"safe":false}},"responses":{"200":{"description":"Event","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Event"}}}},"400":{"description":"Missing or empty time range","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GoogleError"}}}},"401":{"description":"Missing, invalid or expired access token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GoogleError"}}}},"403":{"description":"Rate limit, disabled API or insufficient scopes","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GoogleError"}}}},"404":{"description":"Unknown calendar","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GoogleError"}}}},"409":{"description":"Duplicate id","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GoogleError"}}}},"429":{"description":"Too many requests","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GoogleError"}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EventInput"}}}}}},"/calendar/v3/calendars/{calendarId}/events/{eventId}":{"parameters":[{"name":"calendarId","in":"path","required":true,"schema":{"type":"string","enum":["primary"]},"description":"\`primary\` or a calendar id from calendars.insert / calendarList (parity vocabulary: primary)."},{"name":"eventId","in":"path","required":true,"schema":{"type":"string","x-mockingbird-resource-ref":{"type":"event","missing":"0000000000000000000000mock"}}}],"get":{"operationId":"EventsGet","description":"One event.","x-mockingbird":{"supported":true,"parity":{"enabled":true,"safe":true}},"responses":{"200":{"description":"Event","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Event"}}}},"401":{"description":"Missing, invalid or expired access token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GoogleError"}}}},"403":{"description":"Rate limit, disabled API or insufficient scopes","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GoogleError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GoogleError"}}}},"410":{"description":"Deleted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GoogleError"}}}},"429":{"description":"Too many requests","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GoogleError"}}}}}},"put":{"operationId":"EventsUpdate","description":"Replace an event.","x-mockingbird":{"supported":true,"parity":{"enabled":true,"safe":false}},"responses":{"200":{"description":"Event","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Event"}}}},"400":{"description":"Missing or empty time range","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GoogleError"}}}},"401":{"description":"Missing, invalid or expired access token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GoogleError"}}}},"403":{"description":"Rate limit, disabled API or insufficient scopes","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GoogleError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GoogleError"}}}},"429":{"description":"Too many requests","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GoogleError"}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EventInput"}}}}},"delete":{"operationId":"EventsDelete","description":"Delete an event (it stays visible as cancelled to incremental sync).","x-mockingbird":{"supported":true,"parity":{"enabled":true,"safe":false}},"responses":{"204":{"description":"Deleted"},"401":{"description":"Missing, invalid or expired access token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GoogleError"}}}},"403":{"description":"Rate limit, disabled API or insufficient scopes","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GoogleError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GoogleError"}}}},"410":{"description":"Already deleted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GoogleError"}}}},"429":{"description":"Too many requests","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GoogleError"}}}}}}},"/calendar/v3/calendars/{calendarId}/events/watch":{"parameters":[{"name":"calendarId","in":"path","required":true,"schema":{"type":"string","enum":["primary"]},"description":"\`primary\` or a calendar id from calendars.insert / calendarList (parity vocabulary: primary)."}],"post":{"operationId":"EventsWatch","description":"Open a push-notification channel on a calendar's events. A \`sync\` notification follows immediately, then \`exists\` on every change.","x-mockingbird":{"supported":true,"parity":{"enabled":true,"safe":false}},"responses":{"200":{"description":"Channel","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Channel"}}}},"400":{"description":"Bad channel","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GoogleError"}}}},"401":{"description":"Missing, invalid or expired access token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GoogleError"}}}},"403":{"description":"Rate limit, disabled API or insufficient scopes","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GoogleError"}}}},"404":{"description":"Unknown calendar","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GoogleError"}}}},"429":{"description":"Too many requests","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GoogleError"}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WatchRequest"}}}}}},"/calendar/v3/channels/stop":{"post":{"operationId":"ChannelsStop","description":"Stop a push-notification channel.","x-mockingbird":{"supported":true,"parity":{"enabled":true,"safe":false}},"responses":{"204":{"description":"Stopped"},"400":{"description":"Invalid value","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GoogleError"}}}},"401":{"description":"Missing, invalid or expired access token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GoogleError"}}}},"403":{"description":"Rate limit, disabled API or insufficient scopes","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GoogleError"}}}},"404":{"description":"Unknown channel","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GoogleError"}}}},"429":{"description":"Too many requests","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GoogleError"}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StopRequest"}}}}}}},"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer"}},"schemas":{"TokenRequest":{"type":"object","required":["grant_type"],"properties":{"grant_type":{"type":"string","enum":["authorization_code","refresh_token"]},"code":{"type":"string","examples":["4/mock-parity","4/mock-alice","4/unknown-code"]},"refresh_token":{"type":"string","examples":["1//mock.bogus"]},"client_id":{"type":"string","examples":["client-1.apps.googleusercontent.com"]},"client_secret":{"type":"string","examples":["secret"]},"redirect_uri":{"type":"string","examples":["postmessage"]},"code_verifier":{"type":"string"}}},"TokenResponse":{"type":"object","required":["access_token","expires_in","token_type","scope"],"properties":{"access_token":{"type":"string","x-mockingbird-volatile":{"kind":"token"}},"expires_in":{"type":"integer"},"refresh_token":{"type":"string","x-mockingbird-volatile":{"kind":"token"}},"scope":{"type":"string"},"token_type":{"type":"string","enum":["Bearer"]},"id_token":{"type":"string","x-mockingbird-volatile":{"kind":"token"}}}},"OAuthError":{"type":"object","required":["error"],"properties":{"error":{"type":"string"},"error_description":{"type":"string"}}},"UserInfo":{"type":"object","required":["sub","email"],"properties":{"sub":{"type":"string"},"name":{"type":"string"},"given_name":{"type":"string"},"family_name":{"type":"string"},"picture":{"type":"string"},"email":{"type":"string"},"email_verified":{"type":"boolean"}}},"GoogleError":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message","errors"],"properties":{"code":{"type":"integer"},"message":{"type":"string"},"status":{"type":"string"},"errors":{"type":"array","items":{"type":"object","required":["domain","reason","message"],"properties":{"domain":{"type":"string"},"reason":{"type":"string"},"message":{"type":"string"},"locationType":{"type":"string"},"location":{"type":"string"}}}}}}}},"CalendarInput":{"type":"object","required":["summary"],"properties":{"summary":{"type":"string","minLength":1,"maxLength":100,"examples":["EMR Appointments (Local)"]},"description":{"type":"string","maxLength":500},"timeZone":{"type":"string","examples":["America/New_York","UTC"]}}},"Calendar":{"type":"object","required":["kind","etag","id","summary"],"properties":{"kind":{"type":"string","enum":["calendar#calendar"]},"etag":{"type":"string","x-mockingbird-volatile":{"kind":"opaque"}},"id":{"type":"string","x-mockingbird-resource":{"type":"calendar","identity":true},"x-mockingbird-volatile":{"kind":"id"}},"summary":{"type":"string"},"description":{"type":"string"},"timeZone":{"type":"string"}}},"CalendarListEntry":{"type":"object","required":["kind","id","summary","accessRole"],"properties":{"kind":{"type":"string","enum":["calendar#calendarListEntry"]},"etag":{"type":"string","x-mockingbird-volatile":{"kind":"opaque"}},"id":{"type":"string","x-mockingbird-volatile":{"kind":"id"}},"summary":{"type":"string"},"description":{"type":"string"},"timeZone":{"type":"string"},"primary":{"type":"boolean"},"accessRole":{"type":"string"}}},"CalendarList":{"type":"object","required":["kind","items"],"properties":{"kind":{"type":"string","enum":["calendar#calendarList"]},"etag":{"type":"string","x-mockingbird-volatile":{"kind":"opaque"}},"nextSyncToken":{"type":"string","x-mockingbird-volatile":{"kind":"token"}},"items":{"type":"array","items":{"$ref":"#/components/schemas/CalendarListEntry"}}}},"EventInput":{"type":"object","properties":{"id":{"type":"string","pattern":"^[a-v0-9]{5,40}$","examples":["emrappt00001"]},"summary":{"type":"string","maxLength":200,"examples":["EMR-local-Follow-up","Standup"]},"description":{"type":"string","maxLength":1000},"location":{"type":"string","maxLength":200},"status":{"type":"string","enum":["confirmed","tentative","cancelled"]},"start":{"type":"object","properties":{"dateTime":{"type":"string","examples":["2026-10-01T15:00:00Z","2026-10-01T16:00:00Z"]},"timeZone":{"type":"string","examples":["UTC"]}}},"end":{"type":"object","properties":{"dateTime":{"type":"string","examples":["2026-10-01T16:00:00Z","2026-10-01T15:30:00Z"]},"timeZone":{"type":"string","examples":["UTC"]}}},"extendedProperties":{"type":"object","properties":{"private":{"type":"object","additionalProperties":{"type":"string","maxLength":100}}}}}},"Event":{"type":"object","required":["kind","etag","id","status"],"properties":{"kind":{"type":"string","enum":["calendar#event"]},"etag":{"type":"string","x-mockingbird-volatile":{"kind":"opaque"}},"id":{"type":"string","x-mockingbird-resource":{"type":"event","identity":true},"x-mockingbird-volatile":{"kind":"id"}},"status":{"type":"string"},"htmlLink":{"type":"string","x-mockingbird-volatile":{"kind":"url"}},"created":{"type":"string","x-mockingbird-volatile":{"kind":"timestamp"}},"updated":{"type":"string","x-mockingbird-volatile":{"kind":"timestamp"}},"summary":{"type":"string"},"description":{"type":"string"},"location":{"type":"string"},"creator":{"type":"object"},"organizer":{"type":"object"},"start":{"type":"object","properties":{"dateTime":{"type":"string"},"date":{"type":"string"},"timeZone":{"type":"string"}}},"end":{"type":"object","properties":{"dateTime":{"type":"string"},"date":{"type":"string"},"timeZone":{"type":"string"}}},"iCalUID":{"type":"string","x-mockingbird-volatile":{"kind":"id"}},"sequence":{"type":"integer"},"extendedProperties":{"type":"object"},"reminders":{"type":"object"},"eventType":{"type":"string"}}},"Events":{"type":"object","required":["kind","items"],"properties":{"kind":{"type":"string","enum":["calendar#events"]},"etag":{"type":"string","x-mockingbird-volatile":{"kind":"opaque"}},"summary":{"type":"string"},"updated":{"type":"string","x-mockingbird-volatile":{"kind":"timestamp"}},"timeZone":{"type":"string"},"accessRole":{"type":"string"},"defaultReminders":{"type":"array"},"nextPageToken":{"type":"string","x-mockingbird-volatile":{"kind":"token"}},"nextSyncToken":{"type":"string","x-mockingbird-volatile":{"kind":"token"}},"items":{"type":"array","items":{"$ref":"#/components/schemas/Event"}}}},"WatchRequest":{"type":"object","required":["id","type","address"],"properties":{"id":{"type":"string","minLength":1,"maxLength":64,"pattern":"^[A-Za-z0-9/_+=-]+$"},"type":{"type":"string","enum":["web_hook","webhook"]},"address":{"type":"string","format":"uri","examples":["https://emr.example.com/v1/webhooks/google-calendar/primary","https://emr.example.com/v1/webhooks/google-calendar/emr"]},"token":{"type":"string","maxLength":256},"expiration":{"type":"string","pattern":"^[0-9]{10,14}$"}}},"Channel":{"type":"object","required":["kind","id","resourceId","resourceUri"],"properties":{"kind":{"type":"string","enum":["api#channel"]},"id":{"type":"string","x-mockingbird-resource":{"type":"channel","identity":true}},"resourceId":{"type":"string","x-mockingbird-resource":{"type":"channel_resource","identity":true},"x-mockingbird-volatile":{"kind":"id"}},"resourceUri":{"type":"string","x-mockingbird-volatile":{"kind":"url"}},"token":{"type":"string"},"expiration":{"type":"string","x-mockingbird-volatile":{"kind":"timestamp"}}}},"StopRequest":{"type":"object","required":["id","resourceId"],"properties":{"id":{"type":"string","x-mockingbird-resource-ref":{"type":"channel","missing":"missing-channel"}},"resourceId":{"type":"string","x-mockingbird-resource-ref":{"type":"channel_resource","missing":"missing-resource"}}}}}}}`);
2512
2584
  var operationIds = ["OAuthToken", "OAuthRevoke", "UserInfo", "CalendarListList", "CalendarsInsert", "EventsList", "EventsInsert", "EventsGet", "EventsUpdate", "EventsDelete", "EventsWatch", "ChannelsStop"];
@@ -3564,4 +3636,4 @@ export {
3564
3636
  emailFromCode,
3565
3637
  GoogleCalendarAPI
3566
3638
  };
3567
- //# sourceMappingURL=chunk-W4HXGXSP.js.map
3639
+ //# sourceMappingURL=chunk-PTCOC2XS.js.map