@notionhq/apps 0.0.12 → 0.0.14
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 +32 -0
- package/dist/box.generated.d.ts +164 -0
- package/dist/box.generated.d.ts.map +1 -0
- package/dist/box.generated.js +24 -0
- package/dist/calendar.generated.d.ts +1036 -0
- package/dist/calendar.generated.d.ts.map +1 -0
- package/dist/calendar.generated.js +42 -0
- package/dist/cli/build.d.ts.map +1 -1
- package/dist/cli/build.js +41 -10
- package/dist/cli/codegen.d.ts +2 -0
- package/dist/cli/codegen.d.ts.map +1 -1
- package/dist/cli/codegen.js +13 -2
- package/dist/cli/discover.d.ts +2 -0
- package/dist/cli/discover.d.ts.map +1 -1
- package/dist/cli/discover.js +4 -2
- package/dist/cli/emit-manifest.d.ts +3 -1
- package/dist/cli/emit-manifest.d.ts.map +1 -1
- package/dist/cli/emit-manifest.js +10 -4
- package/dist/cli/index.js +33 -1
- package/dist/confluence.generated.d.ts +98 -0
- package/dist/confluence.generated.d.ts.map +1 -0
- package/dist/confluence.generated.js +18 -0
- package/dist/connection-actions.d.ts +2 -0
- package/dist/connection-actions.d.ts.map +1 -0
- package/dist/connection-actions.js +0 -0
- package/dist/connection-trigger-definitions.generated.d.ts +34 -0
- package/dist/connection-trigger-definitions.generated.d.ts.map +1 -0
- package/dist/connection-trigger-definitions.generated.js +45 -0
- package/dist/connections.d.ts +15 -0
- package/dist/connections.d.ts.map +1 -0
- package/dist/connections.js +79 -0
- package/dist/connections.test.d.ts +2 -0
- package/dist/connections.test.d.ts.map +1 -0
- package/dist/cursor.generated.d.ts +154 -0
- package/dist/cursor.generated.d.ts.map +1 -0
- package/dist/cursor.generated.js +18 -0
- package/dist/custom-block.d.ts +54 -0
- package/dist/custom-block.d.ts.map +1 -0
- package/dist/custom-block.js +30 -0
- package/dist/custom-block.test.d.ts +2 -0
- package/dist/custom-block.test.d.ts.map +1 -0
- package/dist/custom-blocks.d.ts +2 -0
- package/dist/custom-blocks.d.ts.map +1 -0
- package/dist/custom-blocks.js +1 -0
- package/dist/discord.generated.d.ts +279 -0
- package/dist/discord.generated.d.ts.map +1 -0
- package/dist/discord.generated.js +33 -0
- package/dist/gmail.generated.d.ts +184 -0
- package/dist/gmail.generated.d.ts.map +1 -0
- package/dist/gmail.generated.js +21 -0
- package/dist/googleCalendar.generated.d.ts +83 -0
- package/dist/googleCalendar.generated.d.ts.map +1 -0
- package/dist/googleCalendar.generated.js +15 -0
- package/dist/googleDrive.generated.d.ts +210 -0
- package/dist/googleDrive.generated.d.ts.map +1 -0
- package/dist/googleDrive.generated.js +27 -0
- package/dist/googleDriveOauth.generated.d.ts +851 -0
- package/dist/googleDriveOauth.generated.d.ts.map +1 -0
- package/dist/googleDriveOauth.generated.js +84 -0
- package/dist/manifest.d.ts +1 -1
- package/dist/manifest.d.ts.map +1 -1
- package/dist/nds.css +1 -0
- package/dist/notion-as-code/database.d.ts +4 -3
- package/dist/notion-as-code/database.d.ts.map +1 -1
- package/dist/notion-as-code/database.js +11 -2
- package/dist/notion-as-code/intents.d.ts +4 -1
- package/dist/notion-as-code/intents.d.ts.map +1 -1
- package/dist/notion-as-code/page.d.ts +4 -4
- package/dist/notion-as-code/page.d.ts.map +1 -1
- package/dist/notion-as-code/page.js +11 -2
- package/dist/outlook.generated.d.ts +224 -0
- package/dist/outlook.generated.d.ts.map +1 -0
- package/dist/outlook.generated.js +24 -0
- package/dist/providers.generated.d.ts +117 -0
- package/dist/providers.generated.d.ts.map +1 -0
- package/dist/providers.generated.js +108 -0
- package/dist/react.d.ts +2 -0
- package/dist/react.d.ts.map +1 -0
- package/dist/react.js +1 -0
- package/dist/salesforce.generated.d.ts +151 -0
- package/dist/salesforce.generated.d.ts.map +1 -0
- package/dist/salesforce.generated.js +24 -0
- package/dist/slack.generated.d.ts +290 -0
- package/dist/slack.generated.d.ts.map +1 -0
- package/dist/slack.generated.js +30 -0
- package/dist/triggers.generated.d.ts +107 -32
- package/dist/triggers.generated.d.ts.map +1 -1
- package/dist/triggers.generated.js +36 -24
- package/dist/workflow-connections-types.test.d.ts +2 -0
- package/dist/workflow-connections-types.test.d.ts.map +1 -0
- package/dist/workflow-types.test.d.ts +2 -0
- package/dist/workflow-types.test.d.ts.map +1 -0
- package/dist/workflow.d.ts +20 -16
- package/dist/workflow.d.ts.map +1 -1
- package/dist/workflow.js +14 -17
- package/docs/BUILD.md +83 -14
- package/docs/CONNECTIONS.md +129 -0
- package/package.json +16 -2
- package/src/box.generated.ts +187 -0
- package/src/calendar.generated.ts +1117 -0
- package/src/cli/build.test.ts +87 -0
- package/src/cli/build.ts +47 -9
- package/src/cli/codegen.test.ts +2 -0
- package/src/cli/codegen.ts +25 -7
- package/src/cli/discover.test.ts +12 -0
- package/src/cli/discover.ts +6 -2
- package/src/cli/emit-manifest.ts +13 -3
- package/src/cli/index.ts +33 -1
- package/src/confluence.generated.ts +109 -0
- package/src/connection-actions.ts +2 -0
- package/src/connection-trigger-definitions.generated.ts +48 -0
- package/src/connections.test.ts +157 -0
- package/src/connections.ts +126 -0
- package/src/cursor.generated.ts +167 -0
- package/src/custom-block.test.ts +19 -0
- package/src/custom-block.ts +41 -0
- package/src/custom-blocks.ts +1 -0
- package/src/discord.generated.ts +318 -0
- package/src/gmail.generated.ts +205 -0
- package/src/googleCalendar.generated.ts +95 -0
- package/src/googleDrive.generated.ts +235 -0
- package/src/googleDriveOauth.generated.ts +980 -0
- package/src/manifest.ts +1 -1
- package/src/nds.css +1 -0
- package/src/notion-as-code/database.ts +19 -11
- package/src/notion-as-code/intents.ts +2 -1
- package/src/notion-as-code/page.ts +17 -11
- package/src/outlook.generated.ts +249 -0
- package/src/providers.generated.ts +207 -0
- package/src/react.ts +1 -0
- package/src/salesforce.generated.ts +170 -0
- package/src/slack.generated.ts +330 -0
- package/src/triggers.generated.ts +112 -32
- package/src/workflow-connections-types.test.ts +59 -0
- package/src/workflow-types.test.ts +144 -0
- package/src/workflow.test.ts +112 -2
- package/src/workflow.ts +58 -29
package/README.md
CHANGED
|
@@ -74,6 +74,26 @@ Put each default-exported sync directly in `src/syncs/`. A primary key must be a
|
|
|
74
74
|
or rich-text property. Do not include that property in an upsert: the SDK fills it from
|
|
75
75
|
the change's `key`.
|
|
76
76
|
|
|
77
|
+
## Custom blocks
|
|
78
|
+
|
|
79
|
+
Declare browser blocks in `src/customBlocks/<key>.ts`:
|
|
80
|
+
|
|
81
|
+
```ts
|
|
82
|
+
import { createCustomBlock } from "@notionhq/apps/custom-block";
|
|
83
|
+
|
|
84
|
+
export default createCustomBlock({
|
|
85
|
+
path: "./blocks/hello",
|
|
86
|
+
slashCommand: "hello",
|
|
87
|
+
dataSources: {},
|
|
88
|
+
});
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
`path` is relative to the project root. Keep frontend project code out of `src/` to avoid hitting upload caps.
|
|
92
|
+
`notion-apps build-blocks` and `notion-apps upload-blocks` are used for local builds.
|
|
93
|
+
|
|
94
|
+
See [the build and deployment guide](docs/BUILD.md) for provisioning artifacts,
|
|
95
|
+
cloud builds with server coordination, and local builds with CLI coordination.
|
|
96
|
+
|
|
77
97
|
### Moving from the Workers alpha SDK
|
|
78
98
|
|
|
79
99
|
- Remove `type` and `primaryKey` from `createDatabase`.
|
|
@@ -82,6 +102,18 @@ the change's `key`.
|
|
|
82
102
|
- Remove the primary-key property from each upsert's `properties` object.
|
|
83
103
|
- Change imports from `@notionhq/workers/alpha/*` to `@notionhq/apps/*`.
|
|
84
104
|
|
|
105
|
+
## Local / Boxy end to end testing
|
|
106
|
+
|
|
107
|
+
To build and deploy the app template against a running local Notion server:
|
|
108
|
+
|
|
109
|
+
```sh
|
|
110
|
+
# Installed ntn and the notion-cookbook template from main
|
|
111
|
+
scripts/smoketest.sh
|
|
112
|
+
|
|
113
|
+
# CLI binary and template from sibling checkouts
|
|
114
|
+
CLI=local TEMPLATE=local scripts/smoketest.sh
|
|
115
|
+
```
|
|
116
|
+
|
|
85
117
|
## Publishing New Versions
|
|
86
118
|
|
|
87
119
|
Publishing is initiated only from the GitHub Actions UI:
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
import type { ConnectionActionInvoker } from "./connection-actions.js";
|
|
2
|
+
/**
|
|
3
|
+
* Script input for the "Find shared Box item" effect (`box.findSharedItem`),
|
|
4
|
+
* derived from its Tool Core definition's call_function input projection.
|
|
5
|
+
*
|
|
6
|
+
* Resolve a Box shared link to an item ID and type.
|
|
7
|
+
*/
|
|
8
|
+
export type FindSharedItemScriptInput = {
|
|
9
|
+
/**
|
|
10
|
+
* The full Box shared link URL.
|
|
11
|
+
*/
|
|
12
|
+
sharedLink: string;
|
|
13
|
+
};
|
|
14
|
+
/**
|
|
15
|
+
* Canonical Tool Core output for the "Find shared Box item" effect (`box.findSharedItem`).
|
|
16
|
+
* This is the definition's output schema; the effect's script surface may
|
|
17
|
+
* re-encode it before returning.
|
|
18
|
+
*/
|
|
19
|
+
export type FindSharedItemScriptOutput = {
|
|
20
|
+
itemId: string;
|
|
21
|
+
/**
|
|
22
|
+
* One of: `file`, `folder`
|
|
23
|
+
*/
|
|
24
|
+
itemType: "file" | "folder";
|
|
25
|
+
name: string;
|
|
26
|
+
size: number;
|
|
27
|
+
modifiedAt: string;
|
|
28
|
+
owner: string;
|
|
29
|
+
};
|
|
30
|
+
/**
|
|
31
|
+
* Script input for the "Load Box file" effect (`box.loadFile`),
|
|
32
|
+
* derived from its Tool Core definition's call_function input projection.
|
|
33
|
+
*
|
|
34
|
+
* Load a Box file by its file ID.
|
|
35
|
+
*/
|
|
36
|
+
export type LoadFileScriptInput = {
|
|
37
|
+
/**
|
|
38
|
+
* The Box file ID.
|
|
39
|
+
*/
|
|
40
|
+
fileId: string;
|
|
41
|
+
};
|
|
42
|
+
/**
|
|
43
|
+
* Canonical Tool Core output for the "Load Box file" effect (`box.loadFile`).
|
|
44
|
+
* This is the definition's output schema; the effect's script surface may
|
|
45
|
+
* re-encode it before returning.
|
|
46
|
+
*/
|
|
47
|
+
export type LoadFileScriptOutput = {
|
|
48
|
+
/**
|
|
49
|
+
* Always `box-file`
|
|
50
|
+
*/
|
|
51
|
+
type: "box-file";
|
|
52
|
+
title: string;
|
|
53
|
+
blocks: Array<string>;
|
|
54
|
+
fileId: string;
|
|
55
|
+
};
|
|
56
|
+
/**
|
|
57
|
+
* Script input for the "List Box folder" effect (`box.lsFolder`),
|
|
58
|
+
* derived from its Tool Core definition's call_function input projection.
|
|
59
|
+
*
|
|
60
|
+
* List files and subfolders in a Box folder.
|
|
61
|
+
*/
|
|
62
|
+
export type LsFolderScriptInput = {
|
|
63
|
+
/**
|
|
64
|
+
* The Box folder ID to list contents of.
|
|
65
|
+
*/
|
|
66
|
+
folderId: string;
|
|
67
|
+
};
|
|
68
|
+
/**
|
|
69
|
+
* Canonical Tool Core output for the "List Box folder" effect (`box.lsFolder`).
|
|
70
|
+
* This is the definition's output schema; the effect's script surface may
|
|
71
|
+
* re-encode it before returning.
|
|
72
|
+
*/
|
|
73
|
+
export type LsFolderScriptOutput = {
|
|
74
|
+
items: Array<{
|
|
75
|
+
id: string;
|
|
76
|
+
/**
|
|
77
|
+
* One of: `file`, `folder`
|
|
78
|
+
*/
|
|
79
|
+
type: "file" | "folder";
|
|
80
|
+
name: string;
|
|
81
|
+
size: number;
|
|
82
|
+
modifiedAt: string;
|
|
83
|
+
}>;
|
|
84
|
+
};
|
|
85
|
+
/**
|
|
86
|
+
* Script input for the "Search Box" effect (`box.search`),
|
|
87
|
+
* derived from its Tool Core definition's call_function input projection.
|
|
88
|
+
*
|
|
89
|
+
* Search Box via the configured connector.
|
|
90
|
+
*/
|
|
91
|
+
export type SearchScriptInput = {
|
|
92
|
+
/**
|
|
93
|
+
* A single, focused question to search for.
|
|
94
|
+
*/
|
|
95
|
+
question: string;
|
|
96
|
+
/**
|
|
97
|
+
* Brief keywords capturing the core entities.
|
|
98
|
+
*/
|
|
99
|
+
keywords?: string;
|
|
100
|
+
/**
|
|
101
|
+
* Optional time window. Use only "default", "all_time", a duration matching /^\d+[dwmy]$/ (for example, "7d", "2w", "3m", or "1y"), or a date in "YYYY-MM-DD" format. Do not use natural-language durations or combine units.
|
|
102
|
+
*/
|
|
103
|
+
lookback?: string;
|
|
104
|
+
/**
|
|
105
|
+
* Optional list of Box folder IDs to scope the search to. Use findSharedItem or searchFolders to get folder IDs.
|
|
106
|
+
*/
|
|
107
|
+
folderIds?: Array<string>;
|
|
108
|
+
};
|
|
109
|
+
/**
|
|
110
|
+
* Canonical Tool Core output for the "Search Box" effect (`box.search`).
|
|
111
|
+
* This is the definition's output schema; the effect's script surface may
|
|
112
|
+
* re-encode it before returning.
|
|
113
|
+
*/
|
|
114
|
+
export type SearchScriptOutput = {
|
|
115
|
+
results: Array<{
|
|
116
|
+
id: string;
|
|
117
|
+
title: string;
|
|
118
|
+
path: string;
|
|
119
|
+
text: string;
|
|
120
|
+
lastEdited: string;
|
|
121
|
+
isPrivate: boolean;
|
|
122
|
+
pageId: string;
|
|
123
|
+
fileType: string;
|
|
124
|
+
fileId: string;
|
|
125
|
+
}>;
|
|
126
|
+
};
|
|
127
|
+
/**
|
|
128
|
+
* Script input for the "Search Box folders" effect (`box.searchFolders`),
|
|
129
|
+
* derived from its Tool Core definition's call_function input projection.
|
|
130
|
+
*
|
|
131
|
+
* Search Box folders by name.
|
|
132
|
+
*/
|
|
133
|
+
export type SearchFoldersScriptInput = {
|
|
134
|
+
/**
|
|
135
|
+
* The search query for finding folders.
|
|
136
|
+
*/
|
|
137
|
+
question: string;
|
|
138
|
+
/**
|
|
139
|
+
* Optional additional keywords to refine the folder search.
|
|
140
|
+
*/
|
|
141
|
+
keywords?: string;
|
|
142
|
+
};
|
|
143
|
+
/**
|
|
144
|
+
* Canonical Tool Core output for the "Search Box folders" effect (`box.searchFolders`).
|
|
145
|
+
* This is the definition's output schema; the effect's script surface may
|
|
146
|
+
* re-encode it before returning.
|
|
147
|
+
*/
|
|
148
|
+
export type SearchFoldersScriptOutput = {
|
|
149
|
+
results: Array<{
|
|
150
|
+
id: string;
|
|
151
|
+
name: string;
|
|
152
|
+
folderId: string;
|
|
153
|
+
}>;
|
|
154
|
+
};
|
|
155
|
+
export declare class BoxConnectionClient {
|
|
156
|
+
private readonly invoke;
|
|
157
|
+
constructor(invoke: ConnectionActionInvoker);
|
|
158
|
+
findSharedItem(args: FindSharedItemScriptInput): Promise<FindSharedItemScriptOutput>;
|
|
159
|
+
loadFile(args: LoadFileScriptInput): Promise<LoadFileScriptOutput>;
|
|
160
|
+
lsFolder(args: LsFolderScriptInput): Promise<LsFolderScriptOutput>;
|
|
161
|
+
search(args: SearchScriptInput): Promise<SearchScriptOutput>;
|
|
162
|
+
searchFolders(args: SearchFoldersScriptInput): Promise<SearchFoldersScriptOutput>;
|
|
163
|
+
}
|
|
164
|
+
//# sourceMappingURL=box.generated.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"box.generated.d.ts","sourceRoot":"","sources":["../src/box.generated.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,yBAAyB,CAAA;AACtE;;;;;GAKG;AACH,MAAM,MAAM,yBAAyB,GAAG;IACvC;;OAEG;IACH,UAAU,EAAE,MAAM,CAAA;CAClB,CAAA;AAED;;;;GAIG;AACH,MAAM,MAAM,0BAA0B,GAAG;IACxC,MAAM,EAAE,MAAM,CAAA;IACd;;OAEG;IACH,QAAQ,EAAE,MAAM,GAAG,QAAQ,CAAA;IAC3B,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;IACZ,UAAU,EAAE,MAAM,CAAA;IAClB,KAAK,EAAE,MAAM,CAAA;CACb,CAAA;AAED;;;;;GAKG;AACH,MAAM,MAAM,mBAAmB,GAAG;IACjC;;OAEG;IACH,MAAM,EAAE,MAAM,CAAA;CACd,CAAA;AAED;;;;GAIG;AACH,MAAM,MAAM,oBAAoB,GAAG;IAClC;;OAEG;IACH,IAAI,EAAE,UAAU,CAAA;IAChB,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,KAAK,CAAC,MAAM,CAAC,CAAA;IACrB,MAAM,EAAE,MAAM,CAAA;CACd,CAAA;AAED;;;;;GAKG;AACH,MAAM,MAAM,mBAAmB,GAAG;IACjC;;OAEG;IACH,QAAQ,EAAE,MAAM,CAAA;CAChB,CAAA;AAED;;;;GAIG;AACH,MAAM,MAAM,oBAAoB,GAAG;IAClC,KAAK,EAAE,KAAK,CAAC;QACZ,EAAE,EAAE,MAAM,CAAA;QACV;;WAEG;QACH,IAAI,EAAE,MAAM,GAAG,QAAQ,CAAA;QACvB,IAAI,EAAE,MAAM,CAAA;QACZ,IAAI,EAAE,MAAM,CAAA;QACZ,UAAU,EAAE,MAAM,CAAA;KAClB,CAAC,CAAA;CACF,CAAA;AAED;;;;;GAKG;AACH,MAAM,MAAM,iBAAiB,GAAG;IAC/B;;OAEG;IACH,QAAQ,EAAE,MAAM,CAAA;IAChB;;OAEG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB;;OAEG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB;;OAEG;IACH,SAAS,CAAC,EAAE,KAAK,CAAC,MAAM,CAAC,CAAA;CACzB,CAAA;AAED;;;;GAIG;AACH,MAAM,MAAM,kBAAkB,GAAG;IAChC,OAAO,EAAE,KAAK,CAAC;QACd,EAAE,EAAE,MAAM,CAAA;QACV,KAAK,EAAE,MAAM,CAAA;QACb,IAAI,EAAE,MAAM,CAAA;QACZ,IAAI,EAAE,MAAM,CAAA;QACZ,UAAU,EAAE,MAAM,CAAA;QAClB,SAAS,EAAE,OAAO,CAAA;QAClB,MAAM,EAAE,MAAM,CAAA;QACd,QAAQ,EAAE,MAAM,CAAA;QAChB,MAAM,EAAE,MAAM,CAAA;KACd,CAAC,CAAA;CACF,CAAA;AAED;;;;;GAKG;AACH,MAAM,MAAM,wBAAwB,GAAG;IACtC;;OAEG;IACH,QAAQ,EAAE,MAAM,CAAA;IAChB;;OAEG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAA;CACjB,CAAA;AAED;;;;GAIG;AACH,MAAM,MAAM,yBAAyB,GAAG;IACvC,OAAO,EAAE,KAAK,CAAC;QACd,EAAE,EAAE,MAAM,CAAA;QACV,IAAI,EAAE,MAAM,CAAA;QACZ,QAAQ,EAAE,MAAM,CAAA;KAChB,CAAC,CAAA;CACF,CAAA;AAED,qBAAa,mBAAmB;IACnB,OAAO,CAAC,QAAQ,CAAC,MAAM;gBAAN,MAAM,EAAE,uBAAuB;IAC5D,cAAc,CACb,IAAI,EAAE,yBAAyB,GAC7B,OAAO,CAAC,0BAA0B,CAAC;IAGtC,QAAQ,CAAC,IAAI,EAAE,mBAAmB,GAAG,OAAO,CAAC,oBAAoB,CAAC;IAGlE,QAAQ,CAAC,IAAI,EAAE,mBAAmB,GAAG,OAAO,CAAC,oBAAoB,CAAC;IAGlE,MAAM,CAAC,IAAI,EAAE,iBAAiB,GAAG,OAAO,CAAC,kBAAkB,CAAC;IAG5D,aAAa,CACZ,IAAI,EAAE,wBAAwB,GAC5B,OAAO,CAAC,yBAAyB,CAAC;CAGrC"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
class BoxConnectionClient {
|
|
2
|
+
constructor(invoke) {
|
|
3
|
+
this.invoke = invoke;
|
|
4
|
+
}
|
|
5
|
+
invoke;
|
|
6
|
+
findSharedItem(args) {
|
|
7
|
+
return this.invoke("findSharedItem", args);
|
|
8
|
+
}
|
|
9
|
+
loadFile(args) {
|
|
10
|
+
return this.invoke("loadFile", args);
|
|
11
|
+
}
|
|
12
|
+
lsFolder(args) {
|
|
13
|
+
return this.invoke("lsFolder", args);
|
|
14
|
+
}
|
|
15
|
+
search(args) {
|
|
16
|
+
return this.invoke("search", args);
|
|
17
|
+
}
|
|
18
|
+
searchFolders(args) {
|
|
19
|
+
return this.invoke("searchFolders", args);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
export {
|
|
23
|
+
BoxConnectionClient
|
|
24
|
+
};
|