@q9labsai/chalk-client 4.1.5 → 4.1.7

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 (56) hide show
  1. package/dist/access/grant.d.ts +8 -0
  2. package/dist/access/grant.d.ts.map +1 -1
  3. package/dist/{chunk-PBCGWE2V.js → chunk-C4BIONCP.js} +442 -7
  4. package/dist/chunk-DFLTEYWX.js +144 -0
  5. package/dist/chunk-JPNE4K2L.js +8911 -0
  6. package/dist/{chunk-DI7C5UEM.js → chunk-MMK2K3LO.js} +63 -174
  7. package/dist/client.d.ts +951 -59
  8. package/dist/client.d.ts.map +1 -1
  9. package/dist/connection/dependencies.d.ts +4 -4
  10. package/dist/connection/dependencies.d.ts.map +1 -1
  11. package/dist/connection/lifecycle.d.ts.map +1 -1
  12. package/dist/connection/production.d.ts.map +1 -1
  13. package/dist/connection/snapshot.d.ts +2 -2
  14. package/dist/connection/snapshot.d.ts.map +1 -1
  15. package/dist/effect.js +1012 -7052
  16. package/dist/generated/http-api.d.ts +941 -62
  17. package/dist/generated/http-api.d.ts.map +1 -1
  18. package/dist/generated/schemas.d.ts +1353 -31
  19. package/dist/generated/schemas.d.ts.map +1 -1
  20. package/dist/index.d.ts +1 -0
  21. package/dist/index.d.ts.map +1 -1
  22. package/dist/index.js +20 -2
  23. package/dist/media/client.d.ts.map +1 -1
  24. package/dist/media/index.d.ts +2 -1
  25. package/dist/media/index.d.ts.map +1 -1
  26. package/dist/media/index.js +5 -1
  27. package/dist/media/observers.d.ts +3 -0
  28. package/dist/media/observers.d.ts.map +1 -0
  29. package/dist/media/plane.d.ts +25 -0
  30. package/dist/media/plane.d.ts.map +1 -1
  31. package/dist/media/rtk.d.ts +101 -0
  32. package/dist/media/rtk.d.ts.map +1 -0
  33. package/dist/media/target.d.ts +10 -0
  34. package/dist/media/target.d.ts.map +1 -0
  35. package/dist/public-invites/client.d.ts +4 -0
  36. package/dist/public-invites/client.d.ts.map +1 -0
  37. package/dist/public-invites/index.d.ts +5 -0
  38. package/dist/public-invites/index.d.ts.map +1 -0
  39. package/dist/public-invites/index.js +18 -0
  40. package/dist/public-invites/types.d.ts +67 -0
  41. package/dist/public-invites/types.d.ts.map +1 -0
  42. package/dist/server/{chunk-A6YMG5FM.js → chunk-C4XITY5U.js} +1 -1
  43. package/dist/server/client.d.ts.map +1 -1
  44. package/dist/server/index.cjs +72 -19
  45. package/dist/server/index.d.cts +1 -1
  46. package/dist/server/index.d.ts +1 -1
  47. package/dist/server/index.d.ts.map +1 -1
  48. package/dist/server/index.js +72 -19
  49. package/dist/server/server-only.js +1 -1
  50. package/dist/server/transport.d.cts +1 -1
  51. package/dist/server/transport.d.ts +1 -1
  52. package/dist/server/transport.d.ts.map +1 -1
  53. package/dist/server/types.d.cts +40 -0
  54. package/dist/server/types.d.ts +40 -0
  55. package/dist/server/types.d.ts.map +1 -1
  56. package/package.json +20 -2
