@pulse-editor/react-api 0.1.1-beta.84 → 0.1.1-beta.85

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.
@@ -1,13 +1,4 @@
1
1
  import { OAuthConnectConfig } from "@pulse-editor/shared-utils";
2
- export type OAuthState = {
3
- accessToken?: string;
4
- refreshToken?: string;
5
- tokenType?: string;
6
- scope?: string;
7
- expiresAt?: string | number;
8
- idToken?: string;
9
- [key: string]: any;
10
- };
11
2
  /**
12
3
  * Hook to manage OAuth credentials for a Pulse App.
13
4
  *
@@ -23,14 +14,7 @@ export type OAuthState = {
23
14
  export default function useOAuth(appId: string, provider?: string): {
24
15
  isReady: boolean;
25
16
  isLoading: boolean;
26
- oauth: OAuthState | null;
27
17
  isAuthenticated: boolean;
28
18
  connect: (config: OAuthConnectConfig) => Promise<void>;
29
19
  disconnect: () => Promise<void>;
30
- refetchOAuth: () => Promise<void>;
31
- refreshToken: (params: {
32
- tokenEndpoint: string;
33
- clientId: string;
34
- clientSecret?: string;
35
- }) => Promise<OAuthState | null>;
36
20
  };
package/dist/main.d.ts CHANGED
@@ -14,11 +14,10 @@ import useVideoGen from "./hooks/ai-modality/use-video-gen";
14
14
  import useAppSettings from "./hooks/editor/use-app-settings";
15
15
  import { useArtifact } from "./hooks/editor/use-artifact";
16
16
  import useEditorEnv from "./hooks/editor/use-editor-env";
17
+ import useOAuth from "./hooks/editor/use-oauth";
17
18
  import useOpenApp from "./hooks/editor/use-open-app";
18
19
  import useOpenLink from "./hooks/editor/use-open-link";
19
20
  import useOwnedAppView from "./hooks/editor/use-owned-app-view";
20
- import useOAuth from "./hooks/editor/use-oauth";
21
- export type { OAuthState } from "./hooks/editor/use-oauth";
22
21
  import useSnapshotState from "./hooks/editor/use-snapshot-state";
23
22
  import { useTranslations } from "./hooks/editor/use-translations";
24
23
  import useFileSystem from "./hooks/workspace/use-file-system";
@@ -27,4 +26,4 @@ import useTerminal from "./hooks/workspace/use-terminal";
27
26
  import useWorkspaceInfo from "./hooks/workspace/use-workspace-info";
28
27
  import ReceiveFileProvider from "./providers/receive-file-provider";
29
28
  import SnapshotProvider from "./providers/snapshot-provider";
30
- export { ReceiveFileProvider, SnapshotProvider, useActionEffect, useAgents, useAgentTools, useAppSettings, useArtifact, useEditorEnv, useFile, useFileSystem, useImageGen, useLLM, useLoading, useNotification, useOCR, useOpenApp, useOpenLink, useOAuth, useOwnedAppView, useReceiveFile, useSnapshotState, useSTT, useTerminal, useTheme, useTranslations, useTTS, useVideoGen, useWorkspaceInfo, };
29
+ export { ReceiveFileProvider, SnapshotProvider, useActionEffect, useAgents, useAgentTools, useAppSettings, useArtifact, useEditorEnv, useFile, useFileSystem, useImageGen, useLLM, useLoading, useNotification, useOAuth, useOCR, useOpenApp, useOpenLink, useOwnedAppView, useReceiveFile, useSnapshotState, useSTT, useTerminal, useTheme, useTranslations, useTTS, useVideoGen, useWorkspaceInfo, };
package/dist/main.js CHANGED
@@ -1,4 +1,4 @@
1
- import { InterModuleCommunication, IMCMessageTypeEnum } from '@pulse-editor/shared-utils';
1
+ import { InterModuleCommunication, IMCMessageTypeEnum, OAuthStatusEnum } from '@pulse-editor/shared-utils';
2
2
  import React, { useState, useEffect, useRef, useMemo, useCallback, createContext, useContext } from 'react';
3
3
 
4
4
  var byteToHex = [];
@@ -6271,68 +6271,6 @@ function useEditorEnv() {
6271
6271
  };
6272
6272
  }
6273
6273
 
6274
- function useOpenApp() {
6275
- const receiverHandlerMap = new Map();
6276
- const { imc, isReady } = useIMC(receiverHandlerMap, "open-app");
6277
- async function openApp(appId, location, version) {
6278
- if (!isReady) {
6279
- throw new Error("IMC is not ready");
6280
- }
6281
- await imc?.sendMessage(IMCMessageTypeEnum.EditorOpenApp, {
6282
- appId,
6283
- version,
6284
- location,
6285
- });
6286
- }
6287
- return {
6288
- isReady,
6289
- openApp,
6290
- };
6291
- }
6292
-
6293
- function useOpenLink() {
6294
- const receiverHandlerMap = new Map();
6295
- const { imc, isReady } = useIMC(receiverHandlerMap, "open-link");
6296
- async function openLink(url) {
6297
- if (!isReady) {
6298
- throw new Error("IMC is not ready");
6299
- }
6300
- await imc?.sendMessage(IMCMessageTypeEnum.EditorOpenLink, {
6301
- url: url.toString(),
6302
- });
6303
- }
6304
- return {
6305
- isReady,
6306
- openLink,
6307
- };
6308
- }
6309
-
6310
- function useOwnedAppView() {
6311
- const receiverHandlerMap = new Map([]);
6312
- const { imc, isReady } = useIMC(receiverHandlerMap, "owned-app");
6313
- const runAppAction = useCallback(async (ownedAppViewModel, actionName, args) => {
6314
- if (isReady) {
6315
- const appViewId = ownedAppViewModel.viewId;
6316
- const skillActions = ownedAppViewModel.appConfig.actions || [];
6317
- const action = skillActions.find((a) => a.name === actionName);
6318
- if (!action) {
6319
- throw new Error(`Action ${actionName} not found in owned app ${ownedAppViewModel.appConfig.id}`);
6320
- }
6321
- const result = await imc?.sendMessage(IMCMessageTypeEnum.EditorAppUseOwnedApp, {
6322
- viewId: appViewId,
6323
- actionName,
6324
- args,
6325
- });
6326
- return result;
6327
- }
6328
- return undefined;
6329
- }, [imc, isReady]);
6330
- return {
6331
- isReady,
6332
- runAppAction,
6333
- };
6334
- }
6335
-
6336
6274
  function generateRandomString(length) {
6337
6275
  const array = new Uint8Array(length);
6338
6276
  crypto.getRandomValues(array);
@@ -6351,18 +6289,24 @@ function generateRandomString(length) {
6351
6289
  * @param provider A provider identifier used to namespace the OAuth state.
6352
6290
  */
