@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,117 +1,110 @@
1
1
  import { beforeAll, describe, expect, it } from 'vitest'
2
- import { IntegrationProxy } from '../../../src/integrations/proxy.js'
3
- import { loadIntegrationTools } from '../../../src/integrations/dataLoader.js'
4
-
5
- // LIVE GitHub integration tests using managed OAuth
6
- // Required env vars:
7
- // - COMMANDABLE_MANAGED_OAUTH_BASE_URL
8
- // - COMMANDABLE_MANAGED_OAUTH_SECRET_KEY
9
- // - GITHUB_TEST_CONNECTION_ID (managed OAuth connection for provider 'github')
10
-
11
- interface Ctx {
12
- owner?: string
13
- repo?: string
14
- issue_number?: number
15
- }
2
+ import { createCredentialStore, createIntegrationNode, createProxy, createToolbox, hasEnv } from '../../__tests__/liveHarness.js'
16
3
 
17
- const env = process.env as Record<string, string>
18
- const hasEnv = (...keys: string[]) => keys.every(k => !!env[k] && env[k].trim().length > 0)
19
- const suite = hasEnv('COMMANDABLE_MANAGED_OAUTH_BASE_URL', 'COMMANDABLE_MANAGED_OAUTH_SECRET_KEY', 'GITHUB_TEST_CONNECTION_ID')
20
- ? describe
21
- : describe.skip
4
+ // LIVE GitHub read tests -- runs once per available credential variant.
5
+ // Required env vars (at least one):
6
+ // - GITHUB_CLASSIC_PAT
7
+ // - GITHUB_FINE_GRAINED_PAT
22
8
 