@@ -1,7 +1,13 @@
1
1
  import {
2
+ CloudflareRTKClient,
2
3
  CloudflareSFUClient,
3
4
  createCloudflareSFUHTTPTransport
4
- } from "./chunk-PBCGWE2V.js";
5
+ } from "./chunk-C4BIONCP.js";
6
+ import {
7
+ AccessGrantError,
8
+ requireParsedAccessGrant,
9
+ validEpisodeDiagnosticCredential
10
+ } from "./chunk-JPNE4K2L.js";
5
11
  import {
6
12
  createBrowserSyncLifecycle,
7
13
  createBrowserWebSocketFactory,
@@ -81,7 +87,15 @@ function validateRefresh(previous, next, replaceMediaConnection) {
81
87
  if (left.tenantId !== right.tenantId || left.spaceId !== right.spaceId || left.episodeId !== right.episodeId || left.participantId !== right.participantId || left.participantGeneration !== right.participantGeneration) {
82
88
  throw new TypeError("Access grant refresh changed its subject");
83
89
  }
84
- if (!replaceMediaConnection && previous.media.clientPayload.connectionId !== next.media.clientPayload.connectionId) throw new TypeError("Access grant refresh unexpectedly replaced its media connection");
90
+ if (!replaceMediaConnection && (previous.media.provider !== next.media.provider || mediaBinding(previous) !== mediaBinding(next))) throw new TypeError("Access grant refresh unexpectedly replaced its media connection");
91
+ }
92
+ function mediaBinding(access) {
93
+ switch (access.media.provider) {
94
+ case "cloudflare_sfu":
95
+ return access.media.clientPayload.connectionId;
96
+ case "cloudflare_rtk":
97
+ return access.media.clientPayload.providerSubject;
98
+ }
85
99
  }
86
100
  function expiresAt(value) {
87
101
  const timestamp = Date.parse(value);
@@ -1669,8 +1683,18 @@ function createChatFileTransport(apiBaseURL, input) {
1669
1683
  });
1670
1684
  }