6353
6291
  function useOAuth(appId, provider = "default") {
6354
- const { isReady, isLoaded, settings, deleteSetting, refetch } = useAppSettings(appId);
6355
- const keyPrefix = `oauth:${provider}:`;
6356
- const oauthEntries = Object.entries(settings).filter(([k]) => k.startsWith(keyPrefix));
6357
- const oauthRaw = oauthEntries.length > 0
6358
- ? Object.fromEntries(oauthEntries.map(([k, v]) => [k.slice(keyPrefix.length), v]))
6359
- : null;
6360
- const oauth = oauthRaw &&
6361
- Object.values(oauthRaw).some((v) => v !== null && v !== undefined)
6362
- ? oauthRaw
6363
- : null;
6292
+ const { isReady, isLoaded } = useAppSettings(appId);
6293
+ const [isAuthenticated, setIsAuthenticated] = useState(false);
6364
6294
  const receiverHandlerMap = new Map();
6365
6295
  const { imc, isReady: isIMCReady } = useIMC(receiverHandlerMap, "oauth");
6296
+ async function checkAuthStatus() {
6297
+ if (!isIMCReady)
6298
+ return;
6299
+ try {
6300
+ const status = await imc?.sendMessage(IMCMessageTypeEnum.EditorOAuthCheckStatus, { appId, provider });
6301
+ setIsAuthenticated(status === OAuthStatusEnum.Authenticated);
6302
+ }
6303
+ catch {
6304
+ setIsAuthenticated(false);
6305
+ }
6306
+ }
6307
+ useEffect(() => {
6308
+ checkAuthStatus();
6309
+ }, [isIMCReady]);
6366
6310
  /**
6367
6311
  * Initiate the OAuth flow. The editor handles everything:
6368
6312
  * - Dynamic client registration (if `registrationEndpoint` is provided and `clientId` is omitted)
@@ -6388,66 +6332,99 @@ function useOAuth(appId, provider = "default") {
6388
6332
  });
6389
6333
  }
6390
6334
  /**
6391
- * Sign out: removes all stored OAuth tokens for this provider from the
6392
- * editor backend and resets local auth state immediately.
6335
+ * Sign out: sends a disconnect request through the editor to remove
6336
+ * stored OAuth tokens on the backend for this provider.
6393
6337
  */
6394
6338
  async function disconnect() {
6395
- // Collect keys before deletion so we don't rely on stale `oauth`
6396
- const keysToDelete = oauthEntries.map(([k]) => k);
6397
- await Promise.all(keysToDelete.map((key) => deleteSetting(key)));
6398
- }
6399
- /**
6400
- * Re-fetch OAuth state from app settings.
6401
- * Call this after the user completes the OAuth flow in the external window.
6402
- */
6403
- async function refetchOAuth() {
6404
- await refetch();
6339
+ if (!isIMCReady) {
6340
+ throw new Error("IMC is not ready.");
6341
+ }
6342
+ await imc?.sendMessage(IMCMessageTypeEnum.EditorOAuthDisconnect, {
6343
+ appId,
6344
+ provider,
6345
+ });
6346
+ setIsAuthenticated(false);
6405
6347
  }
6406
- // Revalidate OAuth state when the user returns to the tab
6348
+ // Revalidate OAuth status when the user returns to the tab
6407
6349
  useEffect(() => {
6408
6350
  function handleVisibilityChange() {
6409
6351
  if (document.visibilityState === "visible") {
6410
- refetch();
6352
+ checkAuthStatus();
6411
6353
  }
6412
6354
  }
6413
6355
  document.addEventListener("visibilitychange", handleVisibilityChange);
6414
6356
  return () => {
6415
6357
  document.removeEventListener("visibilitychange", handleVisibilityChange);
6416
6358
  };
6417
- }, [isReady]);
6418
- /**
6419
- * Refresh the access token using the stored refresh token.
6420
- * The editor backend exchanges the refresh token with the OAuth provider
6421
- * and persists the new tokens automatically.
6422
- */
6423
- async function refreshToken(params) {
6424
- if (!isIMCReady) {
6425
- throw new Error("IMC is not ready.");
6426
- }
6427
- if (!oauth?.refreshToken) {
6428
- throw new Error("No refresh token available.");
6359
+ }, [isIMCReady]);
6360
+ return {
6361
+ isReady,
6362
+ isLoading: !isLoaded,
6363
+ isAuthenticated,
6364
+ connect,
6365
+ disconnect,
6366
+ };
6367
+ }
6368
+
6369
+ function useOpenApp() {
6370
+ const receiverHandlerMap = new Map();
6371
+ const { imc, isReady } = useIMC(receiverHandlerMap, "open-app");
6372
+ async function openApp(appId, location, version) {
6373
+ if (!isReady) {
6374
+ throw new Error("IMC is not ready");
6429
6375
  }
6430
- const result = await imc?.sendMessage(IMCMessageTypeEnum.EditorOAuthRefreshToken, {
6376
+ await imc?.sendMessage(IMCMessageTypeEnum.EditorOpenApp, {
6431
6377
  appId,
6432
- provider,
6433
- tokenEndpoint: params.tokenEndpoint,
6434
- refreshToken: oauth.refreshToken,
6435
- clientId: params.clientId,
6436
- clientSecret: params.clientSecret,
6378
+ version,
6379
+ location,
6437
6380
  });
6438
- // Re-fetch settings to sync local state
6439
- await refetchOAuth();
6440
- return result ?? null;
6441
6381
  }
6442
6382
  return {
6443
6383
  isReady,
6444
- isLoading: !isLoaded,
6445
- oauth,
6446
- isAuthenticated: Boolean(oauth?.accessToken),
6447
- connect,
6448
- disconnect,
6449
- refetchOAuth,
6450
- refreshToken,
6384
+ openApp,
6385
+ };
6386
+ }
6387
+
6388
+ function useOpenLink() {
6389
+ const receiverHandlerMap = new Map();
6390
+ const { imc, isReady } = useIMC(receiverHandlerMap, "open-link");
6391
+ async function openLink(url) {
6392
+ if (!isReady) {
6393
+ throw new Error("IMC is not ready");
6394
+ }
6395
+ await imc?.sendMessage(IMCMessageTypeEnum.EditorOpenLink, {
6396
+ url: url.toString(),
6397
+ });
6398
+ }
6399
+ return {
6400
+ isReady,
6401
+ openLink,
6402
+ };
6403
+ }
6404
+
6405
+ function useOwnedAppView() {
6406
+ const receiverHandlerMap = new Map([]);
6407
+ const { imc, isReady } = useIMC(receiverHandlerMap, "owned-app");
6408
+ const runAppAction = useCallback(async (ownedAppViewModel, actionName, args) => {
6409
+ if (isReady) {
6410
+ const appViewId = ownedAppViewModel.viewId;
6411
+ const skillActions = ownedAppViewModel.appConfig.actions || [];
6412
+ const action = skillActions.find((a) => a.name === actionName);
6413
+ if (!action) {
6414
+ throw new Error(`Action ${actionName} not found in owned app ${ownedAppViewModel.appConfig.id}`);
6415
+ }
6416
+ const result = await imc?.sendMessage(IMCMessageTypeEnum.EditorAppUseOwnedApp, {
6417
+ viewId: appViewId,
6418
+ actionName,
6419
+ args,
6420
+ });
6421
+ return result;
6422
+ }
6423
+ return undefined;
6424
+ }, [imc, isReady]);
6425
+ return {
6426
+ isReady,
6427
+ runAppAction,
6451
6428
  };
6452
6429
  }
6453
6430