@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.
Files changed (79) hide show
  1. package/dist/credentials-index.d.ts +4 -21
  2. package/dist/credentials-index.d.ts.map +1 -1
  3. package/dist/credentials-index.js +407 -215
  4. package/dist/credentials-index.js.map +1 -1
  5. package/dist/index.d.ts +2 -2
  6. package/dist/index.d.ts.map +1 -1
  7. package/dist/index.js +1 -1
  8. package/dist/index.js.map +1 -1
  9. package/dist/loader.d.ts +38 -2
  10. package/dist/loader.d.ts.map +1 -1
  11. package/dist/loader.js +70 -16
  12. package/dist/loader.js.map +1 -1
  13. package/integrations/__tests__/liveHarness.ts +84 -0
  14. package/integrations/__tests__/usageParity.ts +54 -0
  15. package/integrations/airtable/__tests__/get_handlers.test.ts +18 -15
  16. package/integrations/airtable/__tests__/usage_parity.test.ts +3 -29
  17. package/integrations/airtable/__tests__/write_and_admin_handlers.test.ts +20 -17
  18. package/integrations/airtable/credentials.json +21 -16
  19. package/integrations/github/__tests__/get_handlers.test.ts +101 -108
  20. package/integrations/github/__tests__/usage_parity.test.ts +15 -27
  21. package/integrations/github/__tests__/write_handlers.test.ts +219 -306
  22. package/integrations/github/credentials.json +40 -15
  23. package/integrations/github/credentials_hint_classic_pat.md +8 -0
  24. package/integrations/github/credentials_hint_fine_grained_pat.md +9 -0
  25. package/integrations/github/manifest.json +2 -2
  26. package/integrations/google-calendar/__tests__/get_handlers.test.ts +21 -13
  27. package/integrations/google-calendar/__tests__/usage_parity.test.ts +3 -28
  28. package/integrations/google-calendar/__tests__/write_and_admin_handlers.test.ts +24 -17
  29. package/integrations/google-calendar/credentials.json +50 -29
  30. package/integrations/google-calendar/credentials_hint_oauth_token.md +8 -0
  31. package/integrations/google-calendar/credentials_hint_service_account.md +10 -0
  32. package/integrations/google-docs/__tests__/get_handlers.test.ts +87 -61
  33. package/integrations/google-docs/__tests__/usage_parity.test.ts +3 -28
  34. package/integrations/google-docs/__tests__/write_handlers.test.ts +248 -245
  35. package/integrations/google-docs/credentials.json +50 -29
  36. package/integrations/google-docs/credentials_hint_oauth_token.md +8 -0
  37. package/integrations/google-docs/credentials_hint_service_account.md +10 -0
  38. package/integrations/google-drive/credentials.json +57 -0
  39. package/integrations/google-drive/credentials_hint_oauth_token.md +8 -0
  40. package/integrations/google-drive/credentials_hint_service_account.md +10 -0
  41. package/integrations/google-drive/handlers/create_file.js +15 -0
  42. package/integrations/google-drive/handlers/create_folder.js +15 -0
  43. package/integrations/google-drive/handlers/delete_file.js +14 -0
  44. package/integrations/google-drive/handlers/get_file.js +7 -0
  45. package/integrations/google-drive/handlers/move_file.js +12 -0
  46. package/integrations/google-drive/manifest.json +42 -0
  47. package/integrations/google-drive/schemas/create_file.json +12 -0
  48. package/integrations/google-drive/schemas/create_folder.json +11 -0
  49. package/integrations/google-drive/schemas/delete_file.json +10 -0
  50. package/integrations/google-drive/schemas/get_file.json +10 -0
  51. package/integrations/google-drive/schemas/move_file.json +12 -0
  52. package/integrations/google-sheet/__tests__/get_handlers.test.ts +47 -55
  53. package/integrations/google-sheet/__tests__/usage_parity.test.ts +3 -29
  54. package/integrations/google-sheet/__tests__/write_handlers.test.ts +64 -63
  55. package/integrations/google-sheet/credentials.json +50 -29
  56. package/integrations/google-sheet/credentials_hint_oauth_token.md +8 -0
  57. package/integrations/google-sheet/credentials_hint_service_account.md +10 -0
  58. package/integrations/google-slides/__tests__/get_handlers.test.ts +37 -36
  59. package/integrations/google-slides/__tests__/usage_parity.test.ts +3 -28
  60. package/integrations/google-slides/__tests__/write_handlers.test.ts +65 -58
  61. package/integrations/google-slides/credentials.json +50 -29
  62. package/integrations/google-slides/credentials_hint_oauth_token.md +8 -0
  63. package/integrations/google-slides/credentials_hint_service_account.md +10 -0
  64. package/integrations/notion/__tests__/get_handlers.test.ts +18 -15
  65. package/integrations/notion/__tests__/usage_parity.test.ts +3 -28
  66. package/integrations/notion/__tests__/write_and_admin_handlers.test.ts +56 -60
  67. package/integrations/notion/credentials.json +22 -17
  68. package/integrations/trello/__tests__/get_handlers.test.ts +58 -73
  69. package/integrations/trello/__tests__/usage_parity.test.ts +3 -28
  70. package/integrations/trello/__tests__/write_and_admin_handlers.test.ts +49 -67
  71. package/integrations/trello/credentials.json +26 -21
  72. package/integrations/trello/handlers/close_board.js +6 -0
  73. package/integrations/trello/handlers/create_board.js +11 -0
  74. package/integrations/trello/handlers/delete_board.js +13 -0
  75. package/integrations/trello/manifest.json +21 -0
  76. package/integrations/trello/schemas/close_board.json +10 -0
  77. package/integrations/trello/schemas/create_board.json +12 -0
  78. package/integrations/trello/schemas/delete_board.json +10 -0
  79. package/package.json +1 -1
