@lvce-editor/api 9.37.2 → 9.38.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.
- package/README.md +31 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +2 -0
- package/dist/parts/AuthenticationProvider/AuthenticationProvider.d.ts +17 -0
- package/dist/parts/AuthenticationProvider/AuthenticationProvider.js +1 -0
- package/dist/parts/AuthenticationProviderRegistry/AuthenticationProviderRegistry.d.ts +9 -0
- package/dist/parts/AuthenticationProviderRegistry/AuthenticationProviderRegistry.js +98 -0
- package/dist/parts/AuthenticationProviderRegistrySnapshot/AuthenticationProviderRegistrySnapshot.d.ts +6 -0
- package/dist/parts/AuthenticationProviderRegistrySnapshot/AuthenticationProviderRegistrySnapshot.js +1 -0
- package/dist/parts/PrettyError/PrettyError.d.ts +7 -0
- package/dist/parts/PrettyError/PrettyError.js +35 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -67,3 +67,34 @@ const registration = registerPortProvider({
|
|
|
67
67
|
```
|
|
68
68
|
|
|
69
69
|
Ports queries matching extensions with the current workspace URI. Each extension may register one provider per scheme. Return an empty array when no ports are available, and dispose the registration when deactivating. The provider supplies addresses; the API does not create tunnels or change their visibility. Results from disposed registrations are discarded.
|
|
70
|
+
|
|
71
|
+
## Authentication providers
|
|
72
|
+
|
|
73
|
+
Extensions can contribute a functional authentication provider with session callbacks. The provider's stable `id` and display `label` identify it; requested scopes are passed to the callbacks, and session results include an account, access token, and granted scopes.
|
|
74
|
+
|
|
75
|
+
```ts
|
|
76
|
+
import { activate, registerAuthenticationProvider } from '@lvce-editor/api'
|
|
77
|
+
|
|
78
|
+
await activate()
|
|
79
|
+
const registration = registerAuthenticationProvider({
|
|
80
|
+
id: 'example',
|
|
81
|
+
label: 'Example Account',
|
|
82
|
+
async getSessions(scopes) {
|
|
83
|
+
return []
|
|
84
|
+
},
|
|
85
|
+
async createSession(scopes) {
|
|
86
|
+
return {
|
|
87
|
+
id: 'account-session',
|
|
88
|
+
accessToken: 'token',
|
|
89
|
+
account: { id: 'account', label: 'Example Account' },
|
|
90
|
+
scopes,
|
|
91
|
+
}
|
|
92
|
+
},
|
|
93
|
+
async removeSession(sessionId) {},
|
|
94
|
+
})
|
|
95
|
+
|
|
96
|
+
// Dispose the contribution when the extension deactivates.
|
|
97
|
+
registration.dispose()
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
The editor can call `executeAuthenticationProviderGetSessions`, `executeAuthenticationProviderCreateSession`, and `executeAuthenticationProviderRemoveSession` by provider id. Session callbacks are responsible for account selection, consent, token storage, and revocation.
|
package/dist/index.d.ts
CHANGED
|
@@ -2,6 +2,9 @@ export { activate } from './parts/Activation/Activation.ts';
|
|
|
2
2
|
export { getColorThemeNames } from './parts/ColorTheme/ColorTheme.ts';
|
|
3
3
|
export { markdownToVirtualDom } from './parts/Markdown/Markdown.ts';
|
|
4
4
|
export { getAccessToken, type GetAccessTokenOptions } from './parts/Authentication/Authentication.ts';
|
|
5
|
+
export { executeAuthenticationProviderCreateSession, executeAuthenticationProviderGetSessions, executeAuthenticationProviderRemoveSession, getAuthenticationProviderRegistrySnapshot, registerAuthenticationProvider, resetAuthenticationProviderRegistry, } from './parts/AuthenticationProviderRegistry/AuthenticationProviderRegistry.ts';
|
|
6
|
+
export type { AuthenticationAccount, AuthenticationProvider, AuthenticationSession } from './parts/AuthenticationProvider/AuthenticationProvider.ts';
|
|
7
|
+
export type { AuthenticationProviderRegistrySnapshot } from './parts/AuthenticationProviderRegistrySnapshot/AuthenticationProviderRegistrySnapshot.ts';
|
|
5
8
|
export { createElectronWebContentsView } from './parts/ElectronWebContentsView/ElectronWebContentsView.ts';
|
|
6
9
|
export { executeCommand } from './parts/ExecuteCommand/ExecuteCommand.ts';
|
|
7
10
|
export { showFileQuickPick, showQuickInput, showQuickPick } from './parts/QuickPick/QuickPick.ts';
|
|
@@ -19,6 +22,7 @@ export { exists, getFileHash, getFileHashes, mkdir, readAsObjectUrl, readDirWith
|
|
|
19
22
|
export { registerFileChangeHandler, type FileChangeHandler, type FileChanges } from './parts/FileChangeHandler/FileChangeHandler.ts';
|
|
20
23
|
export { executeFileSystemProviderGetOpenExternalPath, executeFileSystemProviderIsReadonly, executeFileSystemProviderMkdir, executeFileSystemProviderReadDirWithFileTypes, executeFileSystemProviderReadFile, executeFileSystemProviderRemove, executeFileSystemProviderRename, executeFileSystemProviderWriteFile, getFileSystemProviderRegistrySnapshot, registerFileSystemProvider, resetFileSystemProviderRegistry, } from './parts/FileSystemProviderRegistry/FileSystemProviderRegistry.ts';
|
|
21
24
|
export { closeUri, confirm, getRecentlyOpenedWorkspaceUris, getWorkspaceFolder, getWorkspaceUri, handleWorkspaceRefresh, openUri, setWorkspaceUri, showErrorMessage, showNotification, type ConfirmOptions, type NotificationType, type ShowErrorMessageOptions, } from './parts/Host/Host.ts';
|
|
25
|
+
export { preparePrettyError } from './parts/PrettyError/PrettyError.ts';
|
|
22
26
|
export { executeHoverProvider, getHoverProviderRegistrySnapshot, registerHoverProvider, resetHoverProviderRegistry } from './parts/Hover/Hover.ts';
|
|
23
27
|
export { executeSignatureHelpProvider, getSignatureHelpProviderRegistrySnapshot, registerSignatureHelpProvider, resetSignatureHelpProviderRegistry, } from './parts/SignatureHelp/SignatureHelp.ts';
|
|
24
28
|
export { getPlatform, getUserDataDir, type Platform } from './parts/Platform/Platform.ts';
|
package/dist/index.js
CHANGED
|
@@ -2,6 +2,7 @@ export { activate } from "./parts/Activation/Activation.js";
|
|
|
2
2
|
export { getColorThemeNames } from "./parts/ColorTheme/ColorTheme.js";
|
|
3
3
|
export { markdownToVirtualDom } from "./parts/Markdown/Markdown.js";
|
|
4
4
|
export { getAccessToken } from "./parts/Authentication/Authentication.js";
|
|
5
|
+
export { executeAuthenticationProviderCreateSession, executeAuthenticationProviderGetSessions, executeAuthenticationProviderRemoveSession, getAuthenticationProviderRegistrySnapshot, registerAuthenticationProvider, resetAuthenticationProviderRegistry, } from "./parts/AuthenticationProviderRegistry/AuthenticationProviderRegistry.js";
|
|
5
6
|
export { createElectronWebContentsView } from "./parts/ElectronWebContentsView/ElectronWebContentsView.js";
|
|
6
7
|
export { executeCommand } from "./parts/ExecuteCommand/ExecuteCommand.js";
|
|
7
8
|
export { showFileQuickPick, showQuickInput, showQuickPick } from "./parts/QuickPick/QuickPick.js";
|
|
@@ -19,6 +20,7 @@ export { exists, getFileHash, getFileHashes, mkdir, readAsObjectUrl, readDirWith
|
|
|
19
20
|
export { registerFileChangeHandler } from "./parts/FileChangeHandler/FileChangeHandler.js";
|
|
20
21
|
export { executeFileSystemProviderGetOpenExternalPath, executeFileSystemProviderIsReadonly, executeFileSystemProviderMkdir, executeFileSystemProviderReadDirWithFileTypes, executeFileSystemProviderReadFile, executeFileSystemProviderRemove, executeFileSystemProviderRename, executeFileSystemProviderWriteFile, getFileSystemProviderRegistrySnapshot, registerFileSystemProvider, resetFileSystemProviderRegistry, } from "./parts/FileSystemProviderRegistry/FileSystemProviderRegistry.js";
|
|
21
22
|
export { closeUri, confirm, getRecentlyOpenedWorkspaceUris, getWorkspaceFolder, getWorkspaceUri, handleWorkspaceRefresh, openUri, setWorkspaceUri, showErrorMessage, showNotification, } from "./parts/Host/Host.js";
|
|
23
|
+
export { preparePrettyError } from "./parts/PrettyError/PrettyError.js";
|
|
22
24
|
export { executeHoverProvider, getHoverProviderRegistrySnapshot, registerHoverProvider, resetHoverProviderRegistry } from "./parts/Hover/Hover.js";
|
|
23
25
|
export { executeSignatureHelpProvider, getSignatureHelpProviderRegistrySnapshot, registerSignatureHelpProvider, resetSignatureHelpProviderRegistry, } from "./parts/SignatureHelp/SignatureHelp.js";
|
|
24
26
|
export { getPlatform, getUserDataDir } from "./parts/Platform/Platform.js";
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export interface AuthenticationAccount {
|
|
2
|
+
readonly id: string;
|
|
3
|
+
readonly label: string;
|
|
4
|
+
}
|
|
5
|
+
export interface AuthenticationSession {
|
|
6
|
+
readonly accessToken: string;
|
|
7
|
+
readonly account: AuthenticationAccount;
|
|
8
|
+
readonly id: string;
|
|
9
|
+
readonly scopes: readonly string[];
|
|
10
|
+
}
|
|
11
|
+
export interface AuthenticationProvider {
|
|
12
|
+
readonly createSession: (scopes: readonly string[]) => Promise<AuthenticationSession> | AuthenticationSession;
|
|
13
|
+
readonly getSessions: (scopes: readonly string[]) => Promise<readonly AuthenticationSession[]> | readonly AuthenticationSession[];
|
|
14
|
+
readonly id: string;
|
|
15
|
+
readonly label: string;
|
|
16
|
+
readonly removeSession: (sessionId: string) => Promise<void> | void;
|
|
17
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { AuthenticationProvider, AuthenticationSession } from '../AuthenticationProvider/AuthenticationProvider.ts';
|
|
2
|
+
import type { AuthenticationProviderRegistrySnapshot } from '../AuthenticationProviderRegistrySnapshot/AuthenticationProviderRegistrySnapshot.ts';
|
|
3
|
+
import type { Disposable } from '../Disposable/Disposable.ts';
|
|
4
|
+
export declare const registerAuthenticationProvider: (provider: AuthenticationProvider) => Disposable;
|
|
5
|
+
export declare const executeAuthenticationProviderGetSessions: (providerId: string, scopes: readonly string[]) => Promise<readonly AuthenticationSession[]>;
|
|
6
|
+
export declare const executeAuthenticationProviderCreateSession: (providerId: string, scopes: readonly string[]) => Promise<AuthenticationSession>;
|
|
7
|
+
export declare const executeAuthenticationProviderRemoveSession: (providerId: string, sessionId: string) => Promise<void>;
|
|
8
|
+
export declare const getAuthenticationProviderRegistrySnapshot: () => AuthenticationProviderRegistrySnapshot;
|
|
9
|
+
export declare const resetAuthenticationProviderRegistry: () => void;
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import * as ExtensionApiCommandRegistry from "../ExtensionApiCommandRegistry/ExtensionApiCommandRegistry.js";
|
|
2
|
+
import { ExtensionApiError } from "../ExtensionApiError/ExtensionApiError.js";
|
|
3
|
+
const providers = Object.create(null);
|
|
4
|
+
const assertSession = (session, providerId) => {
|
|
5
|
+
if (!session || typeof session !== 'object') {
|
|
6
|
+
throw new ExtensionApiError(`authentication provider ${providerId} returned an invalid session`);
|
|
7
|
+
}
|
|
8
|
+
const value = session;
|
|
9
|
+
if (typeof value.id !== 'string' || value.id.length === 0) {
|
|
10
|
+
throw new ExtensionApiError(`authentication provider ${providerId} returned a session without an id`);
|
|
11
|
+
}
|
|
12
|
+
if (typeof value.accessToken !== 'string' || value.accessToken.length === 0) {
|
|
13
|
+
throw new ExtensionApiError(`authentication provider ${providerId} returned a session without an access token`);
|
|
14
|
+
}
|
|
15
|
+
if (!Array.isArray(value.scopes) || value.scopes.some((scope) => typeof scope !== 'string' || scope.length === 0)) {
|
|
16
|
+
throw new ExtensionApiError(`authentication provider ${providerId} returned a session with invalid scopes`);
|
|
17
|
+
}
|
|
18
|
+
if (!value.account || typeof value.account !== 'object') {
|
|
19
|
+
throw new ExtensionApiError(`authentication provider ${providerId} returned a session without an account`);
|
|
20
|
+
}
|
|
21
|
+
const account = value.account;
|
|
22
|
+
if (typeof account.id !== 'string' || account.id.length === 0 || typeof account.label !== 'string' || account.label.length === 0) {
|
|
23
|
+
throw new ExtensionApiError(`authentication provider ${providerId} returned a session with an invalid account`);
|
|
24
|
+
}
|
|
25
|
+
return session;
|
|
26
|
+
};
|
|
27
|
+
const assertScopes = (scopes) => {
|
|
28
|
+
if (!Array.isArray(scopes) || scopes.some((scope) => !(typeof scope === 'string' && scope.length > 0))) {
|
|
29
|
+
throw new ExtensionApiError('authentication scopes must be an array of non-empty strings');
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
const getProvider = (providerId) => {
|
|
33
|
+
const provider = providers[providerId];
|
|
34
|
+
if (!provider) {
|
|
35
|
+
throw new ExtensionApiError(`authentication provider ${providerId} not found`);
|
|
36
|
+
}
|
|
37
|
+
return provider;
|
|
38
|
+
};
|
|
39
|
+
export const registerAuthenticationProvider = (provider) => {
|
|
40
|
+
if (!provider) {
|
|
41
|
+
throw new ExtensionApiError('authentication provider is not defined');
|
|
42
|
+
}
|
|
43
|
+
const providerRecord = provider;
|
|
44
|
+
if (typeof providerRecord.id !== 'string' || providerRecord.id.length === 0) {
|
|
45
|
+
throw new ExtensionApiError('authentication provider is missing id');
|
|
46
|
+
}
|
|
47
|
+
const { id } = provider;
|
|
48
|
+
if (typeof providerRecord.label !== 'string' || providerRecord.label.length === 0) {
|
|
49
|
+
throw new ExtensionApiError(`authentication provider ${id} is missing label`);
|
|
50
|
+
}
|
|
51
|
+
for (const methodName of ['getSessions', 'createSession', 'removeSession']) {
|
|
52
|
+
if (typeof providerRecord[methodName] !== 'function') {
|
|
53
|
+
throw new ExtensionApiError(`authentication provider ${id} is missing ${methodName} function`);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
if (id in providers) {
|
|
57
|
+
throw new ExtensionApiError(`authentication provider ${id} is already registered`);
|
|
58
|
+
}
|
|
59
|
+
providers[id] = provider;
|
|
60
|
+
ExtensionApiCommandRegistry.registerCommandMap(commandMap);
|
|
61
|
+
return {
|
|
62
|
+
dispose() {
|
|
63
|
+
delete providers[id];
|
|
64
|
+
},
|
|
65
|
+
};
|
|
66
|
+
};
|
|
67
|
+
export const executeAuthenticationProviderGetSessions = async (providerId, scopes) => {
|
|
68
|
+
assertScopes(scopes);
|
|
69
|
+
const sessions = await getProvider(providerId).getSessions(scopes);
|
|
70
|
+
if (!Array.isArray(sessions)) {
|
|
71
|
+
throw new ExtensionApiError(`authentication provider ${providerId} returned invalid sessions`);
|
|
72
|
+
}
|
|
73
|
+
return sessions.map((session) => assertSession(session, providerId));
|
|
74
|
+
};
|
|
75
|
+
export const executeAuthenticationProviderCreateSession = async (providerId, scopes) => {
|
|
76
|
+
assertScopes(scopes);
|
|
77
|
+
return assertSession(await getProvider(providerId).createSession(scopes), providerId);
|
|
78
|
+
};
|
|
79
|
+
export const executeAuthenticationProviderRemoveSession = async (providerId, sessionId) => {
|
|
80
|
+
if (typeof sessionId !== 'string' || sessionId.length === 0) {
|
|
81
|
+
throw new ExtensionApiError('authentication session id is missing');
|
|
82
|
+
}
|
|
83
|
+
await getProvider(providerId).removeSession(sessionId);
|
|
84
|
+
};
|
|
85
|
+
export const getAuthenticationProviderRegistrySnapshot = () => ({
|
|
86
|
+
providers: Object.values(providers).map(({ id, label }) => ({ id, label })),
|
|
87
|
+
});
|
|
88
|
+
export const resetAuthenticationProviderRegistry = () => {
|
|
89
|
+
for (const id of Object.keys(providers)) {
|
|
90
|
+
delete providers[id];
|
|
91
|
+
}
|
|
92
|
+
};
|
|
93
|
+
const commandMap = {
|
|
94
|
+
'ExtensionApi.executeAuthenticationProviderCreateSession': executeAuthenticationProviderCreateSession,
|
|
95
|
+
'ExtensionApi.executeAuthenticationProviderGetSessions': executeAuthenticationProviderGetSessions,
|
|
96
|
+
'ExtensionApi.executeAuthenticationProviderRemoveSession': executeAuthenticationProviderRemoveSession,
|
|
97
|
+
'ExtensionApi.getAuthenticationProviderRegistrySnapshot': getAuthenticationProviderRegistrySnapshot,
|
|
98
|
+
};
|
package/dist/parts/AuthenticationProviderRegistrySnapshot/AuthenticationProviderRegistrySnapshot.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { executeCommand } from "../ExecuteCommand/ExecuteCommand.js";
|
|
2
|
+
const serializeError = (error) => {
|
|
3
|
+
if (error instanceof Error) {
|
|
4
|
+
return {
|
|
5
|
+
code: error.code,
|
|
6
|
+
codeFrame: error.codeFrame,
|
|
7
|
+
constructor: { name: error.constructor.name },
|
|
8
|
+
message: error.message,
|
|
9
|
+
name: error.name,
|
|
10
|
+
stack: error.stack,
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
if (error && typeof error === 'object') {
|
|
14
|
+
const value = error;
|
|
15
|
+
const constructorName = Object.hasOwn(value, 'constructor') ? value.constructor?.name : undefined;
|
|
16
|
+
return {
|
|
17
|
+
code: value.code,
|
|
18
|
+
codeFrame: value.codeFrame,
|
|
19
|
+
constructor: constructorName ? { name: constructorName } : undefined,
|
|
20
|
+
message: value.message || value.errorMessage,
|
|
21
|
+
name: value.name || constructorName,
|
|
22
|
+
stack: value.stack || value.errorStack,
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
return { message: String(error) };
|
|
26
|
+
};
|
|
27
|
+
export const preparePrettyError = async (error) => {
|
|
28
|
+
const serialized = serializeError(error);
|
|
29
|
+
try {
|
|
30
|
+
return (await executeCommand('ErrorHandling.preparePrettyError', serialized));
|
|
31
|
+
}
|
|
32
|
+
catch {
|
|
33
|
+
return serialized;
|
|
34
|
+
}
|
|
35
|
+
};
|