@shipfox/api-integration-github 2.0.0

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 (179) hide show
  1. package/.turbo/turbo-build.log +2 -0
  2. package/.turbo/turbo-type$colon$emit.log +1 -0
  3. package/.turbo/turbo-type.log +1 -0
  4. package/CHANGELOG.md +138 -0
  5. package/LICENSE +21 -0
  6. package/dist/api/client.d.ts +90 -0
  7. package/dist/api/client.d.ts.map +1 -0
  8. package/dist/api/client.js +306 -0
  9. package/dist/api/client.js.map +1 -0
  10. package/dist/api/installation-token-envelope.d.ts +36 -0
  11. package/dist/api/installation-token-envelope.d.ts.map +1 -0
  12. package/dist/api/installation-token-envelope.js +123 -0
  13. package/dist/api/installation-token-envelope.js.map +1 -0
  14. package/dist/api/installation-token-provider.d.ts +23 -0
  15. package/dist/api/installation-token-provider.d.ts.map +1 -0
  16. package/dist/api/installation-token-provider.js +130 -0
  17. package/dist/api/installation-token-provider.js.map +1 -0
  18. package/dist/api/shared-installation-token-cache.d.ts +43 -0
  19. package/dist/api/shared-installation-token-cache.d.ts.map +1 -0
  20. package/dist/api/shared-installation-token-cache.js +224 -0
  21. package/dist/api/shared-installation-token-cache.js.map +1 -0
  22. package/dist/config.d.ts +15 -0
  23. package/dist/config.d.ts.map +1 -0
  24. package/dist/config.js +44 -0
  25. package/dist/config.js.map +1 -0
  26. package/dist/core/actions-logs.d.ts +47 -0
  27. package/dist/core/actions-logs.d.ts.map +1 -0
  28. package/dist/core/actions-logs.js +134 -0
  29. package/dist/core/actions-logs.js.map +1 -0
  30. package/dist/core/agent-tool-selection.d.ts +4 -0
  31. package/dist/core/agent-tool-selection.d.ts.map +1 -0
  32. package/dist/core/agent-tool-selection.js +38 -0
  33. package/dist/core/agent-tool-selection.js.map +1 -0
  34. package/dist/core/agent-tools.d.ts +50 -0
  35. package/dist/core/agent-tools.d.ts.map +1 -0
  36. package/dist/core/agent-tools.js +1122 -0
  37. package/dist/core/agent-tools.js.map +1 -0
  38. package/dist/core/errors.d.ts +15 -0
  39. package/dist/core/errors.d.ts.map +1 -0
  40. package/dist/core/errors.js +22 -0
  41. package/dist/core/errors.js.map +1 -0
  42. package/dist/core/install.d.ts +38 -0
  43. package/dist/core/install.d.ts.map +1 -0
  44. package/dist/core/install.js +64 -0
  45. package/dist/core/install.js.map +1 -0
  46. package/dist/core/source-control.d.ts +15 -0
  47. package/dist/core/source-control.d.ts.map +1 -0
  48. package/dist/core/source-control.js +175 -0
  49. package/dist/core/source-control.js.map +1 -0
  50. package/dist/core/state.d.ts +12 -0
  51. package/dist/core/state.d.ts.map +1 -0
  52. package/dist/core/state.js +54 -0
  53. package/dist/core/state.js.map +1 -0
  54. package/dist/core/webhook.d.ts +20 -0
  55. package/dist/core/webhook.d.ts.map +1 -0
  56. package/dist/core/webhook.js +216 -0
  57. package/dist/core/webhook.js.map +1 -0
  58. package/dist/db/db.d.ts +433 -0
  59. package/dist/db/db.d.ts.map +1 -0
  60. package/dist/db/db.js +18 -0
  61. package/dist/db/db.js.map +1 -0
  62. package/dist/db/installation-token-lock.d.ts +8 -0
  63. package/dist/db/installation-token-lock.d.ts.map +1 -0
  64. package/dist/db/installation-token-lock.js +37 -0
  65. package/dist/db/installation-token-lock.js.map +1 -0
  66. package/dist/db/installations.d.ts +33 -0
  67. package/dist/db/installations.d.ts.map +1 -0
  68. package/dist/db/installations.js +56 -0
  69. package/dist/db/installations.js.map +1 -0
  70. package/dist/db/migrations.d.ts +2 -0
  71. package/dist/db/migrations.d.ts.map +1 -0
  72. package/dist/db/migrations.js +5 -0
  73. package/dist/db/migrations.js.map +1 -0
  74. package/dist/db/schema/common.d.ts +2 -0
  75. package/dist/db/schema/common.d.ts.map +1 -0
  76. package/dist/db/schema/common.js +4 -0
  77. package/dist/db/schema/common.js.map +1 -0
  78. package/dist/db/schema/installations.d.ts +218 -0
  79. package/dist/db/schema/installations.d.ts.map +1 -0
  80. package/dist/db/schema/installations.js +46 -0
  81. package/dist/db/schema/installations.js.map +1 -0
  82. package/dist/index.d.ts +53 -0
  83. package/dist/index.d.ts.map +1 -0
  84. package/dist/index.js +66 -0
  85. package/dist/index.js.map +1 -0
  86. package/dist/metrics/index.d.ts +2 -0
  87. package/dist/metrics/index.d.ts.map +1 -0
  88. package/dist/metrics/index.js +3 -0
  89. package/dist/metrics/index.js.map +1 -0
  90. package/dist/metrics/instance.d.ts +14 -0
  91. package/dist/metrics/instance.d.ts.map +1 -0
  92. package/dist/metrics/instance.js +75 -0
  93. package/dist/metrics/instance.js.map +1 -0
  94. package/dist/presentation/dto/integrations.d.ts +15 -0
  95. package/dist/presentation/dto/integrations.d.ts.map +1 -0
  96. package/dist/presentation/dto/integrations.js +10 -0
  97. package/dist/presentation/dto/integrations.js.map +1 -0
  98. package/dist/presentation/e2eRoutes/create-connection.d.ts +11 -0
  99. package/dist/presentation/e2eRoutes/create-connection.d.ts.map +1 -0
  100. package/dist/presentation/e2eRoutes/create-connection.js +57 -0
  101. package/dist/presentation/e2eRoutes/create-connection.js.map +1 -0
  102. package/dist/presentation/e2eRoutes/index.d.ts +5 -0
  103. package/dist/presentation/e2eRoutes/index.d.ts.map +1 -0
  104. package/dist/presentation/e2eRoutes/index.js +11 -0
  105. package/dist/presentation/e2eRoutes/index.js.map +1 -0
  106. package/dist/presentation/routes/errors.d.ts +2 -0
  107. package/dist/presentation/routes/errors.d.ts.map +1 -0
  108. package/dist/presentation/routes/errors.js +46 -0
  109. package/dist/presentation/routes/errors.js.map +1 -0
  110. package/dist/presentation/routes/install.d.ts +13 -0
  111. package/dist/presentation/routes/install.d.ts.map +1 -0
  112. package/dist/presentation/routes/install.js +77 -0
  113. package/dist/presentation/routes/install.js.map +1 -0
  114. package/dist/presentation/routes/webhooks.d.ts +16 -0
  115. package/dist/presentation/routes/webhooks.d.ts.map +1 -0
  116. package/dist/presentation/routes/webhooks.js +110 -0
  117. package/dist/presentation/routes/webhooks.js.map +1 -0
  118. package/dist/tsconfig.test.tsbuildinfo +1 -0
  119. package/drizzle/0000_initial.sql +17 -0
  120. package/drizzle/meta/_journal.json +13 -0
  121. package/drizzle.config.ts +7 -0
  122. package/package.json +71 -0
  123. package/src/api/client.test.ts +94 -0
  124. package/src/api/client.ts +525 -0
  125. package/src/api/installation-token-envelope.ts +171 -0
  126. package/src/api/installation-token-provider.test.ts +241 -0
  127. package/src/api/installation-token-provider.ts +224 -0
  128. package/src/api/shared-installation-token-cache.test.ts +294 -0
  129. package/src/api/shared-installation-token-cache.ts +346 -0
  130. package/src/config.test.ts +14 -0
  131. package/src/config.ts +47 -0
  132. package/src/connection-external-url.test.ts +78 -0
  133. package/src/core/actions-logs.test.ts +156 -0
  134. package/src/core/actions-logs.ts +186 -0
  135. package/src/core/agent-tool-selection.test.ts +41 -0
  136. package/src/core/agent-tool-selection.ts +42 -0
  137. package/src/core/agent-tools.test.ts +539 -0
  138. package/src/core/agent-tools.ts +1269 -0
  139. package/src/core/errors.ts +23 -0
  140. package/src/core/install.test.ts +238 -0
  141. package/src/core/install.ts +119 -0
  142. package/src/core/source-control.test.ts +327 -0
  143. package/src/core/source-control.ts +223 -0
  144. package/src/core/state.test.ts +43 -0
  145. package/src/core/state.ts +85 -0
  146. package/src/core/webhook.test.ts +522 -0
  147. package/src/core/webhook.ts +296 -0
  148. package/src/db/db.ts +18 -0
  149. package/src/db/installation-token-lock.test.ts +68 -0
  150. package/src/db/installation-token-lock.ts +39 -0
  151. package/src/db/installations.test.ts +67 -0
  152. package/src/db/installations.ts +108 -0
  153. package/src/db/migrations.ts +4 -0
  154. package/src/db/schema/common.ts +3 -0
  155. package/src/db/schema/installations.ts +46 -0
  156. package/src/index.ts +124 -0
  157. package/src/metrics/index.ts +1 -0
  158. package/src/metrics/instance.ts +82 -0
  159. package/src/presentation/dto/integrations.ts +8 -0
  160. package/src/presentation/e2eRoutes/create-connection.ts +70 -0
  161. package/src/presentation/e2eRoutes/index.test.ts +126 -0
  162. package/src/presentation/e2eRoutes/index.ts +14 -0
  163. package/src/presentation/routes/errors.ts +43 -0
  164. package/src/presentation/routes/install.test.ts +279 -0
  165. package/src/presentation/routes/install.ts +93 -0
  166. package/src/presentation/routes/webhooks.test.ts +560 -0
  167. package/src/presentation/routes/webhooks.ts +115 -0
  168. package/test/env.ts +16 -0
  169. package/test/factories/github-installation.ts +35 -0
  170. package/test/factories/index.ts +1 -0
  171. package/test/fixtures/github-webhook.ts +20 -0
  172. package/test/globalSetup.ts +14 -0
  173. package/test/index.ts +2 -0
  174. package/test/setup.ts +17 -0
  175. package/tsconfig.build.json +9 -0
  176. package/tsconfig.build.tsbuildinfo +1 -0
  177. package/tsconfig.json +3 -0
  178. package/tsconfig.test.json +9 -0
  179. package/vitest.config.ts +12 -0