@@ -1,6 +1,5 @@
1
- import { beforeAll, describe, expect, it } from 'vitest'
2
- import { IntegrationProxy } from '../../../src/integrations/proxy.js'
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
- 'TRELLO_TEST_CONNECTION_ID',
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 buildWrite: (name: string) => ((input: any) => Promise<any>)
27
- let buildRead: (name: string) => ((input: any) => Promise<any>)
21
+ let trello: ReturnType<typeof createToolbox>
28
22
 
29
23
  beforeAll(async () => {
30
- const { COMMANDABLE_MANAGED_OAUTH_BASE_URL, COMMANDABLE_MANAGED_OAUTH_SECRET_KEY, TRELLO_API_KEY, TRELLO_TEST_CONNECTION_ID } = env
31
-
32
- const proxy = new IntegrationProxy({
33
- managedOAuthBaseUrl: COMMANDABLE_MANAGED_OAUTH_BASE_URL,
34
- managedOAuthSecretKey: COMMANDABLE_MANAGED_OAUTH_SECRET_KEY,
35
- trelloApiKey: TRELLO_API_KEY,
36
- })
37
- const integrationNode = { id: 'node-trello', type: 'trello', label: 'Trello', connectionId: TRELLO_TEST_CONNECTION_ID } as any
38
-
39
- const tools = loadIntegrationTools('trello')
40
- expect(tools).toBeTruthy()
41
-
42
- buildWrite = (name: string) => {
43
- const tool = tools!.write.find(t => t.name === name)
44
- expect(tool, `write tool ${name} exists`).toBeTruthy()
45
- const integration = { fetch: (path: string, init?: RequestInit) => proxy.call(integrationNode, path, init) }
46
- const build = new Function('integration', `return (${tool!.handlerCode});`)
47
- return build(integration) as (input: any) => Promise<any>
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 = buildRead('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 = buildWrite('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 = buildRead('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 = buildWrite('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 = buildWrite('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 = buildWrite('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 = buildWrite('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 = buildWrite('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 = buildRead('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 = buildWrite('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 = buildWrite('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 = buildWrite('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 = buildWrite('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 = buildRead('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 = buildWrite('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 = buildWrite('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 = buildRead('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 = buildWrite('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 = buildWrite('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
- "schema": {
3
- "type": "object",
4
- "properties": {
5
- "apiKey": {
6
- "type": "string",
7
- "title": "API Key",
8
- "description": "Your Trello API key from https://trello.com/power-ups/admin"
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
- "apiToken": {
11
- "type": "string",
12
- "title": "API Token",
13
- "description": "Your Trello API token (\"token\" param). Generate one via Trello's authorize flow."
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,6 @@
1
+ async (input) => {
2
+ const params = new URLSearchParams({ closed: 'true' })
3
+ const res = await integration.fetch(`/boards/${encodeURIComponent(input.boardId)}?${params.toString()}`, { method: 'PUT' })
4
+ return await res.json()
5
+ }
6
+
@@ -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,10 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "type": "object",
4
+ "required": ["boardId"],
5
+ "additionalProperties": false,
6
+ "properties": {
7
+ "boardId": { "type": "string" }
8
+ }
9
+ }
10
+
@@ -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
+
@@ -0,0 +1,10 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "type": "object",
4
+ "required": ["boardId"],
5
+ "additionalProperties": false,
6
+ "properties": {
7
+ "boardId": { "type": "string" }
8
+ }
9
+ }
10
+
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@commandable/integration-data",
3
- "version": "0.0.1",
3
+ "version": "0.0.4",
4
4
  "description": "Integration data (manifests, schemas, handlers, credential configs) for Commandable integrations.",
5
5
  "license": "AGPL-3.0-only",
6
6
  "repository": {