doe-sdk 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 (127) hide show
  1. package/README.md +509 -0
  2. package/dist/cli/index.d.ts +17 -0
  3. package/dist/cli/index.d.ts.map +1 -0
  4. package/dist/cli/index.js +118 -0
  5. package/dist/cli/index.js.map +1 -0
  6. package/dist/cli/init.d.ts +25 -0
  7. package/dist/cli/init.d.ts.map +1 -0
  8. package/dist/cli/init.js +100 -0
  9. package/dist/cli/init.js.map +1 -0
  10. package/dist/cli/login.d.ts +52 -0
  11. package/dist/cli/login.d.ts.map +1 -0
  12. package/dist/cli/login.js +571 -0
  13. package/dist/cli/login.js.map +1 -0
  14. package/dist/cli/publish.d.ts +27 -0
  15. package/dist/cli/publish.d.ts.map +1 -0
  16. package/dist/cli/publish.js +531 -0
  17. package/dist/cli/publish.js.map +1 -0
  18. package/dist/cli/scaffold.d.ts +18 -0
  19. package/dist/cli/scaffold.d.ts.map +1 -0
  20. package/dist/cli/scaffold.js +252 -0
  21. package/dist/cli/scaffold.js.map +1 -0
  22. package/dist/cli/ui.d.ts +57 -0
  23. package/dist/cli/ui.d.ts.map +1 -0
  24. package/dist/cli/ui.js +339 -0
  25. package/dist/cli/ui.js.map +1 -0
  26. package/dist/cli/validate.d.ts +28 -0
  27. package/dist/cli/validate.d.ts.map +1 -0
  28. package/dist/cli/validate.js +1270 -0
  29. package/dist/cli/validate.js.map +1 -0
  30. package/dist/compat/legacy-adapter.d.ts +198 -0
  31. package/dist/compat/legacy-adapter.d.ts.map +1 -0
  32. package/dist/compat/legacy-adapter.js +318 -0
  33. package/dist/compat/legacy-adapter.js.map +1 -0
  34. package/dist/index.d.ts +14 -0
  35. package/dist/index.d.ts.map +1 -0
  36. package/dist/index.js +16 -0
  37. package/dist/index.js.map +1 -0
  38. package/dist/runtime/client.d.ts +370 -0
  39. package/dist/runtime/client.d.ts.map +1 -0
  40. package/dist/runtime/client.js +470 -0
  41. package/dist/runtime/client.js.map +1 -0
  42. package/dist/runtime/index.d.ts +8 -0
  43. package/dist/runtime/index.d.ts.map +1 -0
  44. package/dist/runtime/index.js +7 -0
  45. package/dist/runtime/index.js.map +1 -0
  46. package/dist/types/api.d.ts +564 -0
  47. package/dist/types/api.d.ts.map +1 -0
  48. package/dist/types/api.js +11 -0
  49. package/dist/types/api.js.map +1 -0
  50. package/dist/types/index.d.ts +12 -0
  51. package/dist/types/index.d.ts.map +1 -0
  52. package/dist/types/index.js +10 -0
  53. package/dist/types/index.js.map +1 -0
  54. package/dist/types/manifest.d.ts +412 -0
  55. package/dist/types/manifest.d.ts.map +1 -0
  56. package/dist/types/manifest.js +42 -0
  57. package/dist/types/manifest.js.map +1 -0
  58. package/dist/types/marketplace-categories.d.ts +9 -0
  59. package/dist/types/marketplace-categories.d.ts.map +1 -0
  60. package/dist/types/marketplace-categories.js +16 -0
  61. package/dist/types/marketplace-categories.js.map +1 -0
  62. package/dist/types/permissions.d.ts +86 -0
  63. package/dist/types/permissions.d.ts.map +1 -0
  64. package/dist/types/permissions.js +295 -0
  65. package/dist/types/permissions.js.map +1 -0
  66. package/dist/types/theme/index.d.ts +7 -0
  67. package/dist/types/theme/index.d.ts.map +1 -0
  68. package/dist/types/theme/index.js +7 -0
  69. package/dist/types/theme/index.js.map +1 -0
  70. package/dist/types/theme/schema.d.ts +1205 -0
  71. package/dist/types/theme/schema.d.ts.map +1 -0
  72. package/dist/types/theme/schema.js +325 -0
  73. package/dist/types/theme/schema.js.map +1 -0
  74. package/dist/types/theme/types.d.ts +648 -0
  75. package/dist/types/theme/types.d.ts.map +1 -0
  76. package/dist/types/theme/types.js +8 -0
  77. package/dist/types/theme/types.js.map +1 -0
  78. package/package.json +75 -0
  79. package/templates/extension/README.md +254 -0
  80. package/templates/extension/icon.png +0 -0
  81. package/templates/extension/index.html +42 -0
  82. package/templates/extension/manifest.json +57 -0
  83. package/templates/extension/package.json +24 -0
  84. package/templates/extension/src/App.tsx +252 -0
  85. package/templates/extension/src/components/OnboardingComplete.tsx +190 -0
  86. package/templates/extension/src/components/OnboardingProgress.tsx +82 -0
  87. package/templates/extension/src/components/OnboardingWelcome.tsx +166 -0
  88. package/templates/extension/src/components/StepContainer.tsx +217 -0
  89. package/templates/extension/src/components/playground/CanvasTab.tsx +24 -0
  90. package/templates/extension/src/components/playground/ConfigTab.tsx +24 -0
  91. package/templates/extension/src/components/playground/EventsTab.tsx +24 -0
  92. package/templates/extension/src/components/playground/InfoTab.tsx +89 -0
  93. package/templates/extension/src/components/playground/NetworkTab.tsx +24 -0
  94. package/templates/extension/src/components/playground/PlaygroundContainer.tsx +184 -0
  95. package/templates/extension/src/components/playground/ResultDisplay.tsx +30 -0
  96. package/templates/extension/src/components/playground/StorageTab.tsx +24 -0
  97. package/templates/extension/src/components/playground/UITab.tsx +24 -0
  98. package/templates/extension/src/components/shared/CanvasControls.tsx +130 -0
  99. package/templates/extension/src/components/shared/ConfigControls.tsx +154 -0
  100. package/templates/extension/src/components/shared/EventsControls.tsx +232 -0
  101. package/templates/extension/src/components/shared/InfoControls.tsx +281 -0
  102. package/templates/extension/src/components/shared/NetworkControls.tsx +328 -0
  103. package/templates/extension/src/components/shared/StorageControls.tsx +203 -0
  104. package/templates/extension/src/components/shared/UIControls.tsx +199 -0
  105. package/templates/extension/src/components/shared/index.ts +15 -0
  106. package/templates/extension/src/components/steps/CanvasStep.tsx +67 -0
  107. package/templates/extension/src/components/steps/ClipboardStep.tsx +167 -0
  108. package/templates/extension/src/components/steps/ConfigStep.tsx +63 -0
  109. package/templates/extension/src/components/steps/EventsStep.tsx +69 -0
  110. package/templates/extension/src/components/steps/InfoStep.tsx +70 -0
  111. package/templates/extension/src/components/steps/NetworkStep.tsx +70 -0
  112. package/templates/extension/src/components/steps/StorageStep.tsx +61 -0
  113. package/templates/extension/src/components/steps/UIStep.tsx +70 -0
  114. package/templates/extension/src/hooks/useDoe.ts +93 -0
  115. package/templates/extension/src/hooks/useOnboarding.ts +264 -0
  116. package/templates/extension/src/hooks/usePointerHandlers.ts +105 -0
  117. package/templates/extension/src/main.tsx +18 -0
  118. package/templates/extension/src/styles.ts +265 -0
  119. package/templates/extension/tsconfig.json +28 -0
  120. package/templates/extension/vite.config.ts +32 -0
  121. package/templates/theme/README.md +132 -0
  122. package/templates/theme/manifest.json +19 -0
  123. package/templates/theme/package.json +16 -0
  124. package/templates/theme/styles/.gitkeep +2 -0
  125. package/templates/theme/themes/theme.json +32 -0
  126. package/templates/theme/vite-plugin-doe-theme.ts +53 -0
  127. package/templates/theme/vite.config.ts +10 -0