@@ -0,0 +1,17 @@
1
+ CREATE TABLE "integrations_github_installations" (
2
+ "id" uuid PRIMARY KEY DEFAULT uuidv7() NOT NULL,
3
+ "connection_id" uuid NOT NULL,
4
+ "installation_id" text NOT NULL,
5
+ "account_login" text NOT NULL,
6
+ "account_type" text NOT NULL,
7
+ "repository_selection" text NOT NULL,
8
+ "suspended_at" timestamp with time zone,
9
+ "deleted_at" timestamp with time zone,
10
+ "latest_event" jsonb NOT NULL,
11
+ "installer_user_id" uuid,
12
+ "created_at" timestamp with time zone DEFAULT now() NOT NULL,
13
+ "updated_at" timestamp with time zone DEFAULT now() NOT NULL
14
+ );
15
+ --> statement-breakpoint
16
+ CREATE UNIQUE INDEX "integrations_github_installations_connection_unique" ON "integrations_github_installations" USING btree ("connection_id");--> statement-breakpoint
17
+ CREATE UNIQUE INDEX "integrations_github_installations_installation_unique" ON "integrations_github_installations" USING btree ("installation_id");
@@ -0,0 +1,13 @@
1
+ {
2
+ "version": "7",
3
+ "dialect": "postgresql",
4
+ "entries": [
5
+ {
6
+ "idx": 0,
7
+ "version": "7",
8
+ "when": 1777541400000,
9
+ "tag": "0000_initial",
10
+ "breakpoints": true
11
+ }
12
+ ]
13
+ }
@@ -0,0 +1,7 @@
1
+ import {defineConfig} from 'drizzle-kit';
2
+
3
+ export default defineConfig({
4
+ schema: './src/db/schema/*.ts',
5
+ out: './drizzle',
6
+ dialect: 'postgresql',
7
+ });
package/package.json ADDED
@@ -0,0 +1,71 @@
1
+ {
2
+ "name": "@shipfox/api-integration-github",
3
+ "license": "MIT",
4
+ "version": "2.0.0",
5
+ "repository": {
6
+ "type": "git",
7
+ "url": "git+https://github.com/ShipfoxHQ/shipfox.git",
8
+ "directory": "libs/api/integration/github"
9
+ },
10
+ "private": false,
11
+ "type": "module",
12
+ "main": "dist/index.js",
13
+ "types": "dist/index.d.ts",
14
+ "imports": {
15
+ "#test/*": "./test/*",
16
+ "#*": {
17
+ "workspace-source": "./src/*",
18
+ "development": "./src/*",
19
+ "default": "./dist/*"
20
+ }
21
+ },
22
+ "exports": {
23
+ ".": {
24
+ "development": {
25
+ "types": "./src/index.ts",
26
+ "default": "./src/index.ts"
27
+ },
28
+ "default": {
29
+ "types": "./dist/index.d.ts",
30
+ "default": "./dist/index.js"
31
+ }
32
+ }
33
+ },
34
+ "dependencies": {
35
+ "@octokit/webhooks": "^14.2.0",
36
+ "drizzle-orm": "^0.45.2",
37
+ "ky": "^2.0.0",
38
+ "octokit": "^5.0.3",
39
+ "zod": "^4.4.3",
40
+ "@shipfox/api-auth-context": "2.0.0",
41
+ "@shipfox/api-integration-core-dto": "2.0.0",
42
+ "@shipfox/api-workspaces": "2.0.0",
43
+ "@shipfox/api-integration-github-dto": "2.0.0",
44
+ "@shipfox/config": "1.2.1",
45
+ "@shipfox/node-fastify": "0.2.1",
46
+ "@shipfox/node-drizzle": "0.2.1",
47
+ "@shipfox/node-postgres": "0.4.1",
48
+ "@shipfox/node-opentelemetry": "0.5.0"
49
+ },
50
+ "devDependencies": {
51
+ "@types/pg": "^8.15.5",
52
+ "drizzle-kit": "^0.31.10",
53
+ "fastify": "^5.3.3",
54
+ "fastify-type-provider-zod": "^6.0.0",
55
+ "fishery": "^2.2.2",
56
+ "@shipfox/typescript": "1.1.6",
57
+ "@shipfox/ts-config": "1.3.8",
58
+ "@shipfox/biome": "1.8.1",
59
+ "@shipfox/swc": "1.2.5",
60
+ "@shipfox/vitest": "1.2.2"
61
+ },
62
+ "scripts": {
63
+ "build": "shipfox-swc",
64
+ "check": "shipfox-biome-check",
65
+ "check:fix": "shipfox-biome-check --write",
66
+ "test": "shipfox-vitest-run",
67
+ "test:watch": "shipfox-vitest-watch",
68
+ "type": "shipfox-tsc-check",
69
+ "type:emit": "shipfox-tsc-emit"
70
+ }
71
+ }
@@ -0,0 +1,94 @@
1
+ import {GithubIntegrationProviderError} from '#core/errors.js';
2
+ import {createGithubApiClient} from './client.js';
3
+
4
+ const {createInstallationAccessTokenMock} = vi.hoisted(() => ({
5
+ createInstallationAccessTokenMock: vi.fn(),
6
+ }));
7
+
8
+ vi.mock('octokit', () => ({
9
+ App: class App {
10
+ octokit = {
11
+ rest: {apps: {createInstallationAccessToken: createInstallationAccessTokenMock}},
12
+ };
13
+ },
14
+ Octokit: {
15
+ defaults(options: unknown) {
16
+ return {defaults: options};
17
+ },
18
+ },
19
+ RequestError: class RequestError extends Error {},
20
+ }));
21
+
22
+ describe('OctokitGithubApiClient.createInstallationAccessToken', () => {
23
+ beforeEach(() => {
24
+ createInstallationAccessTokenMock.mockReset();
25
+ });
26
+
27
+ it('mints a repository-scoped, read-only installation token', async () => {
28
+ createInstallationAccessTokenMock.mockResolvedValue({
29
+ data: {token: 'ghs_installationtoken', expires_at: '2026-06-10T12:00:00.000Z'},
30
+ });
31
+ const client = createGithubApiClient();
32
+
33
+ const result = await client.createInstallationAccessToken({
34
+ installationId: 1,
35
+ repositoryId: 42,
36
+ });
37
+
38
+ expect(result).toEqual({
39
+ token: 'ghs_installationtoken',
40
+ expiresAt: new Date('2026-06-10T12:00:00.000Z'),
41
+ });
42
+ expect(createInstallationAccessTokenMock).toHaveBeenCalledWith({
43
+ installation_id: 1,
44
+ repository_ids: [42],
45
+ permissions: {contents: 'read'},
46
+ });
47
+ });
48
+
49
+ it('mints a repository-scoped write installation token when requested', async () => {
50
+ createInstallationAccessTokenMock.mockResolvedValue({
51
+ data: {token: 'ghs_installationtoken', expires_at: '2026-06-10T12:00:00.000Z'},
52
+ });
53
+ const client = createGithubApiClient();
54
+
55
+ await client.createInstallationAccessToken({
56
+ installationId: 1,
57
+ repositoryId: 42,
58
+ permissions: {contents: 'write'},
59
+ });
60
+
61
+ expect(createInstallationAccessTokenMock).toHaveBeenCalledWith({
62
+ installation_id: 1,
63
+ repository_ids: [42],
64
+ permissions: {contents: 'write'},
65
+ });
66
+ });
67
+
68
+ it('rejects a response without a token', async () => {
69
+ createInstallationAccessTokenMock.mockResolvedValue({
70
+ data: {expires_at: '2026-06-10T12:00:00.000Z'},
71
+ });
72
+ const client = createGithubApiClient();
73
+
74
+ const result = client.createInstallationAccessToken({installationId: 1, repositoryId: 42});
75
+
76
+ await expect(result).rejects.toMatchObject({
77
+ reason: 'malformed-provider-response',
78
+ });
79
+ await expect(result).rejects.toBeInstanceOf(GithubIntegrationProviderError);
80
+ });
81
+
82
+ it('rejects a response with a missing or unparseable expiry', async () => {
83
+ createInstallationAccessTokenMock.mockResolvedValue({
84
+ data: {token: 'ghs_installationtoken'},
85
+ });
86
+ const client = createGithubApiClient();
87
+
88
+ const result = client.createInstallationAccessToken({installationId: 1, repositoryId: 42});
89
+
90
+ await expect(result).rejects.toMatchObject({
91
+ reason: 'malformed-provider-response',
92
+ });
93
+ });
94
+ });