@fragno-dev/github-app-fragment 0.0.1

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 (104) hide show
  1. package/LICENSE.md +16 -0
  2. package/README.md +163 -0
  3. package/bin/run.js +5 -0
  4. package/dist/browser/client/react.d.ts +37 -0
  5. package/dist/browser/client/react.d.ts.map +1 -0
  6. package/dist/browser/client/react.js +166 -0
  7. package/dist/browser/client/react.js.map +1 -0
  8. package/dist/browser/client/solid.d.ts +35 -0
  9. package/dist/browser/client/solid.d.ts.map +1 -0
  10. package/dist/browser/client/solid.js +136 -0
  11. package/dist/browser/client/solid.js.map +1 -0
  12. package/dist/browser/client/svelte.d.ts +30 -0
  13. package/dist/browser/client/svelte.d.ts.map +1 -0
  14. package/dist/browser/client/svelte.js +134 -0
  15. package/dist/browser/client/svelte.js.map +1 -0
  16. package/dist/browser/client/vanilla.d.ts +16 -0
  17. package/dist/browser/client/vanilla.d.ts.map +1 -0
  18. package/dist/browser/client/vanilla.js +11 -0
  19. package/dist/browser/client/vanilla.js.map +1 -0
  20. package/dist/browser/client/vue.d.ts +33 -0
  21. package/dist/browser/client/vue.d.ts.map +1 -0
  22. package/dist/browser/client/vue.js +133 -0
  23. package/dist/browser/client/vue.js.map +1 -0
  24. package/dist/browser/factory-BIj4C6PD.js +2210 -0
  25. package/dist/browser/factory-BIj4C6PD.js.map +1 -0
  26. package/dist/browser/index.d.ts +343 -0
  27. package/dist/browser/index.d.ts.map +1 -0
  28. package/dist/browser/index.js +3 -0
  29. package/dist/browser/types-BzeSSOQU.d.ts +660 -0
  30. package/dist/browser/types-BzeSSOQU.d.ts.map +1 -0
  31. package/dist/cli/commands/installations.js +92 -0
  32. package/dist/cli/commands/installations.js.map +1 -0
  33. package/dist/cli/commands/pulls.js +123 -0
  34. package/dist/cli/commands/pulls.js.map +1 -0
  35. package/dist/cli/commands/repositories.js +105 -0
  36. package/dist/cli/commands/repositories.js.map +1 -0
  37. package/dist/cli/commands/serve.js +187 -0
  38. package/dist/cli/commands/serve.js.map +1 -0
  39. package/dist/cli/commands/webhooks.js +122 -0
  40. package/dist/cli/commands/webhooks.js.map +1 -0
  41. package/dist/cli/github/api.js +94 -0
  42. package/dist/cli/github/api.js.map +1 -0
  43. package/dist/cli/github/definition.js +15 -0
  44. package/dist/cli/github/definition.js.map +1 -0
  45. package/dist/cli/github/factory.js +12 -0
  46. package/dist/cli/github/factory.js.map +1 -0
  47. package/dist/cli/github/repo-sync.js +33 -0
  48. package/dist/cli/github/repo-sync.js.map +1 -0
  49. package/dist/cli/github/utils.js +23 -0
  50. package/dist/cli/github/utils.js.map +1 -0
  51. package/dist/cli/github/webhook-processing.js +247 -0
  52. package/dist/cli/github/webhook-processing.js.map +1 -0
  53. package/dist/cli/index.d.ts +5 -0
  54. package/dist/cli/index.d.ts.map +1 -0
  55. package/dist/cli/index.js +263 -0
  56. package/dist/cli/index.js.map +1 -0
  57. package/dist/cli/routes.js +718 -0
  58. package/dist/cli/routes.js.map +1 -0
  59. package/dist/cli/schema.js +47 -0
  60. package/dist/cli/schema.js.map +1 -0
  61. package/dist/cli/utils/client.js +120 -0
  62. package/dist/cli/utils/client.js.map +1 -0
  63. package/dist/cli/utils/config.js +113 -0
  64. package/dist/cli/utils/config.js.map +1 -0
  65. package/dist/cli/utils/options.js +90 -0
  66. package/dist/cli/utils/options.js.map +1 -0
  67. package/dist/cli/utils/output.js +12 -0
  68. package/dist/cli/utils/output.js.map +1 -0
  69. package/dist/node/github/api.d.ts +52 -0
  70. package/dist/node/github/api.d.ts.map +1 -0
  71. package/dist/node/github/api.js +94 -0
  72. package/dist/node/github/api.js.map +1 -0
  73. package/dist/node/github/clients.d.ts +19 -0
  74. package/dist/node/github/clients.d.ts.map +1 -0
  75. package/dist/node/github/clients.js +12 -0
  76. package/dist/node/github/clients.js.map +1 -0
  77. package/dist/node/github/definition.d.ts +33 -0
  78. package/dist/node/github/definition.d.ts.map +1 -0
  79. package/dist/node/github/definition.js +15 -0
  80. package/dist/node/github/definition.js.map +1 -0
  81. package/dist/node/github/factory.d.ts +139 -0
  82. package/dist/node/github/factory.d.ts.map +1 -0
  83. package/dist/node/github/factory.js +18 -0
  84. package/dist/node/github/factory.js.map +1 -0
  85. package/dist/node/github/repo-sync.js +33 -0
  86. package/dist/node/github/repo-sync.js.map +1 -0
  87. package/dist/node/github/types.d.ts +24 -0
  88. package/dist/node/github/types.d.ts.map +1 -0
  89. package/dist/node/github/utils.js +23 -0
  90. package/dist/node/github/utils.js.map +1 -0
  91. package/dist/node/github/webhook-processing.d.ts +15 -0
  92. package/dist/node/github/webhook-processing.d.ts.map +1 -0
  93. package/dist/node/github/webhook-processing.js +247 -0
  94. package/dist/node/github/webhook-processing.js.map +1 -0
  95. package/dist/node/index.d.ts +7 -0
  96. package/dist/node/index.js +6 -0
  97. package/dist/node/routes.d.ts +127 -0
  98. package/dist/node/routes.d.ts.map +1 -0
  99. package/dist/node/routes.js +718 -0
  100. package/dist/node/routes.js.map +1 -0
  101. package/dist/node/schema.js +47 -0
  102. package/dist/node/schema.js.map +1 -0
  103. package/dist/tsconfig.tsbuildinfo +1 -0
  104. package/package.json +114 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"routes.js","names":[],"sources":["../../src/routes.ts"],"sourcesContent":["import type { TableToColumnValues } from \"@fragno-dev/db/query\";\nimport { FragnoId } from \"@fragno-dev/db/schema\";\nimport { z } from \"zod\";\n\nimport { defineRoutes } from \"@fragno-dev/core\";\n\nimport type { GitHubInstallationDetails, GitHubInstallationRepository } from \"./github/api\";\nimport { githubAppFragmentDefinition } from \"./github/definition\";\nimport { hasRepoChanges, toRepoCreateRecord, toRepoRecord } from \"./github/repo-sync\";\nimport {\n isRecord,\n normalizeJoinedInstallation,\n normalizeJoinedLinks,\n toExternalId,\n toStringValue,\n} from \"./github/utils\";\nimport type { WebhookProcessingPayload } from \"./github/webhook-processing\";\nimport { githubAppSchema } from \"./schema\";\n\ntype InstallationRepoRow = TableToColumnValues<\n (typeof githubAppSchema)[\"tables\"][\"installation_repo\"]\n>;\ntype RepoLinkRow = TableToColumnValues<(typeof githubAppSchema)[\"tables\"][\"repo_link\"]>;\ntype RepoId = string | FragnoId;\ntype RepoLinkId = string | FragnoId;\n\nconst toDebugSignature = (signatureHeader: string | null) => {\n if (!signatureHeader) {\n return null;\n }\n if (signatureHeader.length <= 20) {\n return signatureHeader;\n }\n return `${signatureHeader.slice(0, 12)}…${signatureHeader.slice(-8)}`;\n};\n\nconst normalizeLinkKey = (linkKey: string | null | undefined, defaultLinkKey?: string) => {\n const normalized = linkKey?.trim();\n return normalized && normalized.length > 0 ? normalized : (defaultLinkKey ?? \"default\");\n};\n\nconst parseLinkedOnly = (value: string | null) => value === \"true\" || value === \"1\";\n\nconst getHttpStatusCode = (value: unknown): number | null => {\n if (typeof value === \"number\" && Number.isFinite(value)) {\n return value;\n }\n if (typeof value === \"object\" && value && \"status\" in value) {\n const status = (value as { status?: unknown }).status;\n if (typeof status === \"number\" && Number.isFinite(status)) {\n return status;\n }\n }\n return null;\n};\n\nconst installationOutputSchema = z.object({\n id: z.string(),\n accountId: z.string(),\n accountLogin: z.string(),\n accountType: z.string(),\n status: z.string(),\n permissions: z.any(),\n events: z.any(),\n createdAt: z.date(),\n updatedAt: z.date(),\n lastWebhookAt: z.date().nullable(),\n});\n\nconst repoSummarySchema = z.object({\n id: z.string(),\n installationId: z.string(),\n ownerLogin: z.string(),\n name: z.string(),\n fullName: z.string(),\n isPrivate: z.boolean(),\n isFork: z.boolean().nullable(),\n defaultBranch: z.string().nullable(),\n removedAt: z.date().nullable(),\n updatedAt: z.date(),\n});\n\nconst repoWithLinksSchema = repoSummarySchema.extend({\n linkKeys: z.array(z.string()),\n});\n\nconst repoLinkOutputSchema = z.object({\n id: z.string(),\n repoId: z.string(),\n linkKey: z.string(),\n linkedAt: z.date(),\n});\n\nexport const githubAppRoutesFactory = defineRoutes(githubAppFragmentDefinition).create(\n ({ config, defineRoute, deps }) => {\n const api = deps.githubApiClient;\n\n return [\n defineRoute({\n method: \"POST\",\n path: \"/webhooks\",\n errorCodes: [\n \"WEBHOOK_SIGNATURE_INVALID\",\n \"WEBHOOK_DELIVERY_MISSING\",\n \"WEBHOOK_PAYLOAD_INVALID\",\n ],\n handler: async function (ctx, { empty, error }) {\n const rawBody = ctx.rawBody;\n const logWebhook =\n config.webhookDebug === true\n ? (message: string, details?: Record<string, unknown>) => {\n if (details) {\n console.log(\"[github-app-fragment webhook]\", message, details);\n } else {\n console.log(\"[github-app-fragment webhook]\", message);\n }\n }\n : undefined;\n\n logWebhook?.(\"received\", {\n hasRawBody: Boolean(rawBody),\n rawBodyBytes: rawBody ? Buffer.byteLength(rawBody, \"utf8\") : 0,\n signature: toDebugSignature(ctx.headers.get(\"x-hub-signature-256\")),\n deliveryId: ctx.headers.get(\"x-github-delivery\") ?? null,\n event: ctx.headers.get(\"x-github-event\") ?? null,\n contentType: ctx.headers.get(\"content-type\") ?? null,\n });\n\n if (!rawBody) {\n logWebhook?.(\"rejected: missing payload\");\n return error(\n { message: \"Missing webhook payload.\", code: \"WEBHOOK_PAYLOAD_INVALID\" },\n { status: 400 },\n );\n }\n\n const signatureHeader = ctx.headers.get(\"x-hub-signature-256\");\n const signatureOk = await api.verifyWebhookSignature({\n payload: rawBody,\n signatureHeader,\n });\n logWebhook?.(\"signature check\", { ok: signatureOk });\n if (!signatureOk) {\n logWebhook?.(\"rejected: invalid signature\");\n return error(\n { message: \"Invalid webhook signature.\", code: \"WEBHOOK_SIGNATURE_INVALID\" },\n { status: 401 },\n );\n }\n\n const deliveryId = ctx.headers.get(\"x-github-delivery\") ?? \"\";\n if (!deliveryId) {\n logWebhook?.(\"rejected: missing delivery id\");\n return error(\n { message: \"Missing delivery id.\", code: \"WEBHOOK_DELIVERY_MISSING\" },\n { status: 400 },\n );\n }\n\n const event = ctx.headers.get(\"x-github-event\") ?? \"\";\n if (!event) {\n logWebhook?.(\"rejected: missing event\");\n return error(\n { message: \"Missing webhook event type.\", code: \"WEBHOOK_PAYLOAD_INVALID\" },\n { status: 400 },\n );\n }\n\n let payload: unknown;\n try {\n payload = JSON.parse(rawBody);\n } catch {\n logWebhook?.(\"rejected: invalid json\");\n return error(\n { message: \"Invalid JSON payload.\", code: \"WEBHOOK_PAYLOAD_INVALID\" },\n { status: 400 },\n );\n }\n\n if (!isRecord(payload)) {\n logWebhook?.(\"rejected: payload not object\");\n return error(\n { message: \"Invalid webhook payload.\", code: \"WEBHOOK_PAYLOAD_INVALID\" },\n { status: 400 },\n );\n }\n\n const action =\n typeof payload[\"action\"] === \"string\" ? (payload[\"action\"] as string) : null;\n const installationPayload = isRecord(payload[\"installation\"])\n ? payload[\"installation\"]\n : null;\n\n const installationId = toStringValue(\n installationPayload?.[\"id\"] ?? payload[\"installation_id\"],\n );\n if (!installationId) {\n logWebhook?.(\"rejected: missing installation id\");\n return error(\n { message: \"Missing installation id.\", code: \"WEBHOOK_PAYLOAD_INVALID\" },\n { status: 400 },\n );\n }\n\n const now = new Date();\n logWebhook?.(\"accepted\", {\n deliveryId,\n event,\n action,\n installationId,\n });\n const webhookPayload: WebhookProcessingPayload = {\n deliveryId,\n event,\n action,\n installationId,\n payload,\n receivedAt: now.toISOString(),\n };\n\n await this.handlerTx()\n .mutate(({ forSchema }) => {\n const uow = forSchema(githubAppSchema);\n uow.triggerHook(\"processWebhook\", webhookPayload);\n })\n .execute();\n\n return empty(204);\n },\n }),\n defineRoute({\n method: \"GET\",\n path: \"/installations\",\n queryParameters: [\"status\"],\n outputSchema: z.array(installationOutputSchema),\n errorCodes: [\"INVALID_STATUS\"],\n handler: async function ({ query }, { json, error }) {\n const status = query.get(\"status\");\n if (status && ![\"active\", \"suspended\", \"deleted\"].includes(status)) {\n return error(\n { message: `Invalid status: ${status}`, code: \"INVALID_STATUS\" },\n { status: 400 },\n );\n }\n\n const [installations] = await this.handlerTx()\n .retrieve(({ forSchema }) => {\n const uow = forSchema(githubAppSchema);\n if (status) {\n return uow.find(\"installation\", (b) =>\n b.whereIndex(\"idx_installation_status\", (eb) => eb(\"status\", \"=\", status)),\n );\n }\n return uow.find(\"installation\", (b) =>\n b.whereIndex(\"idx_installation_status\", (eb) => eb(\"status\", \"!=\", \"\")),\n );\n })\n .execute();\n\n return json(\n installations.map((installation) => ({\n id: toExternalId(installation.id),\n accountId: installation.accountId,\n accountLogin: installation.accountLogin,\n accountType: installation.accountType,\n status: installation.status,\n permissions: installation.permissions,\n events: installation.events,\n createdAt: installation.createdAt,\n updatedAt: installation.updatedAt,\n lastWebhookAt: installation.lastWebhookAt,\n })),\n );\n },\n }),\n defineRoute({\n method: \"GET\",\n path: \"/installations/:installationId/repos\",\n queryParameters: [\"linkedOnly\", \"linkKey\"],\n outputSchema: z.array(repoWithLinksSchema),\n errorCodes: [\"INSTALLATION_NOT_FOUND\"],\n handler: async function ({ pathParams, query }, { json, error }) {\n const installationId = pathParams.installationId;\n const linkedOnly = parseLinkedOnly(query.get(\"linkedOnly\"));\n const linkKeyFilter = query.get(\"linkKey\")?.trim() ?? null;\n\n const [installation, repos] = await this.handlerTx()\n .retrieve(({ forSchema }) => {\n const uow = forSchema(githubAppSchema);\n return uow\n .findFirst(\"installation\", (b) =>\n b.whereIndex(\"uniq_installation_id\", (eb) => eb(\"id\", \"=\", installationId)),\n )\n .find(\"installation_repo\", (b) =>\n b\n .whereIndex(\"idx_installation_repo_installation\", (eb) =>\n eb(\"installationId\", \"=\", installationId),\n )\n .join((jb) => jb.links()),\n );\n })\n .execute();\n\n if (!installation) {\n return error(\n { message: \"Installation not found.\", code: \"INSTALLATION_NOT_FOUND\" },\n { status: 404 },\n );\n }\n\n const output = [];\n for (const repo of repos) {\n if (repo.removedAt !== null) {\n continue;\n }\n const repoId = toExternalId(repo.id);\n if (!repoId) {\n continue;\n }\n const linkEntries = normalizeJoinedLinks(repo.links);\n const linkKeys = linkEntries\n .filter((link) => !linkKeyFilter || link.linkKey === linkKeyFilter)\n .map((link) => link.linkKey);\n if (linkedOnly && linkKeys.length === 0) {\n continue;\n }\n output.push({\n id: repoId,\n installationId,\n ownerLogin: repo.ownerLogin ?? \"\",\n name: repo.name ?? \"\",\n fullName: repo.fullName ?? \"\",\n isPrivate: Boolean(repo.isPrivate),\n isFork: repo.isFork ?? null,\n defaultBranch: repo.defaultBranch ?? null,\n removedAt: repo.removedAt ?? null,\n updatedAt: repo.updatedAt,\n linkKeys,\n });\n }\n\n return json(output);\n },\n }),\n defineRoute({\n method: \"GET\",\n path: \"/repositories/linked\",\n queryParameters: [\"linkKey\"],\n outputSchema: z.array(repoWithLinksSchema),\n handler: async function ({ query }, { json }) {\n const linkKeyFilter = query.get(\"linkKey\")?.trim() ?? null;\n\n const [repos] = await this.handlerTx()\n .retrieve(({ forSchema }) => {\n const uow = forSchema(githubAppSchema);\n return uow.find(\"installation_repo\", (b) =>\n b\n .whereIndex(\"idx_installation_repo_full_name\", (eb) => eb(\"fullName\", \"!=\", \"\"))\n .join((jb) => jb.installation().links()),\n );\n })\n .execute();\n\n const output = [];\n for (const repo of repos) {\n if (repo.removedAt !== null) {\n continue;\n }\n const repoId = toExternalId(repo.id);\n if (!repoId) {\n continue;\n }\n const installation = normalizeJoinedInstallation(repo.installation);\n if (!installation || installation.status !== \"active\") {\n continue;\n }\n const linkEntries = normalizeJoinedLinks(repo.links);\n const linkKeys = linkEntries\n .filter((link) => !linkKeyFilter || link.linkKey === linkKeyFilter)\n .map((link) => link.linkKey);\n if (linkKeys.length === 0) {\n continue;\n }\n output.push({\n id: repoId,\n installationId: toExternalId(installation.id),\n ownerLogin: repo.ownerLogin ?? \"\",\n name: repo.name ?? \"\",\n fullName: repo.fullName ?? \"\",\n isPrivate: Boolean(repo.isPrivate),\n isFork: repo.isFork ?? null,\n defaultBranch: repo.defaultBranch ?? null,\n removedAt: repo.removedAt ?? null,\n updatedAt: repo.updatedAt,\n linkKeys,\n });\n }\n\n return json(output);\n },\n }),\n defineRoute({\n method: \"POST\",\n path: \"/repositories/link\",\n inputSchema: z.object({\n installationId: z.string(),\n repoId: z.string(),\n linkKey: z.string().optional(),\n }),\n outputSchema: z.object({\n link: repoLinkOutputSchema,\n repo: repoSummarySchema,\n }),\n errorCodes: [\n \"INSTALLATION_NOT_FOUND\",\n \"INSTALLATION_INACTIVE\",\n \"REPO_NOT_FOUND\",\n \"REPO_REMOVED\",\n ],\n handler: async function ({ input }, { json, error }) {\n const values = await input.valid();\n const linkKey = normalizeLinkKey(values.linkKey, config.defaultLinkKey);\n\n const [installation, repos] = await this.handlerTx()\n .retrieve(({ forSchema }) => {\n const uow = forSchema(githubAppSchema);\n return uow\n .findFirst(\"installation\", (b) =>\n b.whereIndex(\"uniq_installation_id\", (eb) =>\n eb(\"id\", \"=\", values.installationId),\n ),\n )\n .find(\"installation_repo\", (b) =>\n b\n .whereIndex(\"idx_installation_repo_installation\", (eb) =>\n eb(\"installationId\", \"=\", values.installationId),\n )\n .join((jb) => jb.links()),\n );\n })\n .execute();\n\n if (!installation) {\n return error(\n { message: \"Installation not found.\", code: \"INSTALLATION_NOT_FOUND\" },\n { status: 404 },\n );\n }\n\n if (installation.status !== \"active\") {\n return error(\n { message: \"Installation is not active.\", code: \"INSTALLATION_INACTIVE\" },\n { status: 409 },\n );\n }\n\n const repo = repos.find((record) => toExternalId(record.id) === values.repoId);\n if (!repo) {\n return error(\n { message: \"Repository not found.\", code: \"REPO_NOT_FOUND\" },\n { status: 404 },\n );\n }\n\n if (repo.removedAt !== null) {\n return error(\n { message: \"Repository has been removed.\", code: \"REPO_REMOVED\" },\n { status: 409 },\n );\n }\n\n const linkEntries = normalizeJoinedLinks(repo.links);\n const existingLink = linkEntries.find((link) => link.linkKey === linkKey);\n\n if (existingLink) {\n return json({\n link: {\n id: toExternalId(existingLink.id),\n repoId: values.repoId,\n linkKey: existingLink.linkKey,\n linkedAt: existingLink.linkedAt,\n },\n repo: {\n id: values.repoId,\n installationId: values.installationId,\n ownerLogin: repo.ownerLogin ?? \"\",\n name: repo.name ?? \"\",\n fullName: repo.fullName ?? \"\",\n isPrivate: Boolean(repo.isPrivate),\n isFork: repo.isFork ?? null,\n defaultBranch: repo.defaultBranch ?? null,\n removedAt: repo.removedAt ?? null,\n updatedAt: repo.updatedAt,\n },\n });\n }\n\n const linkedAt = new Date();\n const linkId = await this.handlerTx()\n .mutate(({ forSchema }) => {\n const uow = forSchema(githubAppSchema);\n return uow.create(\"repo_link\", {\n repoId: values.repoId,\n linkKey,\n linkedAt,\n });\n })\n .execute();\n\n return json({\n link: {\n id: toExternalId(linkId),\n repoId: values.repoId,\n linkKey,\n linkedAt,\n },\n repo: {\n id: values.repoId,\n installationId: values.installationId,\n ownerLogin: repo.ownerLogin ?? \"\",\n name: repo.name ?? \"\",\n fullName: repo.fullName ?? \"\",\n isPrivate: Boolean(repo.isPrivate),\n isFork: repo.isFork ?? null,\n defaultBranch: repo.defaultBranch ?? null,\n removedAt: repo.removedAt ?? null,\n updatedAt: repo.updatedAt,\n },\n });\n },\n }),\n defineRoute({\n method: \"POST\",\n path: \"/repositories/unlink\",\n inputSchema: z.object({\n repoId: z.string(),\n linkKey: z.string().optional(),\n }),\n outputSchema: z.object({ ok: z.literal(true) }),\n errorCodes: [\n \"REPO_NOT_FOUND\",\n \"INSTALLATION_NOT_FOUND\",\n \"INSTALLATION_INACTIVE\",\n \"LINK_NOT_FOUND\",\n ],\n handler: async function ({ input }, { json, error }) {\n const values = await input.valid();\n const linkKey = normalizeLinkKey(values.linkKey, config.defaultLinkKey);\n\n const [repos] = await this.handlerTx()\n .retrieve(({ forSchema }) => {\n const uow = forSchema(githubAppSchema);\n return uow.find(\"installation_repo\", (b) =>\n b\n .whereIndex(\"idx_installation_repo_full_name\", (eb) => eb(\"fullName\", \"!=\", \"\"))\n .join((jb) => jb.installation().links()),\n );\n })\n .execute();\n\n const repo = repos.find((record) => toExternalId(record.id) === values.repoId);\n if (!repo) {\n return error(\n { message: \"Repository not found.\", code: \"REPO_NOT_FOUND\" },\n { status: 404 },\n );\n }\n\n const installation = normalizeJoinedInstallation(repo.installation);\n\n if (!installation) {\n return error(\n { message: \"Installation not found.\", code: \"INSTALLATION_NOT_FOUND\" },\n { status: 404 },\n );\n }\n\n if (installation.status !== \"active\") {\n return error(\n { message: \"Installation is not active.\", code: \"INSTALLATION_INACTIVE\" },\n { status: 409 },\n );\n }\n\n const linkEntries = normalizeJoinedLinks(repo.links);\n const link = linkEntries.find((entry) => entry.linkKey === linkKey);\n\n if (!link) {\n return error({ message: \"Link not found.\", code: \"LINK_NOT_FOUND\" }, { status: 404 });\n }\n\n await this.handlerTx()\n .mutate(({ forSchema }) => {\n const uow = forSchema(githubAppSchema);\n uow.delete(\"repo_link\", link.id as RepoLinkId);\n })\n .execute();\n\n return json({ ok: true });\n },\n }),\n defineRoute({\n method: \"GET\",\n path: \"/repositories/:owner/:repo/pulls\",\n queryParameters: [\"state\", \"perPage\", \"page\"],\n outputSchema: z.object({\n pulls: z.array(z.any()),\n pageInfo: z.object({\n page: z.number(),\n perPage: z.number(),\n }),\n }),\n errorCodes: [\n \"INVALID_STATE\",\n \"INVALID_PER_PAGE\",\n \"INVALID_PAGE\",\n \"REPO_NOT_FOUND\",\n \"REPO_REMOVED\",\n \"REPO_NOT_LINKED\",\n \"INSTALLATION_NOT_FOUND\",\n \"INSTALLATION_INACTIVE\",\n \"GITHUB_API_ERROR\",\n ],\n handler: async function ({ pathParams, query }, { json, error }) {\n const state = query.get(\"state\");\n if (state && ![\"open\", \"closed\", \"all\"].includes(state)) {\n return error(\n { message: `Invalid state: ${state}`, code: \"INVALID_STATE\" },\n { status: 400 },\n );\n }\n const stateFilter = (state ?? undefined) as \"open\" | \"closed\" | \"all\" | undefined;\n\n const perPageRaw = query.get(\"perPage\");\n const perPage = perPageRaw ? Number.parseInt(perPageRaw, 10) : 30;\n if (!Number.isFinite(perPage) || perPage <= 0 || perPage > 100) {\n return error(\n { message: \"perPage must be between 1 and 100.\", code: \"INVALID_PER_PAGE\" },\n { status: 400 },\n );\n }\n\n const pageRaw = query.get(\"page\");\n const page = pageRaw ? Number.parseInt(pageRaw, 10) : 1;\n if (!Number.isFinite(page) || page <= 0) {\n return error(\n { message: \"page must be a positive number.\", code: \"INVALID_PAGE\" },\n { status: 400 },\n );\n }\n\n const fullName = `${pathParams.owner}/${pathParams.repo}`;\n const [repos] = await this.handlerTx()\n .retrieve(({ forSchema }) => {\n const uow = forSchema(githubAppSchema);\n return uow.find(\"installation_repo\", (b) =>\n b\n .whereIndex(\"idx_installation_repo_full_name\", (eb) =>\n eb(\"fullName\", \"=\", fullName),\n )\n .join((jb) => jb.installation().links()),\n );\n })\n .execute();\n\n const repo = repos[0];\n if (!repo) {\n return error(\n { message: \"Repository not found.\", code: \"REPO_NOT_FOUND\" },\n { status: 404 },\n );\n }\n\n if (repo.removedAt !== null) {\n return error(\n { message: \"Repository has been removed.\", code: \"REPO_REMOVED\" },\n { status: 409 },\n );\n }\n\n const installation = normalizeJoinedInstallation(repo.installation);\n\n if (!installation) {\n return error(\n { message: \"Installation not found.\", code: \"INSTALLATION_NOT_FOUND\" },\n { status: 404 },\n );\n }\n\n if (installation.status !== \"active\") {\n return error(\n { message: \"Installation is not active.\", code: \"INSTALLATION_INACTIVE\" },\n { status: 409 },\n );\n }\n\n const installationId = toExternalId(installation.id);\n\n const linkEntries = normalizeJoinedLinks(repo.links);\n const linked = linkEntries.length > 0;\n\n if (!linked) {\n return error(\n { message: \"Repository is not linked.\", code: \"REPO_NOT_LINKED\" },\n { status: 403 },\n );\n }\n\n let pulls: unknown[];\n try {\n const installationOctokit = await api.app.getInstallationOctokit(\n api.resolveInstallationId(installationId),\n );\n const response = await installationOctokit.request(\"GET /repos/{owner}/{repo}/pulls\", {\n owner: pathParams.owner,\n repo: pathParams.repo,\n state: stateFilter,\n per_page: perPage,\n page,\n });\n pulls = response.data;\n } catch (err) {\n const message = err instanceof Error ? err.message : \"GitHub API request failed.\";\n return error({ message, code: \"GITHUB_API_ERROR\" }, { status: 502 });\n }\n\n return json({ pulls, pageInfo: { page, perPage } });\n },\n }),\n defineRoute({\n method: \"POST\",\n path: \"/repositories/:owner/:repo/pulls/:number/reviews\",\n inputSchema: z.object({\n event: z.enum([\"APPROVE\", \"REQUEST_CHANGES\", \"COMMENT\"]).optional(),\n body: z.string().optional(),\n comments: z.array(z.any()).optional(),\n commitId: z.string().optional(),\n }),\n outputSchema: z.object({ review: z.any() }),\n errorCodes: [\n \"INVALID_PULL_NUMBER\",\n \"REPO_NOT_FOUND\",\n \"REPO_REMOVED\",\n \"REPO_NOT_LINKED\",\n \"INSTALLATION_NOT_FOUND\",\n \"INSTALLATION_INACTIVE\",\n \"GITHUB_API_ERROR\",\n ],\n handler: async function ({ pathParams, input }, { json, error }) {\n const values = await input.valid();\n const pullNumber = Number.parseInt(pathParams.number, 10);\n if (!Number.isFinite(pullNumber) || pullNumber <= 0) {\n return error(\n { message: \"Invalid pull request number.\", code: \"INVALID_PULL_NUMBER\" },\n { status: 400 },\n );\n }\n\n const fullName = `${pathParams.owner}/${pathParams.repo}`;\n const [repos] = await this.handlerTx()\n .retrieve(({ forSchema }) => {\n const uow = forSchema(githubAppSchema);\n return uow.find(\"installation_repo\", (b) =>\n b\n .whereIndex(\"idx_installation_repo_full_name\", (eb) =>\n eb(\"fullName\", \"=\", fullName),\n )\n .join((jb) => jb.installation().links()),\n );\n })\n .execute();\n\n const repo = repos[0];\n if (!repo) {\n return error(\n { message: \"Repository not found.\", code: \"REPO_NOT_FOUND\" },\n { status: 404 },\n );\n }\n\n if (repo.removedAt !== null) {\n return error(\n { message: \"Repository has been removed.\", code: \"REPO_REMOVED\" },\n { status: 409 },\n );\n }\n\n const installation = normalizeJoinedInstallation(repo.installation);\n\n if (!installation) {\n return error(\n { message: \"Installation not found.\", code: \"INSTALLATION_NOT_FOUND\" },\n { status: 404 },\n );\n }\n\n if (installation.status !== \"active\") {\n return error(\n { message: \"Installation is not active.\", code: \"INSTALLATION_INACTIVE\" },\n { status: 409 },\n );\n }\n\n const installationId = toExternalId(installation.id);\n\n const linkEntries = normalizeJoinedLinks(repo.links);\n const linked = linkEntries.length > 0;\n\n if (!linked) {\n return error(\n { message: \"Repository is not linked.\", code: \"REPO_NOT_LINKED\" },\n { status: 403 },\n );\n }\n\n let review: unknown;\n try {\n const installationOctokit = await api.app.getInstallationOctokit(\n api.resolveInstallationId(installationId),\n );\n const response = await installationOctokit.request(\n \"POST /repos/{owner}/{repo}/pulls/{pull_number}/reviews\",\n {\n owner: pathParams.owner,\n repo: pathParams.repo,\n pull_number: pullNumber,\n event: values.event,\n body: values.body,\n comments: values.comments,\n commit_id: values.commitId,\n },\n );\n review = response.data;\n } catch (err) {\n const message = err instanceof Error ? err.message : \"GitHub API request failed.\";\n return error({ message, code: \"GITHUB_API_ERROR\" }, { status: 502 });\n }\n\n return json({ review });\n },\n }),\n defineRoute({\n method: \"POST\",\n path: \"/installations/:installationId/sync\",\n outputSchema: z.object({\n added: z.number(),\n removed: z.number(),\n updated: z.number(),\n }),\n errorCodes: [\"GITHUB_API_ERROR\", \"INSTALLATION_NOT_FOUND\"],\n handler: async function ({ pathParams }, { json, error }) {\n const installationId = pathParams.installationId;\n let bootstrapInstallation: GitHubInstallationDetails | null = null;\n\n const [existingInstallation, existingRepos] = await this.handlerTx()\n .retrieve(({ forSchema }) => {\n const uow = forSchema(githubAppSchema);\n return uow\n .findFirst(\"installation\", (b) =>\n b.whereIndex(\"uniq_installation_id\", (eb) => eb(\"id\", \"=\", installationId)),\n )\n .find(\"installation_repo\", (b) =>\n b\n .whereIndex(\"idx_installation_repo_installation\", (eb) =>\n eb(\"installationId\", \"=\", installationId),\n )\n .join((jb) => jb.links()),\n );\n })\n .execute();\n\n if (!existingInstallation) {\n try {\n bootstrapInstallation = await api.getInstallation(installationId);\n } catch (err) {\n if (getHttpStatusCode(err) === 404) {\n return error(\n { message: \"Installation not found.\", code: \"INSTALLATION_NOT_FOUND\" },\n { status: 404 },\n );\n }\n const message = err instanceof Error ? err.message : \"GitHub API request failed.\";\n return error({ message, code: \"GITHUB_API_ERROR\" }, { status: 502 });\n }\n }\n\n let response: { repositories: GitHubInstallationRepository[] };\n try {\n response = await api.listInstallationRepos(installationId);\n } catch (err) {\n const message = err instanceof Error ? err.message : \"GitHub API request failed.\";\n return error({ message, code: \"GITHUB_API_ERROR\" }, { status: 502 });\n }\n\n const repos = response.repositories ?? [];\n const now = new Date();\n\n const existingById = new Map<string, InstallationRepoRow>();\n for (const repo of existingRepos) {\n const id = toExternalId(repo.id);\n if (id) {\n existingById.set(id, repo);\n }\n }\n\n const repoLinksByRepoId = new Map<string, RepoLinkRow[]>();\n for (const repo of existingRepos) {\n const repoId = toExternalId(repo.id);\n if (!repoId) {\n continue;\n }\n const linkEntries = normalizeJoinedLinks(repo.links);\n if (linkEntries.length === 0) {\n continue;\n }\n repoLinksByRepoId.set(repoId, linkEntries);\n }\n\n let added = 0;\n let updated = 0;\n let removed = 0;\n\n type RepoUpdateData = Omit<ReturnType<typeof toRepoRecord>, \"id\">;\n const creates: Array<ReturnType<typeof toRepoRecord>> = [];\n const updates: Array<{ id: RepoId; data: Partial<RepoUpdateData> }> = [];\n const removals: Array<RepoId> = [];\n const linksToDelete: Array<RepoLinkId> = [];\n\n const seen = new Set<string>();\n\n for (const repo of repos) {\n const record = toRepoRecord(installationId, repo, now);\n seen.add(record.id);\n const existing = existingById.get(record.id);\n\n if (!existing) {\n added += 1;\n creates.push(record);\n continue;\n }\n\n if (hasRepoChanges(existing, record)) {\n updated += 1;\n updates.push({\n id: existing.id as RepoId,\n data: {\n installationId: record.installationId,\n ownerLogin: record.ownerLogin,\n name: record.name,\n fullName: record.fullName,\n isPrivate: record.isPrivate,\n ...(record.isFork !== undefined ? { isFork: record.isFork } : {}),\n ...(record.defaultBranch !== undefined\n ? { defaultBranch: record.defaultBranch }\n : {}),\n removedAt: null,\n updatedAt: now,\n },\n });\n }\n }\n\n for (const [repoId, repo] of existingById.entries()) {\n if (seen.has(repoId)) {\n continue;\n }\n if (repo.removedAt === null) {\n removed += 1;\n removals.push(repo.id as RepoId);\n const links = repoLinksByRepoId.get(repoId);\n if (links) {\n for (const link of links) {\n linksToDelete.push(link.id as RepoLinkId);\n }\n }\n }\n }\n\n if (\n bootstrapInstallation ||\n creates.length > 0 ||\n updates.length > 0 ||\n removals.length > 0 ||\n linksToDelete.length > 0\n ) {\n await this.handlerTx()\n .mutate(({ forSchema }) => {\n const uow = forSchema(githubAppSchema);\n\n if (bootstrapInstallation) {\n uow.create(\"installation\", {\n id: bootstrapInstallation.id,\n accountId: bootstrapInstallation.accountId,\n accountLogin: bootstrapInstallation.accountLogin,\n accountType: bootstrapInstallation.accountType,\n status: bootstrapInstallation.status,\n permissions: bootstrapInstallation.permissions,\n events: bootstrapInstallation.events,\n });\n }\n\n for (const record of creates) {\n uow.create(\"installation_repo\", toRepoCreateRecord(record));\n }\n\n for (const update of updates) {\n uow.update(\"installation_repo\", update.id, (b) => b.set(update.data));\n }\n\n for (const id of removals) {\n uow.update(\"installation_repo\", id, (b) =>\n b.set({ removedAt: now, updatedAt: now }),\n );\n }\n\n for (const id of linksToDelete) {\n uow.delete(\"repo_link\", id);\n }\n })\n .execute();\n }\n\n return json({ added, removed, updated });\n },\n }),\n ];\n },\n);\n"],"mappings":"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"}
