@commandable/integration-data 0.0.1 → 0.0.4
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/dist/credentials-index.d.ts +4 -21
- package/dist/credentials-index.d.ts.map +1 -1
- package/dist/credentials-index.js +407 -215
- package/dist/credentials-index.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/loader.d.ts +38 -2
- package/dist/loader.d.ts.map +1 -1
- package/dist/loader.js +70 -16
- package/dist/loader.js.map +1 -1
- package/integrations/__tests__/liveHarness.ts +84 -0
- package/integrations/__tests__/usageParity.ts +54 -0
- package/integrations/airtable/__tests__/get_handlers.test.ts +18 -15
- package/integrations/airtable/__tests__/usage_parity.test.ts +3 -29
- package/integrations/airtable/__tests__/write_and_admin_handlers.test.ts +20 -17
- package/integrations/airtable/credentials.json +21 -16
- package/integrations/github/__tests__/get_handlers.test.ts +101 -108
- package/integrations/github/__tests__/usage_parity.test.ts +15 -27
- package/integrations/github/__tests__/write_handlers.test.ts +219 -306
- package/integrations/github/credentials.json +40 -15
- package/integrations/github/credentials_hint_classic_pat.md +8 -0
- package/integrations/github/credentials_hint_fine_grained_pat.md +9 -0
- package/integrations/github/manifest.json +2 -2
- package/integrations/google-calendar/__tests__/get_handlers.test.ts +21 -13
- package/integrations/google-calendar/__tests__/usage_parity.test.ts +3 -28
- package/integrations/google-calendar/__tests__/write_and_admin_handlers.test.ts +24 -17
- package/integrations/google-calendar/credentials.json +50 -29
- package/integrations/google-calendar/credentials_hint_oauth_token.md +8 -0
- package/integrations/google-calendar/credentials_hint_service_account.md +10 -0
- package/integrations/google-docs/__tests__/get_handlers.test.ts +87 -61
- package/integrations/google-docs/__tests__/usage_parity.test.ts +3 -28
- package/integrations/google-docs/__tests__/write_handlers.test.ts +248 -245
- package/integrations/google-docs/credentials.json +50 -29
- package/integrations/google-docs/credentials_hint_oauth_token.md +8 -0
- package/integrations/google-docs/credentials_hint_service_account.md +10 -0
- package/integrations/google-drive/credentials.json +57 -0
- package/integrations/google-drive/credentials_hint_oauth_token.md +8 -0
- package/integrations/google-drive/credentials_hint_service_account.md +10 -0
- package/integrations/google-drive/handlers/create_file.js +15 -0
- package/integrations/google-drive/handlers/create_folder.js +15 -0
- package/integrations/google-drive/handlers/delete_file.js +14 -0
- package/integrations/google-drive/handlers/get_file.js +7 -0
- package/integrations/google-drive/handlers/move_file.js +12 -0
- package/integrations/google-drive/manifest.json +42 -0
- package/integrations/google-drive/schemas/create_file.json +12 -0
- package/integrations/google-drive/schemas/create_folder.json +11 -0
- package/integrations/google-drive/schemas/delete_file.json +10 -0
- package/integrations/google-drive/schemas/get_file.json +10 -0
- package/integrations/google-drive/schemas/move_file.json +12 -0
- package/integrations/google-sheet/__tests__/get_handlers.test.ts +47 -55
- package/integrations/google-sheet/__tests__/usage_parity.test.ts +3 -29
- package/integrations/google-sheet/__tests__/write_handlers.test.ts +64 -63
- package/integrations/google-sheet/credentials.json +50 -29
- package/integrations/google-sheet/credentials_hint_oauth_token.md +8 -0
- package/integrations/google-sheet/credentials_hint_service_account.md +10 -0
- package/integrations/google-slides/__tests__/get_handlers.test.ts +37 -36
- package/integrations/google-slides/__tests__/usage_parity.test.ts +3 -28
- package/integrations/google-slides/__tests__/write_handlers.test.ts +65 -58
- package/integrations/google-slides/credentials.json +50 -29
- package/integrations/google-slides/credentials_hint_oauth_token.md +8 -0
- package/integrations/google-slides/credentials_hint_service_account.md +10 -0
- package/integrations/notion/__tests__/get_handlers.test.ts +18 -15
- package/integrations/notion/__tests__/usage_parity.test.ts +3 -28
- package/integrations/notion/__tests__/write_and_admin_handlers.test.ts +56 -60
- package/integrations/notion/credentials.json +22 -17
- package/integrations/trello/__tests__/get_handlers.test.ts +58 -73
- package/integrations/trello/__tests__/usage_parity.test.ts +3 -28
- package/integrations/trello/__tests__/write_and_admin_handlers.test.ts +49 -67
- package/integrations/trello/credentials.json +26 -21
- package/integrations/trello/handlers/close_board.js +6 -0
- package/integrations/trello/handlers/create_board.js +11 -0
- package/integrations/trello/handlers/delete_board.js +13 -0
- package/integrations/trello/manifest.json +21 -0
- package/integrations/trello/schemas/close_board.json +10 -0
- package/integrations/trello/schemas/create_board.json +12 -0
- package/integrations/trello/schemas/delete_board.json +10 -0
- package/package.json +1 -1
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import { beforeAll, describe, expect, it } from 'vitest'
|
|
2
|
-
import {
|
|
3
|
-
import { loadIntegrationTools } from '../../../src/integrations/dataLoader.js'
|
|
1
|
+
import { afterAll, beforeAll, describe, expect, it } from 'vitest'
|
|
2
|
+
import { createCredentialStore, createIntegrationNode, createProxy, createToolbox, hasEnv, safeCleanup } from '../../__tests__/liveHarness.js'
|
|
4
3
|
|
|
5
4
|
interface Ctx {
|
|
6
5
|
boardId?: string
|
|
@@ -10,86 +9,69 @@ interface Ctx {
|
|
|
10
9
|
memberId?: string
|
|
11
10
|
}
|
|
12
11
|
|
|
13
|
-
const env = process.env as Record<string, string>
|
|
14
|
-
const hasEnv = (...keys: string[]) => keys.every(k => !!env[k] && env[k].trim().length > 0)
|
|
15
12
|
const suite = hasEnv(
|
|
16
|
-
'COMMANDABLE_MANAGED_OAUTH_BASE_URL',
|
|
17
|
-
'COMMANDABLE_MANAGED_OAUTH_SECRET_KEY',
|
|
18
13
|
'TRELLO_API_KEY',
|
|
19
|
-
'
|
|
14
|
+
'TRELLO_API_TOKEN',
|
|
20
15
|
)
|
|
21
16
|
? describe
|
|
22
17
|
: describe.skip
|
|
23
18
|
|
|
24
19
|
suite('trello write handlers (live)', () => {
|
|
25
20
|
const ctx: Ctx = {}
|
|
26
|
-
let
|
|
27
|
-
let buildRead: (name: string) => ((input: any) => Promise<any>)
|
|
21
|
+
let trello: ReturnType<typeof createToolbox>
|
|
28
22
|
|
|
29
23
|
beforeAll(async () => {
|
|
30
|
-
const
|
|
31
|
-
|
|
32
|
-
const proxy =
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
const
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
expect(
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
buildRead = (name: string) => {
|
|
51
|
-
const tool = tools!.read.find(t => t.name === name)
|
|
52
|
-
expect(tool, `read tool ${name} exists`).toBeTruthy()
|
|
53
|
-
const integration = { fetch: (path: string, init?: RequestInit) => proxy.call(integrationNode, path, init) }
|
|
54
|
-
const build = new Function('integration', `return (${tool!.handlerCode});`)
|
|
55
|
-
return build(integration) as (input: any) => Promise<any>
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
// Discover a board and list for tests
|
|
59
|
-
const get_member_boards = buildRead('get_member_boards')
|
|
60
|
-
const boards = await get_member_boards({})
|
|
61
|
-
ctx.boardId = boards?.[0]?.id
|
|
62
|
-
if (ctx.boardId) {
|
|
63
|
-
const get_board_lists = buildRead('get_board_lists')
|
|
64
|
-
const lists = await get_board_lists({ boardId: ctx.boardId })
|
|
65
|
-
ctx.listId = lists?.[0]?.id
|
|
66
|
-
ctx.listId2 = lists?.[1]?.id || ctx.listId
|
|
67
|
-
}
|
|
24
|
+
const env = process.env as Record<string, string | undefined>
|
|
25
|
+
const credentialStore = createCredentialStore(async () => ({ apiKey: env.TRELLO_API_KEY || '', apiToken: env.TRELLO_API_TOKEN || '' }))
|
|
26
|
+
const proxy = createProxy(credentialStore)
|
|
27
|
+
const node = createIntegrationNode('trello', { label: 'Trello', credentialId: 'trello-creds' })
|
|
28
|
+
trello = createToolbox('trello', proxy, node)
|
|
29
|
+
|
|
30
|
+
// Create an isolated board + two lists for this test run
|
|
31
|
+
const create_board = trello.write('create_board')
|
|
32
|
+
const board = await create_board({ name: `CmdTest Trello ${Date.now()}`, defaultLists: false })
|
|
33
|
+
ctx.boardId = board?.id
|
|
34
|
+
expect(ctx.boardId).toBeTruthy()
|
|
35
|
+
|
|
36
|
+
const create_list = trello.write('create_list')
|
|
37
|
+
const list1 = await create_list({ idBoard: ctx.boardId, name: 'CmdTest List A' })
|
|
38
|
+
const list2 = await create_list({ idBoard: ctx.boardId, name: 'CmdTest List B' })
|
|
39
|
+
ctx.listId = list1?.id
|
|
40
|
+
ctx.listId2 = list2?.id
|
|
41
|
+
expect(ctx.listId).toBeTruthy()
|
|
42
|
+
expect(ctx.listId2).toBeTruthy()
|
|
68
43
|
|
|
69
44
|
// Discover a member to add to card (self)
|
|
70
|
-
const get_member =
|
|
45
|
+
const get_member = trello.read('get_member')
|
|
71
46
|
const me = await get_member({})
|
|
72
47
|
ctx.memberId = me?.id
|
|
73
48
|
}, 60000)
|
|
74
49
|
|
|
50
|
+
afterAll(async () => {
|
|
51
|
+
if (!ctx.boardId)
|
|
52
|
+
return
|
|
53
|
+
await safeCleanup(async () => trello.write('close_board')({ boardId: ctx.boardId }))
|
|
54
|
+
await safeCleanup(async () => trello.write('delete_board')({ boardId: ctx.boardId }))
|
|
55
|
+
}, 60_000)
|
|
56
|
+
|
|
75
57
|
it('create_card -> get_card -> update_card -> move_card_to_list -> delete_card', async () => {
|
|
76
58
|
if (!ctx.boardId || !ctx.listId || !ctx.memberId)
|
|
77
59
|
return expect(true).toBe(true)
|
|
78
60
|
|
|
79
61
|
// Create card
|
|
80
|
-
const create_card =
|
|
62
|
+
const create_card = trello.write('create_card')
|
|
81
63
|
const created = await create_card({ idList: ctx.listId, name: `CmdCard ${Date.now()}`, desc: 'Initial desc' })
|
|
82
64
|
const cardId = created?.id
|
|
83
65
|
expect(cardId).toBeTruthy()
|
|
84
66
|
ctx.cardId = cardId
|
|
85
67
|
|
|
86
68
|
// Read card
|
|
87
|
-
const get_card =
|
|
69
|
+
const get_card = trello.read('get_card')
|
|
88
70
|
const got = await get_card({ cardId })
|
|
89
71
|
expect(got?.id).toBe(cardId)
|
|
90
72
|
|
|
91
73
|
// Update card
|
|
92
|
-
const update_card =
|
|
74
|
+
const update_card = trello.write('update_card')
|
|
93
75
|
const updated = await update_card({ cardId, name: 'Updated Name', desc: 'Updated desc' })
|
|
94
76
|
expect(updated?.id).toBe(cardId)
|
|
95
77
|
|
|
@@ -99,7 +81,7 @@ suite('trello write handlers (live)', () => {
|
|
|
99
81
|
|
|
100
82
|
// Move card
|
|
101
83
|
if (ctx.listId2 && ctx.listId2 !== ctx.listId) {
|
|
102
|
-
const move_card_to_list =
|
|
84
|
+
const move_card_to_list = trello.write('move_card_to_list')
|
|
103
85
|
const moved = await move_card_to_list({ cardId, listId: ctx.listId2 })
|
|
104
86
|
expect(moved?.id).toBe(cardId)
|
|
105
87
|
const got3 = await get_card({ cardId })
|
|
@@ -107,7 +89,7 @@ suite('trello write handlers (live)', () => {
|
|
|
107
89
|
}
|
|
108
90
|
|
|
109
91
|
// Delete card
|
|
110
|
-
const delete_card =
|
|
92
|
+
const delete_card = trello.write('delete_card')
|
|
111
93
|
const del = await delete_card({ cardId })
|
|
112
94
|
expect(Boolean(del === '' || del?.limits || del?.id === cardId || (del && typeof del === 'object'))).toBe(true)
|
|
113
95
|
}, 120000)
|
|
@@ -117,26 +99,26 @@ suite('trello write handlers (live)', () => {
|
|
|
117
99
|
return expect(true).toBe(true)
|
|
118
100
|
|
|
119
101
|
// Create an isolated card for this test
|
|
120
|
-
const create_card =
|
|
102
|
+
const create_card = trello.write('create_card')
|
|
121
103
|
const created = await create_card({ idList: ctx.listId, name: `CmdCard Members ${Date.now()}` })
|
|
122
104
|
const cardId = created?.id
|
|
123
105
|
expect(cardId).toBeTruthy()
|
|
124
106
|
|
|
125
|
-
const add_member_to_card =
|
|
107
|
+
const add_member_to_card = trello.write('add_member_to_card')
|
|
126
108
|
const added = await add_member_to_card({ cardId, memberId: ctx.memberId })
|
|
127
109
|
expect(added).toBeTruthy()
|
|
128
110
|
|
|
129
|
-
const get_card_members =
|
|
111
|
+
const get_card_members = trello.read('get_card_members')
|
|
130
112
|
const members = await get_card_members({ cardId })
|
|
131
113
|
const hasMember = (members || []).some((m: any) => m?.id === ctx.memberId)
|
|
132
114
|
expect(hasMember).toBe(true)
|
|
133
115
|
|
|
134
|
-
const remove_member_from_card =
|
|
116
|
+
const remove_member_from_card = trello.write('remove_member_from_card')
|
|
135
117
|
const removed = await remove_member_from_card({ cardId, memberId: ctx.memberId })
|
|
136
118
|
expect(removed === '' || (removed && typeof removed === 'object')).toBe(true)
|
|
137
119
|
|
|
138
120
|
// Cleanup
|
|
139
|
-
const delete_card =
|
|
121
|
+
const delete_card = trello.write('delete_card')
|
|
140
122
|
await delete_card({ cardId })
|
|
141
123
|
}, 90000)
|
|
142
124
|
|
|
@@ -145,44 +127,44 @@ suite('trello write handlers (live)', () => {
|
|
|
145
127
|
return expect(true).toBe(true)
|
|
146
128
|
|
|
147
129
|
// Create an isolated card for this test
|
|
148
|
-
const create_card =
|
|
130
|
+
const create_card = trello.write('create_card')
|
|
149
131
|
const createdCard = await create_card({ idList: ctx.listId, name: `CmdCard Checklist ${Date.now()}` })
|
|
150
132
|
const cardId = createdCard?.id
|
|
151
133
|
expect(cardId).toBeTruthy()
|
|
152
134
|
|
|
153
|
-
const add_checklist_to_card =
|
|
135
|
+
const add_checklist_to_card = trello.write('add_checklist_to_card')
|
|
154
136
|
const created = await add_checklist_to_card({ cardId, name: `Checklist ${Date.now()}` })
|
|
155
137
|
expect(created?.id).toBeTruthy()
|
|
156
138
|
|
|
157
|
-
const get_card_checklists =
|
|
139
|
+
const get_card_checklists = trello.read('get_card_checklists')
|
|
158
140
|
const lists = await get_card_checklists({ cardId })
|
|
159
141
|
expect(Array.isArray(lists)).toBe(true)
|
|
160
142
|
|
|
161
143
|
// Cleanup
|
|
162
|
-
const delete_card =
|
|
144
|
+
const delete_card = trello.write('delete_card')
|
|
163
145
|
await delete_card({ cardId })
|
|
164
146
|
}, 60000)
|
|
165
147
|
|
|
166
148
|
it('create_list -> get_list -> update_list -> archive_list', async () => {
|
|
167
149
|
if (!ctx.boardId)
|
|
168
150
|
return expect(true).toBe(true)
|
|
169
|
-
const create_list =
|
|
151
|
+
const create_list = trello.write('create_list')
|
|
170
152
|
const created = await create_list({ idBoard: ctx.boardId, name: `CmdList ${Date.now()}` })
|
|
171
153
|
const listId = created?.id
|
|
172
154
|
expect(listId).toBeTruthy()
|
|
173
155
|
|
|
174
|
-
const get_list =
|
|
156
|
+
const get_list = trello.read('get_list')
|
|
175
157
|
const got = await get_list({ listId })
|
|
176
158
|
expect(got?.id).toBe(listId)
|
|
177
159
|
|
|
178
|
-
const update_list =
|
|
160
|
+
const update_list = trello.write('update_list')
|
|
179
161
|
const updated = await update_list({ listId, name: 'Updated List Name' })
|
|
180
162
|
expect(updated?.id).toBe(listId)
|
|
181
163
|
|
|
182
164
|
const got2 = await get_list({ listId })
|
|
183
165
|
expect(got2?.name).toBe('Updated List Name')
|
|
184
166
|
|
|
185
|
-
const archive_list =
|
|
167
|
+
const archive_list = trello.write('archive_list')
|
|
186
168
|
const archived = await archive_list({ listId })
|
|
187
169
|
expect(archived?.closed === true).toBe(true)
|
|
188
170
|
}, 120000)
|
|
@@ -1,26 +1,31 @@
|
|
|
1
1
|
{
|
|
2
|
-
"
|
|
3
|
-
"
|
|
4
|
-
|
|
5
|
-
"
|
|
6
|
-
"type": "
|
|
7
|
-
"
|
|
8
|
-
|
|
2
|
+
"variants": {
|
|
3
|
+
"api_key_token": {
|
|
4
|
+
"label": "API Key + Token",
|
|
5
|
+
"schema": {
|
|
6
|
+
"type": "object",
|
|
7
|
+
"properties": {
|
|
8
|
+
"apiKey": {
|
|
9
|
+
"type": "string",
|
|
10
|
+
"title": "API Key",
|
|
11
|
+
"description": "Your Trello API key from https://trello.com/power-ups/admin"
|
|
12
|
+
},
|
|
13
|
+
"apiToken": {
|
|
14
|
+
"type": "string",
|
|
15
|
+
"title": "API Token",
|
|
16
|
+
"description": "Your Trello API token (\"token\" param). Generate one via Trello's authorize flow."
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
"required": ["apiKey", "apiToken"],
|
|
20
|
+
"additionalProperties": false
|
|
9
21
|
},
|
|
10
|
-
"
|
|
11
|
-
"
|
|
12
|
-
|
|
13
|
-
|
|
22
|
+
"injection": {
|
|
23
|
+
"query": {
|
|
24
|
+
"key": "{{apiKey}}",
|
|
25
|
+
"token": "{{apiToken}}"
|
|
26
|
+
}
|
|
14
27
|
}
|
|
15
|
-
},
|
|
16
|
-
"required": ["apiKey", "apiToken"],
|
|
17
|
-
"additionalProperties": false
|
|
18
|
-
},
|
|
19
|
-
"injection": {
|
|
20
|
-
"query": {
|
|
21
|
-
"key": "{{apiKey}}",
|
|
22
|
-
"token": "{{apiToken}}"
|
|
23
28
|
}
|
|
24
|
-
}
|
|
29
|
+
},
|
|
30
|
+
"default": "api_key_token"
|
|
25
31
|
}
|
|
26
|
-
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
async (input) => {
|
|
2
|
+
const params = new URLSearchParams()
|
|
3
|
+
params.set('name', input.name)
|
|
4
|
+
if (input.defaultLists !== undefined && input.defaultLists !== null)
|
|
5
|
+
params.set('defaultLists', String(Boolean(input.defaultLists)))
|
|
6
|
+
if (input.desc !== undefined && input.desc !== null)
|
|
7
|
+
params.set('desc', String(input.desc))
|
|
8
|
+
const res = await integration.fetch(`/boards?${params.toString()}`, { method: 'POST' })
|
|
9
|
+
return await res.json()
|
|
10
|
+
}
|
|
11
|
+
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
async (input) => {
|
|
2
|
+
const res = await integration.fetch(`/boards/${encodeURIComponent(input.boardId)}`, { method: 'DELETE' })
|
|
3
|
+
if (res.status === 204)
|
|
4
|
+
return { success: true, status: 204 }
|
|
5
|
+
// Trello sometimes returns JSON on delete failures.
|
|
6
|
+
try {
|
|
7
|
+
return await res.json()
|
|
8
|
+
}
|
|
9
|
+
catch {
|
|
10
|
+
return { success: res.ok, status: res.status }
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
|
|
@@ -157,6 +157,27 @@
|
|
|
157
157
|
"handler": "handlers/search.js",
|
|
158
158
|
"scope": "read"
|
|
159
159
|
},
|
|
160
|
+
{
|
|
161
|
+
"name": "create_board",
|
|
162
|
+
"description": "Create a new board.",
|
|
163
|
+
"inputSchema": "schemas/create_board.json",
|
|
164
|
+
"handler": "handlers/create_board.js",
|
|
165
|
+
"scope": "write"
|
|
166
|
+
},
|
|
167
|
+
{
|
|
168
|
+
"name": "close_board",
|
|
169
|
+
"description": "Close a board (set closed=true).",
|
|
170
|
+
"inputSchema": "schemas/close_board.json",
|
|
171
|
+
"handler": "handlers/close_board.js",
|
|
172
|
+
"scope": "write"
|
|
173
|
+
},
|
|
174
|
+
{
|
|
175
|
+
"name": "delete_board",
|
|
176
|
+
"description": "Permanently delete a closed board.",
|
|
177
|
+
"inputSchema": "schemas/delete_board.json",
|
|
178
|
+
"handler": "handlers/delete_board.js",
|
|
179
|
+
"scope": "write"
|
|
180
|
+
},
|
|
160
181
|
{
|
|
161
182
|
"name": "create_card",
|
|
162
183
|
"description": "Create a new card in a list.",
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
3
|
+
"type": "object",
|
|
4
|
+
"required": ["name"],
|
|
5
|
+
"additionalProperties": false,
|
|
6
|
+
"properties": {
|
|
7
|
+
"name": { "type": "string" },
|
|
8
|
+
"defaultLists": { "type": "boolean", "description": "Create the default lists on the board (default: true)" },
|
|
9
|
+
"desc": { "type": "string" }
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
|
package/package.json
CHANGED