@@ -0,0 +1,63 @@
1
+ /**
2
+ * ConfigStep - Onboarding step demonstrating Config API
3
+ *
4
+ * Uses shared ConfigControls component for DRY code.
5
+ */
6
+ import React, { useState } from "react";
7
+ import type { DOEExtensionAPI } from "doe-sdk/runtime";
8
+ import { StepContainer } from "../StepContainer";
9
+ import { STEP_INFO } from "../../hooks/useOnboarding";
10
+ import { ConfigControls } from "../shared";
11
+
12
+ export interface ConfigStepProps {
13
+ api: DOEExtensionAPI;
14
+ stepNumber: number;
15
+ totalSteps: number;
16
+ onPrev: () => void;
17
+ onNext: () => void;
18
+ isLastStep?: boolean;
19
+ }
20
+
21
+ export function ConfigStep({
22
+ api,
23
+ stepNumber,
24
+ totalSteps,
25
+ onPrev,
26
+ onNext,
27
+ isLastStep,
28
+ }: ConfigStepProps): React.ReactElement {
29
+ const [result, setResult] = useState<string>("");
30
+
31
+ const { title, description, icon } = STEP_INFO.config;
32
+
33
+ const codeExample = `// Get a config value
34
+ const city = await api.config.get<string>("defaultCity");
35
+
36
+ // Set a config value
37
+ await api.config.set("defaultCity", "Tokyo");
38
+
39
+ // Open settings UI
40
+ await api.config.openSettings();
41
+
42
+ // Listen for config changes
43
+ api.events.onConfigChange(({ key, value }) => {
44
+ console.log(\`Config \${key} changed to \${value}\`);
45
+ });`;
46
+
47
+ return (
48
+ <StepContainer
49
+ title={title}
50
+ description={description}
51
+ icon={icon}
52
+ stepNumber={stepNumber}
53
+ totalSteps={totalSteps}
54
+ onPrev={onPrev}
55
+ onNext={onNext}
56
+ isLastStep={isLastStep}
57
+ codeExample={codeExample}
58
+ result={result}
59
+ >
60
+ <ConfigControls api={api} onResult={setResult} />
61
+ </StepContainer>
62
+ );
63
+ }
@@ -0,0 +1,69 @@
1
+ /**
2
+ * EventsStep - Onboarding step demonstrating Events API
3
+ *
4
+ * Uses shared EventsControls component for DRY code.
5
+ */
6
+ import React, { useState } from "react";
7
+ import type { DOEExtensionAPI } from "doe-sdk/runtime";
8
+ import { StepContainer } from "../StepContainer";
9
+ import { STEP_INFO } from "../../hooks/useOnboarding";
10
+ import { EventsControls } from "../shared";
11
+
12
+ export interface EventsStepProps {
13
+ api: DOEExtensionAPI;
14
+ stepNumber: number;
15
+ totalSteps: number;
16
+ onPrev: () => void;
17
+ onNext: () => void;
18
+ isLastStep?: boolean;
19
+ }
20
+
21
+ export function EventsStep({
22
+ api,
23
+ stepNumber,
24
+ totalSteps,
25
+ onPrev,
26
+ onNext,
27
+ isLastStep,
28
+ }: EventsStepProps): React.ReactElement {
29
+ const [result, setResult] = useState<string>("Listening for events...");
30
+
31
+ const { title, description, icon } = STEP_INFO.events;
32
+
33
+ const codeExample = `// Selection changes
34
+ const unsub1 = api.events.onSelectionChange((payload) => {
35
+ console.log("Selected shapes:", payload.shapeIds);
36
+ });
37
+
38
+ // Canvas changes (create, update, delete)
39
+ const unsub2 = api.events.onCanvasChange((payload) => {
40
+ console.log(\`\${payload.type}: \${payload.shapeIds.length} shapes\`);
41
+ });
42
+
43
+ // Theme changes
44
+ const unsub3 = api.events.onThemeChange((payload) => {
45
+ console.log("Theme changed to:", payload.mode);
46
+ });
47
+
48
+ // Clean up when done
49
+ unsub1();
50
+ unsub2();
51
+ unsub3();`;
52
+
53
+ return (
54
+ <StepContainer
55
+ title={title}
56
+ description={description}
57
+ icon={icon}
58
+ stepNumber={stepNumber}
59
+ totalSteps={totalSteps}
60
+ onPrev={onPrev}
61
+ onNext={onNext}
62
+ isLastStep={isLastStep}
63
+ codeExample={codeExample}
64
+ result={result}
65
+ >
66
+ <EventsControls api={api} onResult={setResult} />
67
+ </StepContainer>
68
+ );
69
+ }
@@ -0,0 +1,70 @@
1
+ /**
2
+ * InfoStep - Onboarding step demonstrating Workspace + Theme APIs
3
+ *
4
+ * Uses shared InfoControls component for DRY code.
5
+ */
6
+ import React, { useState } from "react";
7
+ import type { DOEExtensionAPI } from "doe-sdk/runtime";
8
+ import { StepContainer } from "../StepContainer";
9
+ import { STEP_INFO } from "../../hooks/useOnboarding";
10
+ import { InfoControls } from "../shared";
11
+
12
+ export interface InfoStepProps {
13
+ api: DOEExtensionAPI;
14
+ stepNumber: number;
15
+ totalSteps: number;
16
+ onPrev: () => void;
17
+ onNext: () => void;
18
+ isLastStep?: boolean;
19
+ }
20
+
21
+ export function InfoStep({
22
+ api,
23
+ stepNumber,
24
+ totalSteps,
25
+ onPrev,
26
+ onNext,
27
+ isLastStep,
28
+ }: InfoStepProps): React.ReactElement {
29
+ const [result, setResult] = useState<string>("");
30
+
31
+ const { title, description, icon } = STEP_INFO.info;
32
+
33
+ const codeExample = `// Get workspace information
34
+ const workspace = await api.workspace.getInfo();
35
+ console.log("Workspace:", workspace.name);
36
+
37
+ // Get current user
38
+ const user = await api.workspace.getCurrentUser();
39
+ if (user) {
40
+ console.log("User:", user.displayName);
41
+ console.log("Avatar:", user.avatarUrl);
42
+ }
43
+
44
+ // Get current theme
45
+ const theme = await api.ui.getTheme();
46
+ console.log("Theme mode:", theme.mode);
47
+ console.log("Colors:", theme.colors);
48
+
49
+ // Listen for theme changes
50
+ api.events.onThemeChange((payload) => {
51
+ console.log("Theme changed to:", payload.mode);
52
+ });`;
53
+
54
+ return (
55
+ <StepContainer
56
+ title={title}
57
+ description={description}
58
+ icon={icon}
59
+ stepNumber={stepNumber}
60
+ totalSteps={totalSteps}
61
+ onPrev={onPrev}
62
+ onNext={onNext}
63
+ isLastStep={isLastStep}
64
+ codeExample={codeExample}
65
+ result={result}
66
+ >
67
+ <InfoControls api={api} onResult={setResult} />
68
+ </StepContainer>
69
+ );
70
+ }
@@ -0,0 +1,70 @@
1
+ /**
2
+ * NetworkStep - Onboarding step demonstrating Network API
3
+ *
4
+ * Uses shared NetworkControls component for DRY code.
5
+ */
6
+ import React, { useState } from "react";
7
+ import type { DOEExtensionAPI } from "doe-sdk/runtime";
8
+ import { StepContainer } from "../StepContainer";
9
+ import { STEP_INFO } from "../../hooks/useOnboarding";
10
+ import { NetworkControls } from "../shared";
11
+
12
+ export interface NetworkStepProps {
13
+ api: DOEExtensionAPI;
14
+ stepNumber: number;
15
+ totalSteps: number;
16
+ onPrev: () => void;
17
+ onNext: () => void;
18
+ isLastStep?: boolean;
19
+ }
20
+
21
+ export function NetworkStep({
22
+ api,
23
+ stepNumber,
24
+ totalSteps,
25
+ onPrev,
26
+ onNext,
27
+ isLastStep,
28
+ }: NetworkStepProps): React.ReactElement {
29
+ const [result, setResult] = useState<string>("");
30
+
31
+ const { title, description, icon } = STEP_INFO.network;
32
+
33
+ const codeExample = `// Call any external API from your extension
34
+ // (add domains to hostPermissions in manifest.json)
35
+
36
+ // Example: Fetch from GitHub API
37
+ const response = await api.network.fetch(
38
+ "https://api.github.com/users/torvalds",
39
+ { timeout: 10000 }
40
+ );
41
+
42
+ if (response.ok) {
43
+ const user = await response.json();
44
+ console.log("Profile:", user.name);
45
+ console.log("Repos:", user.public_repos);
46
+ }
47
+
48
+ // Example: Fetch from any REST API
49
+ const jokes = await api.network.fetch(
50
+ "https://icanhazdadjoke.com/",
51
+ { headers: { Accept: "application/json" } }
52
+ );`;
53
+
54
+ return (
55
+ <StepContainer
56
+ title={title}
57
+ description={description}
58
+ icon={icon}
59
+ stepNumber={stepNumber}
60
+ totalSteps={totalSteps}
61
+ onPrev={onPrev}
62
+ onNext={onNext}
63
+ isLastStep={isLastStep}
64
+ codeExample={codeExample}
65
+ result={result}
66
+ >
67
+ <NetworkControls api={api} onResult={setResult} />
68
+ </StepContainer>
69
+ );
70
+ }
@@ -0,0 +1,61 @@
1
+ /**
2
+ * StorageStep - Onboarding step demonstrating Storage API
3
+ *
4
+ * Uses shared StorageControls component for DRY code.
5
+ */
6
+ import React, { useState } from "react";
7
+ import type { DOEExtensionAPI } from "doe-sdk/runtime";
8
+ import { StepContainer } from "../StepContainer";
9
+ import { STEP_INFO } from "../../hooks/useOnboarding";
10
+ import { StorageControls } from "../shared";
11
+
12
+ export interface StorageStepProps {
13
+ api: DOEExtensionAPI;
14
+ stepNumber: number;
15
+ totalSteps: number;
16
+ onPrev: () => void;
17
+ onNext: () => void;
18
+ isLastStep?: boolean;
19
+ }
20
+
21
+ export function StorageStep({
22
+ api,
23
+ stepNumber,
24
+ totalSteps,
25
+ onPrev,
26
+ onNext,
27
+ isLastStep,
28
+ }: StorageStepProps): React.ReactElement {
29
+ const [result, setResult] = useState<string>("");
30
+
31
+ const { title, description, icon } = STEP_INFO.storage;
32
+
33
+ const codeExample = `// Save a value
34
+ await api.storage.set("myKey", "myValue");
35
+
36
+ // Load a value
37
+ const value = await api.storage.get<string>("myKey");
38
+
39
+ // Delete a value
40
+ await api.storage.delete("myKey");
41
+
42
+ // List all keys
43
+ const keys = await api.storage.keys();`;
44
+
45
+ return (
46
+ <StepContainer
47
+ title={title}
48
+ description={description}
49
+ icon={icon}
50
+ stepNumber={stepNumber}
51
+ totalSteps={totalSteps}
52
+ onPrev={onPrev}
53
+ onNext={onNext}
54
+ isLastStep={isLastStep}
55
+ codeExample={codeExample}
56
+ result={result}
57
+ >
58
+ <StorageControls api={api} onResult={setResult} />
59
+ </StepContainer>
60
+ );
61
+ }
@@ -0,0 +1,70 @@
1
+ /**
2
+ * UIStep - Onboarding step demonstrating UI API
3
+ *
4
+ * Uses shared UIControls component for DRY code.
5
+ */
6
+ import React, { useState } from "react";
7
+ import type { DOEExtensionAPI } from "doe-sdk/runtime";
8
+ import { StepContainer } from "../StepContainer";
9
+ import { STEP_INFO } from "../../hooks/useOnboarding";
10
+ import { UIControls } from "../shared";
11
+
12
+ export interface UIStepProps {
13
+ api: DOEExtensionAPI;
14
+ stepNumber: number;
15
+ totalSteps: number;
16
+ onPrev: () => void;
17
+ onNext: () => void;
18
+ isLastStep?: boolean;
19
+ }
20
+
21
+ export function UIStep({
22
+ api,
23
+ stepNumber,
24
+ totalSteps,
25
+ onPrev,
26
+ onNext,
27
+ isLastStep,
28
+ }: UIStepProps): React.ReactElement {
29
+ const [result, setResult] = useState<string>("");
30
+
31
+ const { title, description, icon } = STEP_INFO.ui;
32
+
33
+ const codeExample = `// Show right-side panel
34
+ await api.ui.showPanel({ title: "My Panel", width: 400 });
35
+ await api.ui.hidePanel();
36
+
37
+ // Show centered modal dialog
38
+ await api.ui.showModal({ title: "My Modal", width: 500, height: 400 });
39
+ await api.ui.hideModal();
40
+
41
+ // Show toast notifications
42
+ await api.ui.showToast("Operation complete!", {
43
+ type: "success", // "info" | "success" | "warning" | "error"
44
+ duration: 3000, // milliseconds
45
+ });
46
+
47
+ // Show confirmation dialog
48
+ const confirmed = await api.ui.confirm("Delete this item?", {
49
+ title: "Confirm Delete",
50
+ confirmText: "Delete",
51
+ cancelText: "Keep",
52
+ });`;
53
+
54
+ return (
55
+ <StepContainer
56
+ title={title}
57
+ description={description}
58
+ icon={icon}
59
+ stepNumber={stepNumber}
60
+ totalSteps={totalSteps}
61
+ onPrev={onPrev}
62
+ onNext={onNext}
63
+ isLastStep={isLastStep}
64
+ codeExample={codeExample}
65
+ result={result}
66
+ >
67
+ <UIControls api={api} onResult={setResult} />
68
+ </StepContainer>
69
+ );
70
+ }
@@ -0,0 +1,93 @@
1
+ /**
2
+ * useDoe - React Hook for DOE Extension API
3
+ *
4
+ * Wraps the official SDK runtime initializer and provides
5
+ * React-friendly state (`isReady`, `error`) for extension apps.
6
+ */
7
+ import { useState, useEffect, useSyncExternalStore } from "react";
8
+ import {
9
+ initializeExtension,
10
+ type DOEExtensionAPI,
11
+ } from "doe-sdk/runtime";
12
+
13
+ // ============================================================================
14
+ // REACT INTEGRATION
15
+ // ============================================================================
16
+
17
+ let globalApi: DOEExtensionAPI | null = null;
18
+ let apiInitPromise: Promise<DOEExtensionAPI> | null = null;
19
+ let initError: Error | null = null;
20
+ const subscribers = new Set<() => void>();
21
+
22
+ // Cached snapshot for useSyncExternalStore (must be referentially stable)
23
+ let cachedSnapshot: { api: DOEExtensionAPI | null; error: Error | null } = { api: null, error: null };
24
+
25
+ function updateSnapshot(): void {
26
+ cachedSnapshot = { api: globalApi, error: initError };
27
+ }
28
+
29
+ function notifySubscribers(): void {
30
+ updateSnapshot();
31
+ for (const sub of subscribers) sub();
32
+ }
33
+
34
+ async function initializeApi(): Promise<DOEExtensionAPI> {
35
+ if (globalApi) return globalApi;
36
+ if (apiInitPromise) return apiInitPromise;
37
+
38
+ apiInitPromise = initializeExtension()
39
+ .then((api) => {
40
+ globalApi = api;
41
+ notifySubscribers();
42
+ return api;
43
+ })
44
+ .catch((error) => {
45
+ initError = error instanceof Error ? error : new Error(String(error));
46
+ notifySubscribers();
47
+ throw initError;
48
+ });
49
+
50
+ return apiInitPromise;
51
+ }
52
+
53
+ function getApiSnapshot() {
54
+ return cachedSnapshot;
55
+ }
56
+
57
+ function subscribeToApi(callback: () => void): () => void {
58
+ subscribers.add(callback);
59
+ return () => subscribers.delete(callback);
60
+ }
61
+
62
+ // ============================================================================
63
+ // HOOK
64
+ // ============================================================================
65
+
66
+ export interface UseDoeResult {
67
+ api: DOEExtensionAPI | null;
68
+ isReady: boolean;
69
+ error: Error | null;
70
+ }
71
+
72
+ export function useDoe(): UseDoeResult {
73
+ const [isInitializing, setIsInitializing] = useState(!globalApi);
74
+
75
+ const { api, error } = useSyncExternalStore(
76
+ subscribeToApi,
77
+ getApiSnapshot,
78
+ getApiSnapshot
79
+ );
80
+
81
+ useEffect(() => {
82
+ if (!globalApi && !apiInitPromise) {
83
+ setIsInitializing(true);
84
+ initializeApi().finally(() => setIsInitializing(false));
85
+ }
86
+ }, []);
87
+
88
+ return {
89
+ api,
90
+ isReady: api !== null && !isInitializing,
91
+ error,
92
+ };
93
+ }