Skip to content

Commit 39ae995

Browse files
committed
Library index view in VS code extension
1 parent 8668733 commit 39ae995

File tree

11 files changed

+574
-315
lines changed

11 files changed

+574
-315
lines changed

packages/client/package-lock.json

Lines changed: 191 additions & 57 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/client/package.json

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "polyapi",
3-
"version": "0.1.14",
3+
"version": "0.1.16",
44
"description": "Poly is a CLI tool to help you create and manage your Poly definitions.",
55
"license": "MIT",
66
"repository": {
@@ -31,26 +31,26 @@
3131
"postversion": "git push && git push --tags"
3232
},
3333
"devDependencies": {
34-
"@types/lodash": "^4.14.191",
34+
"@types/lodash": "^4.14.192",
3535
"copyfiles": "^2.4.1",
36-
"rimraf": "^4.1.2",
36+
"rimraf": "^4.4.1",
3737
"tslint": "^6.1.3",
3838
"tslint-config-prettier": "^1.18.0",
39-
"typescript": "^4.9.5"
39+
"typescript": "^5.0.2"
4040
},
4141
"dependencies": {
42-
"@guanghechen/helper-string": "^4.3.0",
43-
"axios": "^1.3.3",
44-
"chalk": "^4.1.2",
45-
"dotenv": "^16.0.3",
46-
"handlebars": "^4.7.7",
47-
"inquirer": "^8.2.5",
48-
"lodash": "^4.17.21",
49-
"prettier": "^2.8.4",
50-
"shelljs": "^0.8.5",
51-
"socket.io-client": "^4.6.1",
52-
"uuid": "^9.0.0",
53-
"yargs": "^17.7.0"
42+
"@guanghechen/helper-string": "4.7.1",
43+
"axios": "1.3.4",
44+
"chalk": "4.1.2",
45+
"dotenv": "16.0.3",
46+
"handlebars": "4.7.7",
47+
"inquirer": "8.2.5",
48+
"lodash": "4.17.21",
49+
"prettier": "2.8.7",
50+
"shelljs": "0.8.5",
51+
"socket.io-client": "4.6.1",
52+
"uuid": "9.0.0",
53+
"yargs": "17.7.1"
5454
},
5555
"engines": {
5656
"node": ">=18.0.0"

packages/client/src/commands/generate.ts

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,6 @@ const generateTSDeclarationFiles = async (
130130
webhookHandles: WebhookHandleDefinitionDto[],
131131
) => {
132132
const contextData = getContextData(functions, webhookHandles);
133-
const { default: defaultContext, ...otherContexts } = contextData;
134133
const contexts = await generateTSDeclarationFilesForContext(
135134
{
136135
name: '',
@@ -139,13 +138,11 @@ const generateTSDeclarationFiles = async (
139138
fileName: 'default.d.ts',
140139
level: 0,
141140
},
142-
{
143-
...otherContexts,
144-
...defaultContext,
145-
},
141+
contextData,
146142
);
147143

148144
await generateTSIndexDeclarationFile(contexts);
145+
await generateContextDataFile(contextData);
149146
};
150147

151148
const generateTSIndexDeclarationFile = async (contexts: Context[]) => {
@@ -204,20 +201,28 @@ const generateTSContextDeclarationFile = async (
204201
);
205202
};
206203

204+
const generateContextDataFile = async (contextData: Record<string, any>) => {
205+
fs.writeFileSync(`${POLY_LIB_PATH}/context-data.json`, JSON.stringify(contextData, null, 2));
206+
};
207+
207208
const getContextData = (functions: FunctionDefinitionDto[], webhookHandles: WebhookHandleDefinitionDto[]) => {
208209
const contextData = {} as Record<string, any>;
209210

210211
functions.forEach((func) => {
211-
const contextFunctionName = `${func.context || 'default'}.${func.name}`;
212-
set(contextData, contextFunctionName, {
212+
const path = func.context ? `${func.context}.${func.name}` : func.name;
213+
set(contextData, path, {
213214
...func,
214215
type: 'function',
215216
name: func.name.split('.').pop(),
217+
arguments: func.arguments.map((arg) => ({
218+
...arg,
219+
name: toCamelCase(arg.name),
220+
})),
216221
});
217222
});
218223
webhookHandles.forEach((handle) => {
219-
const contextFunctionName = `${handle.context || 'default'}.${handle.name}`;
220-
set(contextData, contextFunctionName, {
224+
const path = handle.context ? `${handle.context}.${handle.name}` : handle.name;
225+
set(contextData, path, {
221226
...handle,
222227
type: 'webhookHandle',
223228
name: handle.name.split('.').pop(),

packages/vscode-extension/CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
### 0.1.7
2+
* Added library index tree
3+
14
### 0.1.6
25
* Fixed issue with Poly not showing when no workspace is open
36
* Updated auto restart of TS server

packages/vscode-extension/package.json

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
"displayName": "Poly Assistant",
44
"description": "Poly AI assistant for VS Code",
55
"icon": "resources/poly-logo.png",
6-
"version": "0.1.6",
6+
"version": "0.1.7",
77
"publisher": "Poly API Corp",
88
"engines": {
99
"vscode": "^1.75.0"
@@ -32,7 +32,7 @@
3232
"commands": [
3333
{
3434
"command": "poly.copySelection",
35-
"title": "Copy"
35+
"title": "Copy selection to Poly"
3636
},
3737
{
3838
"command": "poly.focusMessageInput",
@@ -70,11 +70,28 @@
7070
"poly-view-container": [
7171
{
7272
"type": "webview",
73-
"id": "poly.chat-view",
74-
"name": "Chat"
73+
"id": "poly.ai-view",
74+
"name": "AI"
75+
},
76+
{
77+
"type": "tree",
78+
"id": "poly.library-index-view",
79+
"name": "Library",
80+
"when": "polyLibraryInstalled == true"
81+
},
82+
{
83+
"id": "poly.library-info",
84+
"name": "Library",
85+
"when": "polyLibraryInstalled == false"
7586
}
7687
]
7788
},
89+
"viewsWelcome": [
90+
{
91+
"view": "poly.library-info",
92+
"contents": "No Poly library present.\nTo install the Poly library:\n1. Open a terminal\n2. Run `npm install polyapi`\n3. Run `npx poly generate` to generate code.\n\nMore information about usage can be found in node_modules/polyapi/README.md after the installation."
93+
}
94+
],
7895
"keybindings": [
7996
{
8097
"command": "poly.focusMessageInput",
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import EventEmitter from 'events';
2+
3+
enum Events {
4+
polyDataChanged = 'poly-data-changed',
5+
}
6+
7+
const eventEmitter = new EventEmitter();
8+
9+
export const registerPolyDataChangedListener = (listener: (contextData: Record<string, any>) => any) => {
10+
eventEmitter.on(Events.polyDataChanged, listener);
11+
12+
return () => eventEmitter.off(Events.polyDataChanged, listener);
13+
};
14+
15+
export const polyDataChanged = (functions: Record<string, any>) => eventEmitter.emit(Events.polyDataChanged, functions);
Lines changed: 61 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,69 @@
11
import * as vscode from 'vscode';
2+
import * as ts from 'typescript';
23
import ChatViewProvider from './chat-view-provider';
4+
import LibraryIndexViewProvider from './library-index-view-provider';
35

4-
import { start as startFileWatcher } from './file-watcher';
6+
import { start as startLibraryWatcher } from './library-watcher';
7+
import { registerPolyDataChangedListener } from './events';
8+
9+
const isPolyExpression = (node: ts.Node) => {
10+
if (!node.parent) {
11+
return false;
12+
}
13+
if (node.kind === ts.SyntaxKind.Identifier && node.getText() === 'poly') {
14+
return true;
15+
}
16+
if (node.parent.kind === ts.SyntaxKind.PropertyAccessExpression) {
17+
const currentIndex = node.parent.getChildren().indexOf(node);
18+
if (currentIndex === 0) {
19+
return false;
20+
}
21+
return isPolyExpression(node.parent.getChildren()[currentIndex - 1]);
22+
}
23+
24+
return false;
25+
};
526

627
export async function activate(context: vscode.ExtensionContext) {
7-
const provider = new ChatViewProvider(context);
8-
9-
startFileWatcher();
10-
11-
context.subscriptions.push(vscode.commands.registerCommand('poly.focusMessageInput', () => {
12-
provider.focusMessageInput();
13-
}));
14-
context.subscriptions.push(vscode.commands.registerCommand('poly.copySelection', () => {
15-
vscode.commands.executeCommand('editor.action.clipboardCopyAction');
16-
}));
17-
context.subscriptions.push(vscode.window.registerWebviewViewProvider(
18-
'poly.chat-view',
19-
provider,
20-
{
21-
webviewOptions: {
22-
retainContextWhenHidden: true,
28+
const chatViewProvider = new ChatViewProvider(context);
29+
const libraryIndexViewProvider = new LibraryIndexViewProvider();
30+
31+
const unregisterPolyFunctionsRegeneratedListener = registerPolyDataChangedListener(contexData => {
32+
console.log('POLY: Restarting TS server...');
33+
vscode.commands.executeCommand('typescript.restartTsServer');
34+
35+
console.log('POLY: Regenerating index tree data...');
36+
libraryIndexViewProvider.refresh(contexData);
37+
});
38+
39+
const stopFileWatcher = startLibraryWatcher();
40+
41+
context.subscriptions.push(
42+
vscode.commands.registerCommand('poly.focusMessageInput', () => {
43+
chatViewProvider.focusMessageInput();
44+
}),
45+
vscode.commands.registerCommand('poly.copySelection', () => {
46+
vscode.commands.executeCommand('editor.action.clipboardCopyAction');
47+
}),
48+
vscode.commands.registerCommand('poly.copyLibraryItem', LibraryIndexViewProvider.copyLibraryItem),
49+
vscode.window.registerWebviewViewProvider(
50+
'poly.ai-view',
51+
chatViewProvider,
52+
{
53+
webviewOptions: {
54+
retainContextWhenHidden: true,
55+
},
2356
},
57+
),
58+
vscode.window.registerTreeDataProvider(
59+
'poly.library-index-view',
60+
libraryIndexViewProvider,
61+
),
62+
{
63+
dispose: unregisterPolyFunctionsRegeneratedListener,
64+
},
65+
{
66+
dispose: stopFileWatcher,
2467
},
25-
));
68+
);
2669
}
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
import * as vscode from 'vscode';
2+
import { ProviderResult, TreeItem } from 'vscode';
3+
4+
class LibraryTreeItem extends vscode.TreeItem {
5+
constructor(
6+
public readonly parentPath: string,
7+
public readonly data: any,
8+
public readonly label: string,
9+
public readonly collapsibleState: vscode.TreeItemCollapsibleState,
10+
) {
11+
super(label, collapsibleState);
12+
switch (data.type) {
13+
case 'function':
14+
this.tooltip = new vscode.MarkdownString(`**Function** \n${data.name}(${data.arguments.map(arg => `${arg.name}: ${arg.type}`).join(', ')})`);
15+
break;
16+
case 'webhookHandle':
17+
this.tooltip = new vscode.MarkdownString(`**Webhook listener** \n${data.name}()`);
18+
break;
19+
default:
20+
this.tooltip = new vscode.MarkdownString(`**Context** \n${label}`);
21+
break;
22+
}
23+
}
24+
}
25+
26+
export default class LibraryIndexViewProvider implements vscode.TreeDataProvider<LibraryTreeItem> {
27+
private contextData: Record<string, any> = {};
28+
29+
private _onDidChangeTreeData: vscode.EventEmitter<void> = new vscode.EventEmitter<void>();
30+
readonly onDidChangeTreeData: vscode.Event<void> = this._onDidChangeTreeData.event;
31+
32+
getChildren(parent?: LibraryTreeItem): ProviderResult<LibraryTreeItem[]> {
33+
const data = parent?.data || this.contextData;
34+
if (data.type) {
35+
return [];
36+
}
37+
38+
const parentPath = parent ? `${parent.parentPath}.${parent.label}` : 'poly';
39+
return Object.keys(data)
40+
.map(key => {
41+
const collapsibleState = data[key].type
42+
? vscode.TreeItemCollapsibleState.None
43+
: vscode.TreeItemCollapsibleState.Collapsed;
44+
45+
return new LibraryTreeItem(parentPath, data[key], key, collapsibleState);
46+
})
47+
.sort((a, b) => {
48+
if (a.data.type && !b.data.type) {
49+
return 1;
50+
} else if (b.data.type && !a.data.type) {
51+
return -1;
52+
}
53+
return a.label.localeCompare(b.label);
54+
});
55+
}
56+
57+
getTreeItem(element: LibraryTreeItem): TreeItem | Thenable<TreeItem> {
58+
if (element.data.type === 'function' || element.data.type === 'webhookHandle') {
59+
element.command = {
60+
title: 'Copy to clipboard',
61+
command: 'poly.copyLibraryItem',
62+
arguments: [element],
63+
};
64+
}
65+
return element;
66+
}
67+
68+
public refresh(contextData: Record<string, any>) {
69+
console.log('POLY: Refreshing index tree data...', contextData);
70+
this.contextData = contextData;
71+
this._onDidChangeTreeData.fire();
72+
}
73+
74+
static copyLibraryItem(item: LibraryTreeItem) {
75+
const { parentPath, data } = item;
76+
switch (data.type) {
77+
case 'function':
78+
vscode.env.clipboard.writeText(`await ${parentPath}.${data.name}(${data.arguments.map(arg => `${arg.name}`).join(', ')});`);
79+
break;
80+
case 'webhookHandle':
81+
vscode.env.clipboard.writeText(`${parentPath}.${data.name}(data => {\n\n});`);
82+
break;
83+
default:
84+
break;
85+
}
86+
}
87+
}

0 commit comments

Comments
 (0)