@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":"webhook-processing.js","names":[],"sources":["../../../src/github/webhook-processing.ts"],"sourcesContent":["import type { TableToColumnValues } from \"@fragno-dev/db/query\";\n\nimport type { HookContext } from \"@fragno-dev/db\";\n\nimport type { EmitterWebhookEvent } from \"@octokit/webhooks\";\n\nimport { githubAppSchema } from \"../schema\";\nimport type { GitHubInstallationRepository } from \"./api\";\nimport {\n hasRepoChanges,\n type InstallationRepoRow,\n toRepoCreateRecord,\n toRepoRecord,\n} from \"./repo-sync\";\nimport type { GitHubAppFragmentConfig, GitHubAppWebhookConfig, GitHubAppWebhookOn } from \"./types\";\nimport { normalizeJoinedLinks, toExternalId } from \"./utils\";\n\ntype InstallationRow = TableToColumnValues<(typeof githubAppSchema)[\"tables\"][\"installation\"]>;\ntype RepoLinkRow = TableToColumnValues<(typeof githubAppSchema)[\"tables\"][\"repo_link\"]>;\ntype InstallationRepoId = InstallationRepoRow[\"id\"];\ntype RepoLinkId = RepoLinkRow[\"id\"];\n\ntype GitHubWebhookPayload<TEventName extends EmitterWebhookEvent[\"name\"]> = Extract<\n EmitterWebhookEvent,\n { name: TEventName }\n>[\"payload\"];\n\ntype InstallationPayload = GitHubWebhookPayload<\"installation\">;\ntype InstallationRepositoriesPayload = GitHubWebhookPayload<\"installation_repositories\">;\n\n/** Single discriminated union for supported events. One cast at entry derives all typed data. */\ntype SupportedWebhook =\n | { event: \"installation\"; action: string | null; payload: InstallationPayload }\n | {\n event: \"installation_repositories\";\n action: string | null;\n payload: InstallationRepositoriesPayload;\n };\n\nexport type WebhookProcessingPayload = {\n deliveryId: string;\n event: string;\n action: string | null;\n installationId: string;\n payload: Record<string, unknown>;\n receivedAt?: string | null;\n};\n\nconst SUPPORTED_EVENTS = [\"installation\", \"installation_repositories\"] as const;\n\nfunction asSupportedWebhook(data: WebhookProcessingPayload): SupportedWebhook | null {\n if (!SUPPORTED_EVENTS.includes(data.event as (typeof SUPPORTED_EVENTS)[number])) {\n return null;\n }\n return data as unknown as SupportedWebhook;\n}\n\ntype InternalWebhookHandler = (\n event: EmitterWebhookEvent,\n idempotencyKey: string,\n) => void | Promise<void>;\n\nconst toEmitterWebhookEvent = (data: WebhookProcessingPayload): EmitterWebhookEvent => {\n return {\n id: data.deliveryId,\n name: data.event as EmitterWebhookEvent[\"name\"],\n payload: data.payload as EmitterWebhookEvent[\"payload\"],\n } as EmitterWebhookEvent;\n};\n\nconst createWebhookEventDispatcher = (configureOn?: GitHubAppWebhookConfig) => {\n const handlersByEvent = new Map<string, InternalWebhookHandler[]>();\n\n const registerOn: GitHubAppWebhookOn = (event, handler) => {\n const events = Array.isArray(event) ? event : [event];\n for (const eventName of events) {\n const handlers = handlersByEvent.get(eventName);\n if (handlers) {\n handlers.push(handler as InternalWebhookHandler);\n } else {\n handlersByEvent.set(eventName, [handler as InternalWebhookHandler]);\n }\n }\n };\n\n configureOn?.(registerOn);\n\n return async (event: EmitterWebhookEvent, idempotencyKey: string) => {\n if (handlersByEvent.size === 0) {\n return;\n }\n\n const action =\n \"action\" in event.payload && typeof event.payload.action === \"string\"\n ? event.payload.action\n : null;\n const dispatchEvents = action ? [`${event.name}.${action}`, event.name] : [event.name];\n const handlers: InternalWebhookHandler[] = [];\n\n for (const eventName of dispatchEvents) {\n const registered = handlersByEvent.get(eventName);\n if (registered && registered.length > 0) {\n handlers.push(...registered);\n }\n }\n\n if (handlers.length === 0) {\n return;\n }\n\n const settled = await Promise.allSettled(\n handlers.map(async (handler) => await handler(event, idempotencyKey)),\n );\n const failures = settled\n .filter((result): result is PromiseRejectedResult => result.status === \"rejected\")\n .map((result) => result.reason);\n\n if (failures.length === 1) {\n throw failures[0];\n }\n if (failures.length > 1) {\n throw new AggregateError(failures, \"One or more configured webhook handlers failed.\");\n }\n };\n};\n\ntype WebhookRepoSnapshot =\n | NonNullable<InstallationPayload[\"repositories\"]>[number]\n | InstallationRepositoriesPayload[\"repositories_added\"][number];\n\nconst normalizeInstallationStatus = (action: string | null) => {\n switch (action) {\n case \"created\":\n case \"new_permissions_accepted\":\n case \"unsuspend\":\n return \"active\";\n case \"suspend\":\n return \"suspended\";\n case \"deleted\":\n return \"deleted\";\n default:\n return null;\n }\n};\n\nconst resolveReceivedAt = (receivedAt?: string | null) => {\n if (!receivedAt) {\n return new Date();\n }\n const parsed = new Date(receivedAt);\n return Number.isNaN(parsed.getTime()) ? new Date() : parsed;\n};\n\nconst parseOwnerLoginFromFullName = (fullName: string) => {\n const separatorIndex = fullName.indexOf(\"/\");\n if (separatorIndex <= 0) {\n return \"\";\n }\n return fullName.slice(0, separatorIndex);\n};\n\n// Webhook repo snapshots can omit `fork` and `default_branch`.\n// Leave them unset so updates do not overwrite previously synced values.\nconst toInstallationRepoFromWebhookRepository = (\n repo: WebhookRepoSnapshot,\n): GitHubInstallationRepository => {\n const ownerLogin = parseOwnerLoginFromFullName(repo.full_name);\n const mapped: GitHubInstallationRepository = {\n id: repo.id,\n name: repo.name,\n full_name: repo.full_name,\n private: repo.private,\n owner: { login: ownerLogin },\n };\n if (\"fork\" in repo && typeof repo.fork === \"boolean\") {\n mapped.fork = repo.fork;\n }\n if (\"default_branch\" in repo) {\n const defaultBranch = repo.default_branch;\n if (typeof defaultBranch === \"string\" || defaultBranch === null) {\n mapped.default_branch = defaultBranch;\n }\n }\n return mapped;\n};\n\nfunction extractAccountFromInstallation(\n installation: NonNullable<SupportedWebhook[\"payload\"][\"installation\"]>,\n) {\n const account = installation.account;\n if (!account) {\n throw new Error(\"Webhook payload installation missing account\");\n }\n const accountId = `${account.id}`;\n if (\"login\" in account) {\n return { accountId, accountLogin: account.login, accountType: account.type ?? \"\" };\n }\n return { accountId, accountLogin: account.slug, accountType: \"Enterprise\" };\n}\n\nconst isRepoSyncAction = (action: string | null) => {\n return action === \"created\" || action === \"new_permissions_accepted\";\n};\n\ntype RepoUpdateData = Omit<ReturnType<typeof toRepoRecord>, \"id\">;\n\nconst toRepoUpdateData = (\n record: ReturnType<typeof toRepoRecord>,\n now: Date,\n): Partial<RepoUpdateData> => ({\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 ? { defaultBranch: record.defaultBranch } : {}),\n removedAt: null,\n updatedAt: now,\n});\n\nexport const createWebhookProcessor = (config: Pick<GitHubAppFragmentConfig, \"webhook\"> = {}) => {\n const dispatchWebhookEvent = createWebhookEventDispatcher(config.webhook);\n\n return async function processWebhook(this: HookContext, data: WebhookProcessingPayload) {\n const emitterEvent = toEmitterWebhookEvent(data);\n const webhook = asSupportedWebhook(data);\n if (!webhook) {\n await dispatchWebhookEvent(emitterEvent, this.idempotencyKey);\n return;\n }\n\n const { event, action, payload } = webhook;\n const now = resolveReceivedAt(data.receivedAt);\n const installationId = data.installationId;\n\n const installation = payload.installation;\n if (!installation) {\n throw new Error(\"Webhook payload missing installation (required for installation events)\");\n }\n const { accountId, accountLogin, accountType } = extractAccountFromInstallation(installation);\n\n const statusOverride = normalizeInstallationStatus(action);\n const needsRepoSync =\n event === \"installation_repositories\" ||\n (event === \"installation\" && isRepoSyncAction(action));\n\n let existingInstallation: InstallationRow | null = null;\n let existingRepos: Array<InstallationRepoRow & { links?: RepoLinkRow | RepoLinkRow[] }> = [];\n\n if (needsRepoSync) {\n [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 } else {\n [existingInstallation] = await this.handlerTx()\n .retrieve(({ forSchema }) => {\n const uow = forSchema(githubAppSchema);\n return uow.findFirst(\"installation\", (b) =>\n b.whereIndex(\"uniq_installation_id\", (eb) => eb(\"id\", \"=\", installationId)),\n );\n })\n .execute();\n }\n\n const existingStatus =\n existingInstallation && typeof existingInstallation.status === \"string\"\n ? existingInstallation.status\n : null;\n const installationUpdate = {\n accountId,\n accountLogin,\n accountType,\n status: statusOverride || existingStatus || \"active\",\n permissions: installation.permissions ?? existingInstallation?.permissions ?? null,\n events: installation.events ?? existingInstallation?.events ?? null,\n updatedAt: now,\n lastWebhookAt: now,\n };\n\n const creates: Array<ReturnType<typeof toRepoRecord>> = [];\n const updates: Array<{ id: InstallationRepoId; data: Partial<RepoUpdateData> }> = [];\n const removals: Array<InstallationRepoId> = [];\n const linksToDelete: Array<RepoLinkId> = [];\n\n if (needsRepoSync) {\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 if (event === \"installation\") {\n // `repositories` is optional in the webhook payload — absent means no repos\n // were selected during installation, not that the data was truncated.\n const repos = (payload.repositories ?? []).map(toInstallationRepoFromWebhookRepository);\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 creates.push(record);\n continue;\n }\n\n if (hasRepoChanges(existing, record)) {\n updates.push({ id: existing.id, data: toRepoUpdateData(record, now) });\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 removals.push(repo.id);\n const links = repoLinksByRepoId.get(repoId);\n if (links) {\n for (const link of links) {\n linksToDelete.push(link.id);\n }\n }\n }\n }\n }\n\n if (event === \"installation_repositories\") {\n const added = payload.repositories_added;\n const removed = payload.repositories_removed;\n\n for (const repo of added) {\n const record = toRepoRecord(\n installationId,\n toInstallationRepoFromWebhookRepository(repo),\n now,\n );\n const existing = existingById.get(record.id);\n\n if (!existing) {\n creates.push(record);\n continue;\n }\n\n if (hasRepoChanges(existing, record)) {\n updates.push({ id: existing.id, data: toRepoUpdateData(record, now) });\n }\n }\n\n for (const repo of removed) {\n const repoId = toExternalId(repo.id) || null;\n if (!repoId) {\n continue;\n }\n const existing = existingById.get(repoId);\n if (existing && existing.removedAt === null) {\n removals.push(existing.id);\n const links = repoLinksByRepoId.get(repoId);\n if (links) {\n for (const link of links) {\n linksToDelete.push(link.id);\n }\n }\n }\n }\n }\n }\n\n const hasRepoMutations =\n creates.length > 0 || updates.length > 0 || removals.length > 0 || linksToDelete.length > 0;\n\n await this.handlerTx()\n .mutate(({ forSchema }) => {\n const uow = forSchema(githubAppSchema);\n\n if (existingInstallation) {\n uow.update(\"installation\", installationId, (b) => b.set(installationUpdate));\n } else {\n uow.create(\"installation\", {\n id: installationId,\n accountId: installationUpdate.accountId,\n accountLogin: installationUpdate.accountLogin,\n accountType: installationUpdate.accountType,\n status: installationUpdate.status,\n permissions: installationUpdate.permissions,\n events: installationUpdate.events,\n createdAt: now,\n updatedAt: now,\n lastWebhookAt: now,\n });\n }\n\n if (hasRepoMutations) {\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) => b.set({ removedAt: now, updatedAt: now }));\n }\n\n for (const id of linksToDelete) {\n uow.delete(\"repo_link\", id);\n }\n }\n })\n .execute();\n await dispatchWebhookEvent(emitterEvent, this.idempotencyKey);\n };\n};\n"],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ //#region src/cli/index.d.ts
2
+ declare function run(): Promise<void>;
3
+ //#endregion
4
+ export { run };
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","names":[],"sources":["../../src/cli/index.ts"],"mappings":";iBA2IsB,GAAA,CAAA,GAAG,OAAA"}
@@ -0,0 +1,263 @@
1
+ #!/usr/bin/env node
2
+ import { installationsCommand, installationsSubCommands } from "./commands/installations.js";
3
+ import { pullsCommand, pullsSubCommands } from "./commands/pulls.js";
4
+ import { repositoriesCommand, repositoriesSubCommands } from "./commands/repositories.js";
5
+ import { serveCommand } from "./commands/serve.js";
6
+ import { webhooksCommand, webhooksSubCommands } from "./commands/webhooks.js";
7
+ import { readFileSync } from "node:fs";
8
+ import { dirname, join } from "node:path";
9
+ import { fileURLToPath } from "node:url";
10
+ import { cli, define } from "gunshi";
11
+
12
+ //#region src/cli/index.ts
13
+ const __dirname = dirname(fileURLToPath(import.meta.url));
14
+ const version = JSON.parse(readFileSync(join(__dirname, "../../package.json"), "utf-8")).version;
15
+ const mainCommand = define({
16
+ name: "fragno-github-app",
17
+ description: "GitHub App fragment CLI"
18
+ });
19
+ const printMainHelp = () => {
20
+ console.log("GitHub App fragment CLI");
21
+ console.log("");
22
+ console.log("USAGE:");
23
+ console.log(" fragno-github-app <COMMAND>");
24
+ console.log("");
25
+ console.log("COMMANDS:");
26
+ console.log(" serve Start a local fragment server");
27
+ console.log(" installations Installation commands");
28
+ console.log(" repositories Repository commands");
29
+ console.log(" pulls Pull request commands");
30
+ console.log(" webhooks Webhook utilities");
31
+ console.log("");
32
+ console.log("CLIENT OPTIONS:");
33
+ console.log(" -b, --base-url Fragment base URL (env: FRAGNO_GITHUB_APP_BASE_URL)");
34
+ console.log(" -H, --header Extra HTTP header (repeatable)");
35
+ console.log(" --timeout Request timeout in ms (default: 15000)");
36
+ console.log(" --retries Retry count (default: 2)");
37
+ console.log(" --retry-delay Retry delay in ms (default: 500)");
38
+ console.log("");
39
+ console.log("SERVER ENV:");
40
+ console.log(" GITHUB_APP_ID");
41
+ console.log(" GITHUB_APP_SLUG");
42
+ console.log(" GITHUB_APP_PRIVATE_KEY (or GITHUB_APP_PRIVATE_KEY_FILE)");
43
+ console.log(" GITHUB_APP_WEBHOOK_SECRET");
44
+ console.log("");
45
+ console.log("EXAMPLES:");
46
+ console.log(" fragno-github-app serve --port 6173 --db-path ./github-app.sqlite");
47
+ console.log(" fragno-github-app installations list -b http://localhost:6173/github-app-fragment");
48
+ console.log(" fragno-github-app repositories linked -b http://localhost:6173/github-app-fragment");
49
+ console.log("");
50
+ };
51
+ const printServeHelp = () => {
52
+ console.log("Serve command");
53
+ console.log("");
54
+ console.log("USAGE:");
55
+ console.log(" fragno-github-app serve [options]");
56
+ console.log("");
57
+ console.log("OPTIONS:");
58
+ console.log(" -H, --host Host to bind to (default: 127.0.0.1)");
59
+ console.log(" -p, --port Port to listen on (default: 6173)");
60
+ console.log(" --mount-route Override mount route");
61
+ console.log(" --db-path SQLite database path (default: ./github-app-fragment.sqlite)");
62
+ console.log(" --poll-interval Durable hooks poll interval ms (default: 200)");
63
+ console.log("");
64
+ console.log(" --app-id GitHub App ID (env: GITHUB_APP_ID)");
65
+ console.log(" --app-slug GitHub App slug (env: GITHUB_APP_SLUG)");
66
+ console.log(" --private-key GitHub App private key PEM (env: GITHUB_APP_PRIVATE_KEY)");
67
+ console.log(" --private-key-file GitHub App private key PEM file");
68
+ console.log(" --webhook-secret Webhook secret (env: GITHUB_APP_WEBHOOK_SECRET)");
69
+ console.log(" --webhook-debug Log webhook debug info (env: GITHUB_APP_WEBHOOK_DEBUG)");
70
+ console.log(" --api-base-url GitHub API base URL");
71
+ console.log(" --api-version GitHub API version");
72
+ console.log(" --web-base-url GitHub web base URL");
73
+ console.log(" --default-link-key Default link key");
74
+ console.log(" --token-cache-ttl Token cache TTL in seconds");
75
+ console.log("");
76
+ };
77
+ const printInstallationsHelp = () => {
78
+ console.log("Installation commands");
79
+ console.log("");
80
+ console.log("USAGE:");
81
+ console.log(" fragno-github-app installations <COMMAND>");
82
+ console.log("");
83
+ console.log("COMMANDS:");
84
+ console.log(" list List installations");
85
+ console.log(" repos List repositories for an installation");
86
+ console.log(" sync Sync installation repositories from GitHub");
87
+ console.log("");
88
+ };
89
+ const printRepositoriesHelp = () => {
90
+ console.log("Repository commands");
91
+ console.log("");
92
+ console.log("USAGE:");
93
+ console.log(" fragno-github-app repositories <COMMAND>");
94
+ console.log("");
95
+ console.log("COMMANDS:");
96
+ console.log(" linked List linked repositories");
97
+ console.log(" link Link a repository");
98
+ console.log(" unlink Unlink a repository");
99
+ console.log("");
100
+ };
101
+ const printPullsHelp = () => {
102
+ console.log("Pull request commands");
103
+ console.log("");
104
+ console.log("USAGE:");
105
+ console.log(" fragno-github-app pulls <COMMAND>");
106
+ console.log("");
107
+ console.log("COMMANDS:");
108
+ console.log(" list List pull requests");
109
+ console.log(" review Create a pull request review");
110
+ console.log("");
111
+ };
112
+ const printWebhooksHelp = () => {
113
+ console.log("Webhook utilities");
114
+ console.log("");
115
+ console.log("USAGE:");
116
+ console.log(" fragno-github-app webhooks <COMMAND>");
117
+ console.log("");
118
+ console.log("COMMANDS:");
119
+ console.log(" send Send a signed webhook payload");
120
+ console.log("");
121
+ };
122
+ async function run() {
123
+ const args = process.argv.slice(2);
124
+ if (!args.length || args[0] === "--help" || args[0] === "-h") {
125
+ printMainHelp();
126
+ return;
127
+ }
128
+ if (args[0] === "--version" || args[0] === "-v") {
129
+ console.log(version);
130
+ return;
131
+ }
132
+ if (args[0] === "serve") {
133
+ const next = args[1];
134
+ if (!next || next === "--help" || next === "-h") {
135
+ printServeHelp();
136
+ return;
137
+ }
138
+ if (next === "--version" || next === "-v") {
139
+ console.log(version);
140
+ return;
141
+ }
142
+ await cli(args.slice(1), serveCommand, {
143
+ name: "fragno-github-app serve",
144
+ version
145
+ });
146
+ return;
147
+ }
148
+ if (args[0] === "installations") {
149
+ const subCommandName = args[1];
150
+ if (!subCommandName || subCommandName === "--help" || subCommandName === "-h") {
151
+ printInstallationsHelp();
152
+ return;
153
+ }
154
+ if (subCommandName === "--version" || subCommandName === "-v") {
155
+ console.log(version);
156
+ return;
157
+ }
158
+ const subCommand = installationsSubCommands.get(subCommandName);
159
+ if (!subCommand) {
160
+ console.error(`Unknown command: ${subCommandName}`);
161
+ console.log("");
162
+ console.log("Run 'fragno-github-app installations --help' for available commands.");
163
+ process.exit(1);
164
+ }
165
+ await cli(args.slice(2), subCommand, {
166
+ name: `fragno-github-app installations ${subCommandName}`,
167
+ version
168
+ });
169
+ return;
170
+ }
171
+ if (args[0] === "repositories") {
172
+ const subCommandName = args[1];
173
+ if (!subCommandName || subCommandName === "--help" || subCommandName === "-h") {
174
+ printRepositoriesHelp();
175
+ return;
176
+ }
177
+ if (subCommandName === "--version" || subCommandName === "-v") {
178
+ console.log(version);
179
+ return;
180
+ }
181
+ const subCommand = repositoriesSubCommands.get(subCommandName);
182
+ if (!subCommand) {
183
+ console.error(`Unknown command: ${subCommandName}`);
184
+ console.log("");
185
+ console.log("Run 'fragno-github-app repositories --help' for available commands.");
186
+ process.exit(1);
187
+ }
188
+ await cli(args.slice(2), subCommand, {
189
+ name: `fragno-github-app repositories ${subCommandName}`,
190
+ version
191
+ });
192
+ return;
193
+ }
194
+ if (args[0] === "pulls") {
195
+ const subCommandName = args[1];
196
+ if (!subCommandName || subCommandName === "--help" || subCommandName === "-h") {
197
+ printPullsHelp();
198
+ return;
199
+ }
200
+ if (subCommandName === "--version" || subCommandName === "-v") {
201
+ console.log(version);
202
+ return;
203
+ }
204
+ const subCommand = pullsSubCommands.get(subCommandName);
205
+ if (!subCommand) {
206
+ console.error(`Unknown command: ${subCommandName}`);
207
+ console.log("");
208
+ console.log("Run 'fragno-github-app pulls --help' for available commands.");
209
+ process.exit(1);
210
+ }
211
+ await cli(args.slice(2), subCommand, {
212
+ name: `fragno-github-app pulls ${subCommandName}`,
213
+ version
214
+ });
215
+ return;
216
+ }
217
+ if (args[0] === "webhooks") {
218
+ const subCommandName = args[1];
219
+ if (!subCommandName || subCommandName === "--help" || subCommandName === "-h") {
220
+ printWebhooksHelp();
221
+ return;
222
+ }
223
+ if (subCommandName === "--version" || subCommandName === "-v") {
224
+ console.log(version);
225
+ return;
226
+ }
227
+ const subCommand = webhooksSubCommands.get(subCommandName);
228
+ if (!subCommand) {
229
+ console.error(`Unknown command: ${subCommandName}`);
230
+ console.log("");
231
+ console.log("Run 'fragno-github-app webhooks --help' for available commands.");
232
+ process.exit(1);
233
+ }
234
+ await cli(args.slice(2), subCommand, {
235
+ name: `fragno-github-app webhooks ${subCommandName}`,
236
+ version
237
+ });
238
+ return;
239
+ }
240
+ if (args[0].startsWith("-")) {
241
+ await cli(args, mainCommand, {
242
+ name: "fragno-github-app",
243
+ version,
244
+ subCommands: new Map([
245
+ ["serve", serveCommand],
246
+ ["installations", installationsCommand],
247
+ ["repositories", repositoriesCommand],
248
+ ["pulls", pullsCommand],
249
+ ["webhooks", webhooksCommand]
250
+ ])
251
+ });
252
+ return;
253
+ }
254
+ console.error(`Unknown command: ${args[0]}`);
255
+ console.log("");
256
+ console.log("Run 'fragno-github-app --help' for available commands.");
257
+ process.exit(1);
258
+ }
259
+ if (import.meta.main) await run();
260
+
261
+ //#endregion
262
+ export { run };
263
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../src/cli/index.ts"],"sourcesContent":["#!/usr/bin/env node\n\nimport { readFileSync } from \"node:fs\";\nimport { dirname, join } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\n\nimport { cli, define } from \"gunshi\";\nimport type { Args, Command } from \"gunshi\";\n\nimport { installationsCommand, installationsSubCommands } from \"./commands/installations.js\";\nimport { pullsCommand, pullsSubCommands } from \"./commands/pulls.js\";\nimport { repositoriesCommand, repositoriesSubCommands } from \"./commands/repositories.js\";\nimport { serveCommand } from \"./commands/serve.js\";\nimport { webhooksCommand, webhooksSubCommands } from \"./commands/webhooks.js\";\n\nconst __dirname = dirname(fileURLToPath(import.meta.url));\nconst packageJson = JSON.parse(readFileSync(join(__dirname, \"../../package.json\"), \"utf-8\"));\nconst version = packageJson.version as string;\n\nconst mainCommand = define({\n name: \"fragno-github-app\",\n description: \"GitHub App fragment CLI\",\n});\n\nconst printMainHelp = () => {\n console.log(\"GitHub App fragment CLI\");\n console.log(\"\");\n console.log(\"USAGE:\");\n console.log(\" fragno-github-app <COMMAND>\");\n console.log(\"\");\n console.log(\"COMMANDS:\");\n console.log(\" serve Start a local fragment server\");\n console.log(\" installations Installation commands\");\n console.log(\" repositories Repository commands\");\n console.log(\" pulls Pull request commands\");\n console.log(\" webhooks Webhook utilities\");\n console.log(\"\");\n console.log(\"CLIENT OPTIONS:\");\n console.log(\" -b, --base-url Fragment base URL (env: FRAGNO_GITHUB_APP_BASE_URL)\");\n console.log(\" -H, --header Extra HTTP header (repeatable)\");\n console.log(\" --timeout Request timeout in ms (default: 15000)\");\n console.log(\" --retries Retry count (default: 2)\");\n console.log(\" --retry-delay Retry delay in ms (default: 500)\");\n console.log(\"\");\n console.log(\"SERVER ENV:\");\n console.log(\" GITHUB_APP_ID\");\n console.log(\" GITHUB_APP_SLUG\");\n console.log(\" GITHUB_APP_PRIVATE_KEY (or GITHUB_APP_PRIVATE_KEY_FILE)\");\n console.log(\" GITHUB_APP_WEBHOOK_SECRET\");\n console.log(\"\");\n console.log(\"EXAMPLES:\");\n console.log(\" fragno-github-app serve --port 6173 --db-path ./github-app.sqlite\");\n console.log(\n \" fragno-github-app installations list -b http://localhost:6173/github-app-fragment\",\n );\n console.log(\n \" fragno-github-app repositories linked -b http://localhost:6173/github-app-fragment\",\n );\n console.log(\"\");\n};\n\nconst printServeHelp = () => {\n console.log(\"Serve command\");\n console.log(\"\");\n console.log(\"USAGE:\");\n console.log(\" fragno-github-app serve [options]\");\n console.log(\"\");\n console.log(\"OPTIONS:\");\n console.log(\" -H, --host Host to bind to (default: 127.0.0.1)\");\n console.log(\" -p, --port Port to listen on (default: 6173)\");\n console.log(\" --mount-route Override mount route\");\n console.log(\n \" --db-path SQLite database path (default: ./github-app-fragment.sqlite)\",\n );\n console.log(\" --poll-interval Durable hooks poll interval ms (default: 200)\");\n console.log(\"\");\n console.log(\" --app-id GitHub App ID (env: GITHUB_APP_ID)\");\n console.log(\" --app-slug GitHub App slug (env: GITHUB_APP_SLUG)\");\n console.log(\" --private-key GitHub App private key PEM (env: GITHUB_APP_PRIVATE_KEY)\");\n console.log(\" --private-key-file GitHub App private key PEM file\");\n console.log(\" --webhook-secret Webhook secret (env: GITHUB_APP_WEBHOOK_SECRET)\");\n console.log(\" --webhook-debug Log webhook debug info (env: GITHUB_APP_WEBHOOK_DEBUG)\");\n console.log(\" --api-base-url GitHub API base URL\");\n console.log(\" --api-version GitHub API version\");\n console.log(\" --web-base-url GitHub web base URL\");\n console.log(\" --default-link-key Default link key\");\n console.log(\" --token-cache-ttl Token cache TTL in seconds\");\n console.log(\"\");\n};\n\nconst printInstallationsHelp = () => {\n console.log(\"Installation commands\");\n console.log(\"\");\n console.log(\"USAGE:\");\n console.log(\" fragno-github-app installations <COMMAND>\");\n console.log(\"\");\n console.log(\"COMMANDS:\");\n console.log(\" list List installations\");\n console.log(\" repos List repositories for an installation\");\n console.log(\" sync Sync installation repositories from GitHub\");\n console.log(\"\");\n};\n\nconst printRepositoriesHelp = () => {\n console.log(\"Repository commands\");\n console.log(\"\");\n console.log(\"USAGE:\");\n console.log(\" fragno-github-app repositories <COMMAND>\");\n console.log(\"\");\n console.log(\"COMMANDS:\");\n console.log(\" linked List linked repositories\");\n console.log(\" link Link a repository\");\n console.log(\" unlink Unlink a repository\");\n console.log(\"\");\n};\n\nconst printPullsHelp = () => {\n console.log(\"Pull request commands\");\n console.log(\"\");\n console.log(\"USAGE:\");\n console.log(\" fragno-github-app pulls <COMMAND>\");\n console.log(\"\");\n console.log(\"COMMANDS:\");\n console.log(\" list List pull requests\");\n console.log(\" review Create a pull request review\");\n console.log(\"\");\n};\n\nconst printWebhooksHelp = () => {\n console.log(\"Webhook utilities\");\n console.log(\"\");\n console.log(\"USAGE:\");\n console.log(\" fragno-github-app webhooks <COMMAND>\");\n console.log(\"\");\n console.log(\"COMMANDS:\");\n console.log(\" send Send a signed webhook payload\");\n console.log(\"\");\n};\n\nexport async function run() {\n const args = process.argv.slice(2);\n\n if (!args.length || args[0] === \"--help\" || args[0] === \"-h\") {\n printMainHelp();\n return;\n }\n\n if (args[0] === \"--version\" || args[0] === \"-v\") {\n console.log(version);\n return;\n }\n\n if (args[0] === \"serve\") {\n const next = args[1];\n if (!next || next === \"--help\" || next === \"-h\") {\n printServeHelp();\n return;\n }\n if (next === \"--version\" || next === \"-v\") {\n console.log(version);\n return;\n }\n\n await cli(args.slice(1), serveCommand as Command<Args>, {\n name: \"fragno-github-app serve\",\n version,\n });\n return;\n }\n\n if (args[0] === \"installations\") {\n const subCommandName = args[1];\n if (!subCommandName || subCommandName === \"--help\" || subCommandName === \"-h\") {\n printInstallationsHelp();\n return;\n }\n if (subCommandName === \"--version\" || subCommandName === \"-v\") {\n console.log(version);\n return;\n }\n\n const subCommand = installationsSubCommands.get(subCommandName);\n if (!subCommand) {\n console.error(`Unknown command: ${subCommandName}`);\n console.log(\"\");\n console.log(\"Run 'fragno-github-app installations --help' for available commands.\");\n process.exit(1);\n }\n\n await cli(args.slice(2), subCommand as Command<Args>, {\n name: `fragno-github-app installations ${subCommandName}`,\n version,\n });\n return;\n }\n\n if (args[0] === \"repositories\") {\n const subCommandName = args[1];\n if (!subCommandName || subCommandName === \"--help\" || subCommandName === \"-h\") {\n printRepositoriesHelp();\n return;\n }\n if (subCommandName === \"--version\" || subCommandName === \"-v\") {\n console.log(version);\n return;\n }\n\n const subCommand = repositoriesSubCommands.get(subCommandName);\n if (!subCommand) {\n console.error(`Unknown command: ${subCommandName}`);\n console.log(\"\");\n console.log(\"Run 'fragno-github-app repositories --help' for available commands.\");\n process.exit(1);\n }\n\n await cli(args.slice(2), subCommand as Command<Args>, {\n name: `fragno-github-app repositories ${subCommandName}`,\n version,\n });\n return;\n }\n\n if (args[0] === \"pulls\") {\n const subCommandName = args[1];\n if (!subCommandName || subCommandName === \"--help\" || subCommandName === \"-h\") {\n printPullsHelp();\n return;\n }\n if (subCommandName === \"--version\" || subCommandName === \"-v\") {\n console.log(version);\n return;\n }\n\n const subCommand = pullsSubCommands.get(subCommandName);\n if (!subCommand) {\n console.error(`Unknown command: ${subCommandName}`);\n console.log(\"\");\n console.log(\"Run 'fragno-github-app pulls --help' for available commands.\");\n process.exit(1);\n }\n\n await cli(args.slice(2), subCommand as Command<Args>, {\n name: `fragno-github-app pulls ${subCommandName}`,\n version,\n });\n return;\n }\n\n if (args[0] === \"webhooks\") {\n const subCommandName = args[1];\n if (!subCommandName || subCommandName === \"--help\" || subCommandName === \"-h\") {\n printWebhooksHelp();\n return;\n }\n if (subCommandName === \"--version\" || subCommandName === \"-v\") {\n console.log(version);\n return;\n }\n\n const subCommand = webhooksSubCommands.get(subCommandName);\n if (!subCommand) {\n console.error(`Unknown command: ${subCommandName}`);\n console.log(\"\");\n console.log(\"Run 'fragno-github-app webhooks --help' for available commands.\");\n process.exit(1);\n }\n\n await cli(args.slice(2), subCommand as Command<Args>, {\n name: `fragno-github-app webhooks ${subCommandName}`,\n version,\n });\n return;\n }\n\n if (args[0].startsWith(\"-\")) {\n await cli(args, mainCommand as Command<Args>, {\n name: \"fragno-github-app\",\n version,\n subCommands: new Map([\n [\"serve\", serveCommand as Command<Args>],\n [\"installations\", installationsCommand as Command<Args>],\n [\"repositories\", repositoriesCommand as Command<Args>],\n [\"pulls\", pullsCommand as Command<Args>],\n [\"webhooks\", webhooksCommand as Command<Args>],\n ]),\n });\n return;\n }\n\n console.error(`Unknown command: ${args[0]}`);\n console.log(\"\");\n console.log(\"Run 'fragno-github-app --help' for available commands.\");\n process.exit(1);\n}\n\nif (import.meta.main) {\n await run();\n}\n"],"mappings":"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"}