@@ -0,0 +1,47 @@
1
+ import { column, idColumn, referenceColumn, schema } from "@fragno-dev/db/schema";
2
+
3
+ //#region src/schema.ts
4
+ const githubAppSchema = schema("github-app-fragment", (s) => {
5
+ return s.addTable("installation", (t) => {
6
+ return t.addColumn("id", idColumn()).addColumn("accountId", column("string")).addColumn("accountLogin", column("string")).addColumn("accountType", column("string")).addColumn("status", column("string")).addColumn("permissions", column("json")).addColumn("events", column("json")).addColumn("createdAt", column("timestamp").defaultTo((b) => b.now())).addColumn("updatedAt", column("timestamp").defaultTo((b) => b.now())).addColumn("lastWebhookAt", column("timestamp").nullable()).createIndex("idx_installation_account_login", ["accountLogin"]).createIndex("idx_installation_status", ["status"]).createIndex("uniq_installation_id", ["id"], { unique: true });
7
+ }).addTable("installation_repo", (t) => {
8
+ return t.addColumn("id", idColumn()).addColumn("installationId", referenceColumn()).addColumn("ownerLogin", column("string")).addColumn("name", column("string")).addColumn("fullName", column("string")).addColumn("isPrivate", column("bool")).addColumn("isFork", column("bool").nullable()).addColumn("defaultBranch", column("string").nullable()).addColumn("removedAt", column("timestamp").nullable()).addColumn("updatedAt", column("timestamp").defaultTo((b) => b.now())).createIndex("idx_installation_repo_installation", ["installationId"]).createIndex("idx_installation_repo_full_name", ["fullName"]);
9
+ }).addTable("repo_link", (t) => {
10
+ return t.addColumn("id", idColumn()).addColumn("repoId", referenceColumn()).addColumn("linkKey", column("string")).addColumn("linkedAt", column("timestamp").defaultTo((b) => b.now())).createIndex("uniq_repo_link_repo_id_link_key", ["repoId", "linkKey"], { unique: true });
11
+ }).addReference("installation", {
12
+ type: "one",
13
+ from: {
14
+ table: "installation_repo",
15
+ column: "installationId"
16
+ },
17
+ to: {
18
+ table: "installation",
19
+ column: "id"
20
+ }
21
+ }).addReference("links", {
22
+ type: "many",
23
+ from: {
24
+ table: "installation_repo",
25
+ column: "id"
26
+ },
27
+ to: {
28
+ table: "repo_link",
29
+ column: "repoId"
30
+ },
31
+ foreignKey: false
32
+ }).addReference("repo", {
33
+ type: "one",
34
+ from: {
35
+ table: "repo_link",
36
+ column: "repoId"
37
+ },
38
+ to: {
39
+ table: "installation_repo",
40
+ column: "id"
41
+ }
42
+ });
43
+ });
44
+
45
+ //#endregion
46
+ export { githubAppSchema };
47
+ //# sourceMappingURL=schema.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.js","names":[],"sources":["../../src/schema.ts"],"sourcesContent":["import { column, idColumn, referenceColumn, schema } from \"@fragno-dev/db/schema\";\n\nexport const githubAppSchema = schema(\"github-app-fragment\", (s) => {\n return s\n .addTable(\"installation\", (t) => {\n return t\n .addColumn(\"id\", idColumn())\n .addColumn(\"accountId\", column(\"string\"))\n .addColumn(\"accountLogin\", column(\"string\"))\n .addColumn(\"accountType\", column(\"string\"))\n .addColumn(\"status\", column(\"string\"))\n .addColumn(\"permissions\", column(\"json\"))\n .addColumn(\"events\", column(\"json\"))\n .addColumn(\n \"createdAt\",\n column(\"timestamp\").defaultTo((b) => b.now()),\n )\n .addColumn(\n \"updatedAt\",\n column(\"timestamp\").defaultTo((b) => b.now()),\n )\n .addColumn(\"lastWebhookAt\", column(\"timestamp\").nullable())\n .createIndex(\"idx_installation_account_login\", [\"accountLogin\"])\n .createIndex(\"idx_installation_status\", [\"status\"])\n .createIndex(\"uniq_installation_id\", [\"id\"], { unique: true });\n })\n .addTable(\"installation_repo\", (t) => {\n return t\n .addColumn(\"id\", idColumn())\n .addColumn(\"installationId\", referenceColumn())\n .addColumn(\"ownerLogin\", column(\"string\"))\n .addColumn(\"name\", column(\"string\"))\n .addColumn(\"fullName\", column(\"string\"))\n .addColumn(\"isPrivate\", column(\"bool\"))\n .addColumn(\"isFork\", column(\"bool\").nullable())\n .addColumn(\"defaultBranch\", column(\"string\").nullable())\n .addColumn(\"removedAt\", column(\"timestamp\").nullable())\n .addColumn(\n \"updatedAt\",\n column(\"timestamp\").defaultTo((b) => b.now()),\n )\n .createIndex(\"idx_installation_repo_installation\", [\"installationId\"])\n .createIndex(\"idx_installation_repo_full_name\", [\"fullName\"]);\n })\n .addTable(\"repo_link\", (t) => {\n return (\n t\n .addColumn(\"id\", idColumn())\n .addColumn(\"repoId\", referenceColumn())\n // Namespaces a repo link so the same repository can be linked for multiple contexts.\n .addColumn(\"linkKey\", column(\"string\"))\n .addColumn(\n \"linkedAt\",\n column(\"timestamp\").defaultTo((b) => b.now()),\n )\n .createIndex(\"uniq_repo_link_repo_id_link_key\", [\"repoId\", \"linkKey\"], {\n unique: true,\n })\n );\n })\n .addReference(\"installation\", {\n type: \"one\",\n from: { table: \"installation_repo\", column: \"installationId\" },\n to: { table: \"installation\", column: \"id\" },\n })\n .addReference(\"links\", {\n // A repo is considered authorized for PR routes when at least one link exists.\n type: \"many\",\n from: { table: \"installation_repo\", column: \"id\" },\n to: { table: \"repo_link\", column: \"repoId\" },\n foreignKey: false,\n })\n .addReference(\"repo\", {\n type: \"one\",\n from: { table: \"repo_link\", column: \"repoId\" },\n to: { table: \"installation_repo\", column: \"id\" },\n });\n});\n"],"mappings":";;;AAEA,MAAa,kBAAkB,OAAO,wBAAwB,MAAM;AAClE,QAAO,EACJ,SAAS,iBAAiB,MAAM;AAC/B,SAAO,EACJ,UAAU,MAAM,UAAU,CAAC,CAC3B,UAAU,aAAa,OAAO,SAAS,CAAC,CACxC,UAAU,gBAAgB,OAAO,SAAS,CAAC,CAC3C,UAAU,eAAe,OAAO,SAAS,CAAC,CAC1C,UAAU,UAAU,OAAO,SAAS,CAAC,CACrC,UAAU,eAAe,OAAO,OAAO,CAAC,CACxC,UAAU,UAAU,OAAO,OAAO,CAAC,CACnC,UACC,aACA,OAAO,YAAY,CAAC,WAAW,MAAM,EAAE,KAAK,CAAC,CAC9C,CACA,UACC,aACA,OAAO,YAAY,CAAC,WAAW,MAAM,EAAE,KAAK,CAAC,CAC9C,CACA,UAAU,iBAAiB,OAAO,YAAY,CAAC,UAAU,CAAC,CAC1D,YAAY,kCAAkC,CAAC,eAAe,CAAC,CAC/D,YAAY,2BAA2B,CAAC,SAAS,CAAC,CAClD,YAAY,wBAAwB,CAAC,KAAK,EAAE,EAAE,QAAQ,MAAM,CAAC;GAChE,CACD,SAAS,sBAAsB,MAAM;AACpC,SAAO,EACJ,UAAU,MAAM,UAAU,CAAC,CAC3B,UAAU,kBAAkB,iBAAiB,CAAC,CAC9C,UAAU,cAAc,OAAO,SAAS,CAAC,CACzC,UAAU,QAAQ,OAAO,SAAS,CAAC,CACnC,UAAU,YAAY,OAAO,SAAS,CAAC,CACvC,UAAU,aAAa,OAAO,OAAO,CAAC,CACtC,UAAU,UAAU,OAAO,OAAO,CAAC,UAAU,CAAC,CAC9C,UAAU,iBAAiB,OAAO,SAAS,CAAC,UAAU,CAAC,CACvD,UAAU,aAAa,OAAO,YAAY,CAAC,UAAU,CAAC,CACtD,UACC,aACA,OAAO,YAAY,CAAC,WAAW,MAAM,EAAE,KAAK,CAAC,CAC9C,CACA,YAAY,sCAAsC,CAAC,iBAAiB,CAAC,CACrE,YAAY,mCAAmC,CAAC,WAAW,CAAC;GAC/D,CACD,SAAS,cAAc,MAAM;AAC5B,SACE,EACG,UAAU,MAAM,UAAU,CAAC,CAC3B,UAAU,UAAU,iBAAiB,CAAC,CAEtC,UAAU,WAAW,OAAO,SAAS,CAAC,CACtC,UACC,YACA,OAAO,YAAY,CAAC,WAAW,MAAM,EAAE,KAAK,CAAC,CAC9C,CACA,YAAY,mCAAmC,CAAC,UAAU,UAAU,EAAE,EACrE,QAAQ,MACT,CAAC;GAEN,CACD,aAAa,gBAAgB;EAC5B,MAAM;EACN,MAAM;GAAE,OAAO;GAAqB,QAAQ;GAAkB;EAC9D,IAAI;GAAE,OAAO;GAAgB,QAAQ;GAAM;EAC5C,CAAC,CACD,aAAa,SAAS;EAErB,MAAM;EACN,MAAM;GAAE,OAAO;GAAqB,QAAQ;GAAM;EAClD,IAAI;GAAE,OAAO;GAAa,QAAQ;GAAU;EAC5C,YAAY;EACb,CAAC,CACD,aAAa,QAAQ;EACpB,MAAM;EACN,MAAM;GAAE,OAAO;GAAa,QAAQ;GAAU;EAC9C,IAAI;GAAE,OAAO;GAAqB,QAAQ;GAAM;EACjD,CAAC;EACJ"}