1671
1685
  function createMediaClient(apiBaseURL, input) {
1686
+ if (input.access.media.provider === "cloudflare_rtk") {
1687
+ return createRTKConnectionMediaClient(
1688
+ new CloudflareRTKClient({
1689
+ authToken: input.access.media.clientPayload.token,
1690
+ participantId: input.access.subject.participantId,
1691
+ onError: input.onFailure,
1692
+ onScreenEnded: input.onScreenEnded
1693
+ })
1694
+ );
1695
+ }
1672
1696
  const { subject } = input.access;
1673
- return new CloudflareSFUClient({
1697
+ const client = new CloudflareSFUClient({
1674
1698
  bootstrap: input.access.media.clientPayload,
1675
1699
  participantId: subject.participantId,
1676
1700
  transport: createCloudflareSFUHTTPTransport({
@@ -1684,6 +1708,36 @@ function createMediaClient(apiBaseURL, input) {
1684
1708
  onError: input.onFailure,
1685
1709
  onScreenEnded: input.onScreenEnded
1686
1710
  });
1711
+ return createSFUConnectionMediaClient(client);
1712
+ }
1713
+ function createRTKConnectionMediaClient(client) {
1714
+ return bindConnectionMediaClient(client, (input) => {
1715
+ if (!("provider" in input) || input.provider !== "cloudflare_rtk") throw new TypeError("The RealtimeKit adapter requires a Cloudflare RealtimeKit access grant");
1716
+ return client.restart(input);
1717
+ });
1718
+ }
1719
+ function createSFUConnectionMediaClient(client) {
1720
+ return bindConnectionMediaClient(client, (input) => {
1721
+ if ("provider" in input) {
1722
+ if (input.provider !== "cloudflare_sfu") throw new TypeError("The Cloudflare SFU adapter requires a Cloudflare SFU access grant");
1723
+ return client.restart(input.clientPayload);
1724
+ }
1725
+ return client.restart(input);
1726
+ });
1727
+ }
1728
+ function bindConnectionMediaClient(client, restart) {
1729
+ return {
1730
+ setLocalPublicationTarget: client.setLocalPublicationTarget.bind(client),
1731
+ observeLocalPublications: client.observeLocalPublications.bind(client),
1732
+ observeRemotePublications: client.observeRemotePublications.bind(client),
1733
+ start: client.start.bind(client),
1734
+ stop: client.stop.bind(client),
1735
+ restart,
1736
+ prepareLocalTrack: client.prepareLocalTrack.bind(client),
1737
+ clearPreparedLocalTrack: client.clearPreparedLocalTrack.bind(client),
1738
+ getSnapshot: client.getSnapshot.bind(client),
1739
+ subscribe: client.subscribe.bind(client)
1740
+ };
1687
1741
  }
1688
1742
  function createSyncClient(syncURL, input) {
1689
1743
  return createV1SyncClient({
@@ -1725,172 +1779,6 @@ function whiteboardURL(syncURL) {
1725
1779
  // src/connection/lifecycle.ts
1726
1780
  import { Clock as Clock2, Context as Context3, Data as Data2, Deferred, Duration, Effect as Effect2, Exit, Fiber, Layer as Layer3, Queue, Scope, SubscriptionRef } from "effect";
1727
1781
 
1728
- // src/access/base64-url.ts
1729
- function decodeBase64Url(value) {
1730
- const base64 = value.replaceAll("-", "+").replaceAll("_", "/").padEnd(Math.ceil(value.length / 4) * 4, "=");
1731
- const bytes = Uint8Array.from(globalThis.atob(base64), (character) => character.charCodeAt(0));
1732
- return new TextDecoder().decode(bytes);
1733
- }
1734
-
1735
- // src/access/episode-diagnostic-credential.ts
1736
- var INTAKE_PATH = "/_internal/episode-diagnostic-events";
1737
- var RFC3339_ZONED = /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})(?:\.\d+)?(Z|[+-]\d{2}:\d{2})$/;
1738
- function parseEpisodeDiagnosticCredential(value) {
1739
- if (!isRecord3(value)) return null;
1740
- const token = value.token;
1741
- const expiresAt2 = value.expires_at;
1742
- const generation = value.generation;
1743
- const intakePath = value.intake_path;
1744
- if (typeof token !== "string" || !validDiagnosticCredential(token)) return null;
1745
- if (!isRFC3339Zoned(expiresAt2)) return null;
1746
- if (!Number.isSafeInteger(generation) || generation < 1) return null;
1747
- if (intakePath !== INTAKE_PATH) return null;
1748
- return Object.freeze({ token, expiresAt: expiresAt2, generation, intakePath });
1749
- }
1750
- function validEpisodeDiagnosticCredential(credential, now) {
1751
- return credential.intakePath === INTAKE_PATH && Number.isSafeInteger(credential.generation) && credential.generation > 0 && isRFC3339Zoned(credential.expiresAt) && Date.parse(credential.expiresAt) > now && validDiagnosticCredential(credential.token);
1752
- }
1753
- function validDiagnosticCredential(token) {
1754
- const segments = token.split(".");
1755
- if (segments.length !== 3) return false;
1756
- try {
1757
- const payload = JSON.parse(decodeBase64Url(segments[1] ?? ""));
1758
- return isRecord3(payload) && payload.aud === "chalk-diagnostics";
1759
- } catch {
1760
- return false;
1761
- }
1762
- }
1763
- function isRFC3339Zoned(value) {
1764
- if (typeof value !== "string") return false;
1765
- const match = RFC3339_ZONED.exec(value);
1766
- if (!match) return false;
1767
- return validTimestampFields(match) && Number.isFinite(Date.parse(value));
1768
- }
1769
- function validTimestampFields(match) {
1770
- const year = Number(match[1]);
1771
- const month = Number(match[2]);
1772
- const day = Number(match[3]);
1773
- const hour = Number(match[4]);
1774
- const minute = Number(match[5]);
1775
- const second = Number(match[6]);
1776
- const zone = match[7] ?? "";
1777
- return validCalendarDate(year, month, day) && validClockTime(hour, minute, second) && validZoneOffset(zone);
1778
- }
1779
- function inRange(value, min, max) {
1780
- return value >= min && value <= max;
1781
- }
1782
- function validCalendarDate(year, month, day) {
1783
- return inRange(month, 1, 12) && inRange(day, 1, daysInMonth(year, month));
1784
- }
1785
- function validClockTime(hour, minute, second) {
1786
- return inRange(hour, 0, 23) && inRange(minute, 0, 59) && inRange(second, 0, 59);
1787
- }
1788
- function validZoneOffset(zone) {
1789
- if (zone === "Z") return true;
1790
- return inRange(Number(zone.slice(1, 3)), 0, 23) && inRange(Number(zone.slice(4, 6)), 0, 59);
1791
- }
1792
- function daysInMonth(year, month) {
1793
- if (month === 2) return isLeapYear(year) ? 29 : 28;
1794
- return [4, 6, 9, 11].includes(month) ? 30 : 31;
1795
- }
1796
- function isLeapYear(year) {
1797
- return year % 4 === 0 && (year % 100 !== 0 || year % 400 === 0);
1798
- }
1799
- function isRecord3(value) {
1800
- return typeof value === "object" && value !== null && !Array.isArray(value);
1801
- }
1802
-
1803
- // src/access/grant.ts
1804
- var AccessGrantError = class extends TypeError {
1805
- code = "access.invalid";
1806
- constructor(message = "Access grant is invalid") {
1807
- super(message);
1808
- this.name = "AccessGrantError";
1809
- }
1810
- };
1811
- function parseParsedAccessGrant(value) {
1812
- if (!isRecord4(value)) throw new AccessGrantError();
1813
- const subject = parseSubject(value.subject);
1814
- const diagnostics = parseEpisodeDiagnosticCredential(value.diagnostics);
1815
- return {
1816
- subject,
1817
- sync: parseSyncAccess(value.sync),
1818
- media: parseMediaAccess(value.media),
1819
- diagnostics: diagnostics?.generation === subject.participantGeneration ? diagnostics : null
1820
- };
1821
- }
1822
- async function requireParsedAccessGrant(value) {
1823
- if (typeof Response !== "undefined" && value instanceof Response) {
1824
- if (!value.ok) throw new AccessGrantError(`Access grant request failed with HTTP ${value.status}`);
1825
- try {
1826
- return parseParsedAccessGrant(await value.json());
1827
- } catch (error2) {
1828
- if (error2 instanceof AccessGrantError) throw error2;
1829
- throw new AccessGrantError();
1830
- }
1831
- }
1832
- return parseParsedAccessGrant(value);
1833
- }
1834
- function parseSubject(value) {
1835
- if (!isRecord4(value)) throw new AccessGrantError();
1836
- return {
1837
- tenantId: requireNonEmptyString(value.tenant_id),
1838
- spaceId: requireNonEmptyString(value.space_id),
1839
- episodeId: requireNonEmptyString(value.episode_id),
1840
- participantId: requireNonEmptyString(value.participant_id),
1841
- participantGeneration: requirePositiveInteger(value.participant_generation)
1842
- };
1843
- }
1844
- function requirePositiveInteger(value) {
1845
- if (typeof value !== "number" || !Number.isSafeInteger(value) || value < 1) throw new AccessGrantError();
1846
- return value;
1847
- }
1848
- function parseSyncAccess(value) {
1849
- if (!isRecord4(value)) throw new AccessGrantError();
1850
- return {
1851
- token: requireCredential(value.token, "chalk-sync"),
1852
- expiresAt: requireDateTime(value.expires_at ?? value.expiresAt)
1853
- };
1854
- }
1855
- function parseMediaAccess(value) {
1856
- if (!isRecord4(value) || value.provider !== "cloudflare_sfu" || !isRecord4(value.client_payload ?? value.clientPayload)) throw new AccessGrantError();
1857
- const payload = value.client_payload ?? value.clientPayload;
1858
- return {
1859
- token: requireCredential(value.token, "chalk-media"),
1860
- expiresAt: requireDateTime(value.expires_at ?? value.expiresAt),
1861
- provider: value.provider,
1862
- clientPayload: {
1863
- connectionId: requireNonEmptyString(payload.connectionId),
1864
- stunServer: requireNonEmptyString(payload.stunServer)
1865
- }
1866
- };
1867
- }
1868
- function requireCredential(value, audience) {
1869
- const token = requireNonEmptyString(value);
1870
- const segments = token.split(".");
1871
- if (segments.length !== 3) throw new AccessGrantError();
1872
- let payload;
1873
- try {
1874
- payload = JSON.parse(decodeBase64Url(segments[1] ?? ""));
1875
- } catch {
1876
- throw new AccessGrantError();
1877
- }
1878
- if (!isRecord4(payload) || payload.aud !== audience) throw new AccessGrantError();
1879
- return token;
1880
- }
1881
- function requireDateTime(value) {
1882
- const dateTime = requireNonEmptyString(value);
1883
- if (!Number.isFinite(Date.parse(dateTime))) throw new AccessGrantError();
1884
- return dateTime;
1885
- }
1886
- function requireNonEmptyString(value) {
1887
- if (typeof value !== "string" || value.trim().length === 0) throw new AccessGrantError();
1888
- return value;
1889
- }
1890
- function isRecord4(value) {
1891
- return typeof value === "object" && value !== null && !Array.isArray(value);
1892
- }
1893
-
1894
1782
  // src/connection/diagnostics.ts
1895
1783
  var ConnectionDiagnostics = class {
1896
1784
  #limit;
@@ -2346,7 +2234,8 @@ var makeConnectionLifecycleLayerFromServices = (options) => Layer3.effect(
2346
2234
  const sync = model.sync;
2347
2235
  if (!media || !sync) return yield* Effect2.fail(lifecycleFailure("invalid_state", false, "Media recovery requires active ports"));
2348
2236
  const grant = yield* access.refresh("media_recovery", true).pipe(Effect2.mapError(accessFailure));
2349
- yield* foreign6(() => media.restart(grant.media.clientPayload));
2237
+ const restartInput = grant.media.provider === "cloudflare_sfu" ? grant.media.clientPayload : grant.media;
2238
+ yield* foreign6(() => media.restart(restartInput));
2350
2239
  model.mediaSnapshot = media.getSnapshot();
2351
2240
  yield* waitForSyncLive(sync, boundedInteger(options.recovery?.budgetMs, RECOVERY_BUDGET_MS, 1, 6e4));
2352
2241
  });
@@ -4757,7 +4646,7 @@ function stripTrailingUrlSlash(value) {
4757
4646
  return value.endsWith("/") ? value.slice(0, -1) : value;
4758
4647
  }
4759
4648
  function intakeResponse(value) {
4760
- if (!isRecord5(value) || typeof value.diagnosticReference !== "string" || !Number.isSafeInteger(value.committedCursor)) return null;
4649
+ if (!isRecord3(value) || typeof value.diagnosticReference !== "string" || !Number.isSafeInteger(value.committedCursor)) return null;
4761
4650
  if (!Array.isArray(value.accepted) || !Array.isArray(value.duplicates) || !Array.isArray(value.conflicts)) return null;
4762
4651
  return { accepted: value.accepted, duplicates: value.duplicates, conflicts: value.conflicts };
4763
4652
  }
@@ -4768,14 +4657,14 @@ function completeDelivery(delivery, expected) {
4768
4657
  function intakeIds(items, expected, cursorRequired) {
4769
4658
  const ids = [];
4770
4659
  for (const item of items) {
4771
- if (!isRecord5(item) || typeof item.eventId !== "string" || !expected.has(item.eventId)) return null;
4660
+ if (!isRecord3(item) || typeof item.eventId !== "string" || !expected.has(item.eventId)) return null;
4772
4661
  if (cursorRequired && !Number.isSafeInteger(item.cursor)) return null;
4773
4662
  if (!cursorRequired && item.code !== "fingerprint_mismatch") return null;
4774
4663
  ids.push(item.eventId);
4775
4664
  }
4776
4665
  return ids;
4777
4666
  }
4778
- function isRecord5(value) {
4667
+ function isRecord3(value) {
4779
4668
  return typeof value === "object" && value !== null && !Array.isArray(value);
4780
4669
  }
4781
4670
 
@@ -4863,7 +4752,7 @@ var makeSpaceClientCoreLayer = (options, platform = {}) => {
4863
4752
  now: baseDependencies.clock.now,
4864
4753
  setTimeout: baseDependencies.clock.setTimeout,
4865
4754
  clearTimeout: baseDependencies.clock.clearTimeout,
4866
- release: { id: "chalk-client@4.1.5" }
4755
+ release: { id: "chalk-client@4.1.7" }
4867
4756
  });
4868
4757
  const diagnosticSyncClients = /* @__PURE__ */ new Set();
4869
4758
  const dependencies = {