23
- suite('github read handlers (live)', () => {
24
- const ctx: Ctx = {}
25
- let buildHandler: (name: string) => ((input: any) => Promise<any>)
9
+ const env = process.env as Record<string, string | undefined>
26
10
 
27
- beforeAll(async () => {
28
- const { COMMANDABLE_MANAGED_OAUTH_BASE_URL, COMMANDABLE_MANAGED_OAUTH_SECRET_KEY, GITHUB_TEST_CONNECTION_ID } = env
11
+ interface VariantConfig {
12
+ key: string
13
+ token: string
14
+ }
29
15
 
30
- const proxy = new IntegrationProxy({
31
- managedOAuthBaseUrl: COMMANDABLE_MANAGED_OAUTH_BASE_URL,
32
- managedOAuthSecretKey: COMMANDABLE_MANAGED_OAUTH_SECRET_KEY,
33
- })
34
- const integrationNode = { id: 'node-github', type: 'github', label: 'GitHub', connectionId: GITHUB_TEST_CONNECTION_ID } as any
16
+ const variants: VariantConfig[] = [
17
+ { key: 'classic_pat', token: env.GITHUB_CLASSIC_PAT || '' },
18
+ { key: 'fine_grained_pat', token: env.GITHUB_FINE_GRAINED_PAT || '' },
19
+ ].filter(v => v.token.trim().length > 0)
35
20
 
36
- const tools = loadIntegrationTools('github')
37
- expect(tools).toBeTruthy()
21
+ const suiteOrSkip = variants.length > 0 ? describe : describe.skip
38
22
 
39
- buildHandler = (name: string) => {
40
- const tool = tools!.read.find(t => t.name === name)
41
- expect(tool, `tool ${name} exists`).toBeTruthy()
42
- const integration = {
43
- fetch: (path: string, init?: RequestInit) => proxy.call(integrationNode, path, init),
23
+ suiteOrSkip('github read handlers (live)', () => {
24
+ for (const variant of variants) {
25
+ describe(`variant: ${variant.key}`, () => {
26
+ interface Ctx {
27
+ owner?: string
28
+ repo?: string
29
+ issue_number?: number
44
30
  }
45
- const build = new Function('integration', `return (${tool!.handlerCode});`)
46
- return build(integration) as (input: any) => Promise<any>
47
- }
48
-
49
- // Discover owner/repo/issue for tests
50
- const list_repos = buildHandler('list_repos')
51
- const repos = await list_repos({})
52
- const first = Array.isArray(repos) ? repos[0] : repos?.[0]
53
- ctx.owner = first?.owner?.login || first?.owner || first?.full_name?.split?.('/')[0]
54
- ctx.repo = first?.name || first?.full_name?.split?.('/')[1]
55
-
56
- if (ctx.owner && ctx.repo) {
57
- const list_issues = buildHandler('list_issues')
58
- const issues = await list_issues({ owner: ctx.owner, repo: ctx.repo, state: 'all' })
59
- const firstIssue = Array.isArray(issues) ? issues.find((i: any) => typeof i.number === 'number') : undefined
60
- ctx.issue_number = firstIssue?.number
61
- }
62
- }, 60000)
63
-
64
- it('list_repos returns repositories', async () => {
65
- const handler = buildHandler('list_repos')
66
- const result = await handler({})
67
- expect(result).toBeTruthy()
68
- }, 30000)
69
-
70
- it('get_repo returns repo details', async () => {
71
- if (!ctx.owner || !ctx.repo)
72
- return expect(true).toBe(true)
73
- const handler = buildHandler('get_repo')
74
- const result = await handler({ owner: ctx.owner, repo: ctx.repo })
75
- expect(result?.name?.toLowerCase?.()).toBe(ctx.repo?.toLowerCase?.())
76
- }, 30000)
77
-
78
- it('list_issues returns issues for repo', async () => {
79
- if (!ctx.owner || !ctx.repo)
80
- return expect(true).toBe(true)
81
- const handler = buildHandler('list_issues')
82
- const result = await handler({ owner: ctx.owner, repo: ctx.repo, state: 'all' })
83
- expect(Array.isArray(result)).toBe(true)
84
- }, 30000)
85
-
86
- it('get_issue returns a single issue if available', async () => {
87
- if (!ctx.owner || !ctx.repo || !ctx.issue_number)
88
- return expect(true).toBe(true)
89
- const handler = buildHandler('get_issue')
90
- const result = await handler({ owner: ctx.owner, repo: ctx.repo, issue_number: ctx.issue_number })
91
- expect(result?.number).toBe(ctx.issue_number)
92
- }, 30000)
93
-
94
- it('list_pull_requests returns PRs', async () => {
95
- if (!ctx.owner || !ctx.repo)
96
- return expect(true).toBe(true)
97
- const handler = buildHandler('list_pull_requests')
98
- const result = await handler({ owner: ctx.owner, repo: ctx.repo, state: 'all' })
99
- expect(Array.isArray(result)).toBe(true)
100
- }, 30000)
101
-
102
- it('list_branches returns branches', async () => {
103
- if (!ctx.owner || !ctx.repo)
104
- return expect(true).toBe(true)
105
- const handler = buildHandler('list_branches')
106
- const result = await handler({ owner: ctx.owner, repo: ctx.repo })
107
- expect(Array.isArray(result)).toBe(true)
108
- }, 30000)
109
-
110
- it('list_commits returns commits', async () => {
111
- if (!ctx.owner || !ctx.repo)
112
- return expect(true).toBe(true)
113
- const handler = buildHandler('list_commits')
114
- const result = await handler({ owner: ctx.owner, repo: ctx.repo })
115
- expect(Array.isArray(result)).toBe(true)
116
- }, 30000)
31
+
32
+ const ctx: Ctx = {}
33
+ let toolbox: ReturnType<typeof createToolbox>
34
+
35
+ beforeAll(async () => {
36
+ const credentialStore = createCredentialStore(async () => ({ token: variant.token }))
37
+ const proxy = createProxy(credentialStore)
38
+ const node = createIntegrationNode('github', { credentialVariant: variant.key })
39
+ toolbox = createToolbox('github', proxy, node, variant.key)
40
+
41
+ const list_repos = toolbox.read('list_repos')
42
+ const repos = await list_repos({})
43
+ const first = Array.isArray(repos) ? repos[0] : undefined
44
+ ctx.owner = first?.owner?.login || first?.owner || first?.full_name?.split?.('/')[0]
45
+ ctx.repo = first?.name || first?.full_name?.split?.('/')[1]
46
+
47
+ if (ctx.owner && ctx.repo) {
48
+ const list_issues = toolbox.read('list_issues')
49
+ const issues = await list_issues({ owner: ctx.owner, repo: ctx.repo, state: 'all' })
50
+ const firstIssue = Array.isArray(issues) ? issues.find((i: any) => typeof i.number === 'number') : undefined
51
+ ctx.issue_number = firstIssue?.number
52
+ }
53
+ }, 60000)
54
+
55
+ it('list_repos returns repositories', async () => {
56
+ const handler = toolbox.read('list_repos')
57
+ const result = await handler({})
58
+ expect(result).toBeTruthy()
59
+ }, 30000)
60
+
61
+ it('get_repo returns repo details', async () => {
62
+ if (!ctx.owner || !ctx.repo)
63
+ return expect(true).toBe(true)
64
+ const handler = toolbox.read('get_repo')
65
+ const result = await handler({ owner: ctx.owner, repo: ctx.repo })
66
+ expect(result?.name?.toLowerCase?.()).toBe(ctx.repo?.toLowerCase?.())
67
+ }, 30000)
68
+
69
+ it('list_issues returns issues for repo', async () => {
70
+ if (!ctx.owner || !ctx.repo)
71
+ return expect(true).toBe(true)
72
+ const handler = toolbox.read('list_issues')
73
+ const result = await handler({ owner: ctx.owner, repo: ctx.repo, state: 'all' })
74
+ expect(Array.isArray(result)).toBe(true)
75
+ }, 30000)
76
+
77
+ it('get_issue returns a single issue if available', async () => {
78
+ if (!ctx.owner || !ctx.repo || !ctx.issue_number)
79
+ return expect(true).toBe(true)
80
+ const handler = toolbox.read('get_issue')
81
+ const result = await handler({ owner: ctx.owner, repo: ctx.repo, issue_number: ctx.issue_number })
82
+ expect(result?.number).toBe(ctx.issue_number)
83
+ }, 30000)
84
+
85
+ it('list_pull_requests returns PRs', async () => {
86
+ if (!ctx.owner || !ctx.repo)
87
+ return expect(true).toBe(true)
88
+ const handler = toolbox.read('list_pull_requests')
89
+ const result = await handler({ owner: ctx.owner, repo: ctx.repo, state: 'all' })
90
+ expect(Array.isArray(result)).toBe(true)
91
+ }, 30000)
92
+
93
+ it('list_branches returns branches', async () => {
94
+ if (!ctx.owner || !ctx.repo)
95
+ return expect(true).toBe(true)
96
+ const handler = toolbox.read('list_branches')
97
+ const result = await handler({ owner: ctx.owner, repo: ctx.repo })
98
+ expect(Array.isArray(result)).toBe(true)
99
+ }, 30000)
100
+
101
+ it('list_commits returns commits', async () => {
102
+ if (!ctx.owner || !ctx.repo)
103
+ return expect(true).toBe(true)
104
+ const handler = toolbox.read('list_commits')
105
+ const result = await handler({ owner: ctx.owner, repo: ctx.repo })
106
+ expect(Array.isArray(result)).toBe(true)
107
+ }, 30000)
108
+ })
109
+ }
117
110
  })
@@ -1,34 +1,22 @@
1
- import { existsSync, readdirSync, readFileSync } from 'node:fs'
2
- import { resolve } from 'node:path'
3
- import { fileURLToPath } from 'node:url'
4
1
  import { describe, expect, it } from 'vitest'
5
- import { loadIntegrationManifest } from '../../../src/integrations/dataLoader.js'
6
-
7
- function escapeRegExp(str: string): string {
8
- return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
9
- }
2
+ import { getMissingToolUsages } from '../../__tests__/usageParity.js'
10
3
 
11
4
  describe('github static usage parity', () => {
12
- it('every manifest tool is referenced in tests via build*(name)', () => {
13
- const manifest = loadIntegrationManifest('github')!
14
- const toolNames = (manifest.tools as any[]).map(t => t.name)
15
-
16
- const testsDir = fileURLToPath(new URL('.', import.meta.url))
17
- expect(existsSync(testsDir)).toBe(true)
18
- const testFiles = readdirSync(testsDir)
19
- .filter(f => /\.test\.(t|j)s$/.test(f) && !f.includes('usage_parity.test'))
20
- .map(f => resolve(testsDir, f))
21
-
22
- const fileContents = testFiles.map(f => readFileSync(f, 'utf8'))
23
-
24
- const missing: string[] = []
25
- for (const name of toolNames) {
26
- const nameRe = new RegExp(`build(?:Read|Write|Admin)?(?:Handler)?\\(\\s*['"\`]${escapeRegExp(name)}['"\`]\\s*\\)`, 'm')
27
- const found = fileContents.some(src => nameRe.test(src))
28
- if (!found)
29
- missing.push(name)
30
- }
5
+ it('every classic_pat tool is referenced in tests', () => {
6
+ const missing = getMissingToolUsages({
7
+ integrationName: 'github',
8
+ importMetaUrl: import.meta.url,
9
+ credentialVariant: 'classic_pat',
10
+ })
11
+ expect(missing, `Missing handler usages in tests: ${missing.join(', ')}`).toEqual([])
12
+ })
31
13
 
14
+ it('every fine_grained_pat tool is referenced in tests', () => {
15
+ const missing = getMissingToolUsages({
16
+ integrationName: 'github',
17
+ importMetaUrl: import.meta.url,
18
+ credentialVariant: 'fine_grained_pat',
19
+ })
32
20
  expect(missing, `Missing handler usages in tests: ${missing.join(', ')}`).toEqual([])
33
21
  })
34
22
  })