@shipfox/client-integrations 13.0.0 → 14.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 (132) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/CHANGELOG.md +32 -0
  3. package/dist/application/complete-integration-callback.d.ts +11 -0
  4. package/dist/application/complete-integration-callback.d.ts.map +1 -1
  5. package/dist/application/complete-integration-callback.js +38 -8
  6. package/dist/application/complete-integration-callback.js.map +1 -1
  7. package/dist/components/callback-status-shell.d.ts +1 -1
  8. package/dist/components/callback-status-shell.d.ts.map +1 -1
  9. package/dist/components/callback-status-shell.js +3 -3
  10. package/dist/components/callback-status-shell.js.map +1 -1
  11. package/dist/components/connection-picker.js +3 -3
  12. package/dist/components/connection-picker.js.map +1 -1
  13. package/dist/components/installed-integrations-section.js +9 -9
  14. package/dist/components/installed-integrations-section.js.map +1 -1
  15. package/dist/components/integration-delete-confirm-modal.js +1 -1
  16. package/dist/components/integration-delete-confirm-modal.js.map +1 -1
  17. package/dist/components/integration-gallery-for-workspace.js +3 -3
  18. package/dist/components/integration-gallery-for-workspace.js.map +1 -1
  19. package/dist/components/integration-usage-modal.js +6 -6
  20. package/dist/components/integration-usage-modal.js.map +1 -1
  21. package/dist/components/provider-grid.d.ts +1 -1
  22. package/dist/components/provider-grid.d.ts.map +1 -1
  23. package/dist/components/provider-grid.js +10 -10
  24. package/dist/components/provider-grid.js.map +1 -1
  25. package/dist/components/redirect-install-page.js +1 -1
  26. package/dist/components/redirect-install-page.js.map +1 -1
  27. package/dist/components/repository-picker.js +4 -4
  28. package/dist/components/repository-picker.js.map +1 -1
  29. package/dist/components/webhook/copyable-value.js +3 -3
  30. package/dist/components/webhook/copyable-value.js.map +1 -1
  31. package/dist/components/webhook/webhook-create-modal.js +1 -1
  32. package/dist/components/webhook/webhook-create-modal.js.map +1 -1
  33. package/dist/components/webhook/webhook-usage-details.js +2 -2
  34. package/dist/components/webhook/webhook-usage-details.js.map +1 -1
  35. package/dist/core/models.d.ts +6 -0
  36. package/dist/core/models.d.ts.map +1 -1
  37. package/dist/core/models.js +12 -0
  38. package/dist/core/models.js.map +1 -1
  39. package/dist/feature.d.ts +8 -0
  40. package/dist/feature.d.ts.map +1 -1
  41. package/dist/feature.js +10 -0
  42. package/dist/feature.js.map +1 -1
  43. package/dist/hooks/api/integration-mapper.d.ts +3 -1
  44. package/dist/hooks/api/integration-mapper.d.ts.map +1 -1
  45. package/dist/hooks/api/integration-mapper.js +8 -0
  46. package/dist/hooks/api/integration-mapper.js.map +1 -1
  47. package/dist/hooks/api/integrations.d.ts +25 -1
  48. package/dist/hooks/api/integrations.d.ts.map +1 -1
  49. package/dist/hooks/api/integrations.js +44 -1
  50. package/dist/hooks/api/integrations.js.map +1 -1
  51. package/dist/index.d.ts +4 -0
  52. package/dist/index.d.ts.map +1 -1
  53. package/dist/index.js +4 -0
  54. package/dist/index.js.map +1 -1
  55. package/dist/jira-callback-state.d.ts +9 -0
  56. package/dist/jira-callback-state.d.ts.map +1 -0
  57. package/dist/jira-callback-state.js +16 -0
  58. package/dist/jira-callback-state.js.map +1 -0
  59. package/dist/jira-callback.d.ts +11 -0
  60. package/dist/jira-callback.d.ts.map +1 -0
  61. package/dist/jira-callback.js +59 -0
  62. package/dist/jira-callback.js.map +1 -0
  63. package/dist/jira-form-errors.d.ts +8 -0
  64. package/dist/jira-form-errors.d.ts.map +1 -0
  65. package/dist/jira-form-errors.js +55 -0
  66. package/dist/jira-form-errors.js.map +1 -0
  67. package/dist/pages/gitea-install-page.js +4 -4
  68. package/dist/pages/gitea-install-page.js.map +1 -1
  69. package/dist/pages/jira-callback-page.d.ts +2 -0
  70. package/dist/pages/jira-callback-page.d.ts.map +1 -0
  71. package/dist/pages/jira-callback-page.js +341 -0
  72. package/dist/pages/jira-callback-page.js.map +1 -0
  73. package/dist/pages/jira-install-page.d.ts +2 -0
  74. package/dist/pages/jira-install-page.d.ts.map +1 -0
  75. package/dist/pages/jira-install-page.js +26 -0
  76. package/dist/pages/jira-install-page.js.map +1 -0
  77. package/dist/pages/sentry-callback-page.js +7 -7
  78. package/dist/pages/sentry-callback-page.js.map +1 -1
  79. package/dist/pages/source-control-onboarding-page.js +2 -2
  80. package/dist/pages/source-control-onboarding-page.js.map +1 -1
  81. package/dist/provider-catalog.d.ts +1 -1
  82. package/dist/provider-catalog.d.ts.map +1 -1
  83. package/dist/provider-catalog.js +5 -0
  84. package/dist/provider-catalog.js.map +1 -1
  85. package/dist/routes/jira-callback.d.ts +8 -0
  86. package/dist/routes/jira-callback.d.ts.map +1 -0
  87. package/dist/routes/jira-callback.js +9 -0
  88. package/dist/routes/jira-callback.js.map +1 -0
  89. package/dist/routes/jira.d.ts +6 -0
  90. package/dist/routes/jira.d.ts.map +1 -0
  91. package/dist/routes/jira.js +7 -0
  92. package/dist/routes/jira.js.map +1 -0
  93. package/dist/tsconfig.test.tsbuildinfo +1 -1
  94. package/package.json +9 -8
  95. package/src/application/complete-integration-callback.test.ts +44 -1
  96. package/src/application/complete-integration-callback.ts +61 -8
  97. package/src/components/callback-status-shell.tsx +7 -4
  98. package/src/components/connection-picker.tsx +3 -3
  99. package/src/components/installed-integrations-section.tsx +9 -9
  100. package/src/components/integration-delete-confirm-modal.tsx +1 -1
  101. package/src/components/integration-gallery-for-workspace.tsx +3 -3
  102. package/src/components/integration-usage-events.test.ts +13 -0
  103. package/src/components/integration-usage-modal.tsx +6 -6
  104. package/src/components/provider-grid.tsx +10 -10
  105. package/src/components/redirect-install-page.tsx +1 -1
  106. package/src/components/repository-picker.test.tsx +2 -2
  107. package/src/components/repository-picker.tsx +6 -4
  108. package/src/components/webhook/copyable-value.tsx +3 -3
  109. package/src/components/webhook/webhook-create-modal.tsx +1 -1
  110. package/src/components/webhook/webhook-usage-details.tsx +2 -2
  111. package/src/core/models.ts +18 -0
  112. package/src/feature.ts +10 -0
  113. package/src/hooks/api/integration-mapper.ts +6 -0
  114. package/src/hooks/api/integrations.test.ts +92 -0
  115. package/src/hooks/api/integrations.ts +71 -0
  116. package/src/index.ts +4 -0
  117. package/src/jira-callback-state.ts +19 -0
  118. package/src/jira-callback.test.ts +76 -0
  119. package/src/jira-callback.ts +67 -0
  120. package/src/jira-form-errors.test.ts +57 -0
  121. package/src/jira-form-errors.ts +94 -0
  122. package/src/pages/gitea-install-page.tsx +4 -4
  123. package/src/pages/jira-callback-page.test.tsx +250 -0
  124. package/src/pages/jira-callback-page.tsx +366 -0
  125. package/src/pages/jira-install-page.tsx +28 -0
  126. package/src/pages/sentry-callback-page.tsx +7 -7
  127. package/src/pages/source-control-onboarding-page.tsx +2 -2
  128. package/src/provider-catalog.test.ts +6 -0
  129. package/src/provider-catalog.ts +7 -1
  130. package/src/routes/jira-callback.tsx +8 -0
  131. package/src/routes/jira.tsx +4 -0
  132. package/tsconfig.build.tsbuildinfo +1 -1
@@ -0,0 +1,26 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { sessionStorageOrUndefined } from '@shipfox/client-ui';
3
+ import { useCallback } from 'react';
4
+ import { RedirectInstallPage } from '#components/redirect-install-page.js';
5
+ import { useCreateJiraInstallMutation } from '#hooks/api/integrations.js';
6
+ import { saveJiraInstallWorkspace } from '#jira-callback.js';
7
+ export function JiraInstallPage() {
8
+ const createInstall = useCreateJiraInstallMutation();
9
+ const installRequest = useCallback(async (body)=>await createInstall.mutateAsync(body), [
10
+ createInstall
11
+ ]);
12
+ return /*#__PURE__*/ _jsx(RedirectInstallPage, {
13
+ installRequest: installRequest,
14
+ errorFallbackMessage: "Could not start Jira install.",
15
+ loadingLabel: "Connecting Jira",
16
+ beforeRedirect: (workspaceId)=>{
17
+ try {
18
+ saveJiraInstallWorkspace(sessionStorageOrUndefined(), workspaceId);
19
+ } catch {
20
+ // Storage is only a navigation hint; the signed state is authoritative.
21
+ }
22
+ }
23
+ });
24
+ }
25
+
26
+ //# sourceMappingURL=jira-install-page.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/pages/jira-install-page.tsx"],"sourcesContent":["import {sessionStorageOrUndefined} from '@shipfox/client-ui';\nimport {useCallback} from 'react';\nimport {RedirectInstallPage} from '#components/redirect-install-page.js';\nimport {useCreateJiraInstallMutation} from '#hooks/api/integrations.js';\nimport {saveJiraInstallWorkspace} from '#jira-callback.js';\n\nexport function JiraInstallPage() {\n const createInstall = useCreateJiraInstallMutation();\n const installRequest = useCallback(\n async (body: {workspace_id: string}) => await createInstall.mutateAsync(body),\n [createInstall],\n );\n\n return (\n <RedirectInstallPage\n installRequest={installRequest}\n errorFallbackMessage=\"Could not start Jira install.\"\n loadingLabel=\"Connecting Jira\"\n beforeRedirect={(workspaceId) => {\n try {\n saveJiraInstallWorkspace(sessionStorageOrUndefined(), workspaceId);\n } catch {\n // Storage is only a navigation hint; the signed state is authoritative.\n }\n }}\n />\n );\n}\n"],"names":["sessionStorageOrUndefined","useCallback","RedirectInstallPage","useCreateJiraInstallMutation","saveJiraInstallWorkspace","JiraInstallPage","createInstall","installRequest","body","mutateAsync","errorFallbackMessage","loadingLabel","beforeRedirect","workspaceId"],"mappings":";AAAA,SAAQA,yBAAyB,QAAO,qBAAqB;AAC7D,SAAQC,WAAW,QAAO,QAAQ;AAClC,SAAQC,mBAAmB,QAAO,uCAAuC;AACzE,SAAQC,4BAA4B,QAAO,6BAA6B;AACxE,SAAQC,wBAAwB,QAAO,oBAAoB;AAE3D,OAAO,SAASC;IACd,MAAMC,gBAAgBH;IACtB,MAAMI,iBAAiBN,YACrB,OAAOO,OAAiC,MAAMF,cAAcG,WAAW,CAACD,OACxE;QAACF;KAAc;IAGjB,qBACE,KAACJ;QACCK,gBAAgBA;QAChBG,sBAAqB;QACrBC,cAAa;QACbC,gBAAgB,CAACC;YACf,IAAI;gBACFT,yBAAyBJ,6BAA6Ba;YACxD,EAAE,OAAM;YACN,wEAAwE;YAC1E;QACF;;AAGN"}
@@ -152,7 +152,7 @@ export function SentryCallbackPage() {
152
152
  return /*#__PURE__*/ _jsxs(CallbackColumn, {
153
153
  children: [
154
154
  /*#__PURE__*/ _jsxs("header", {
155
- className: "flex flex-col gap-8",
155
+ className: "flex flex-col gap-inline",
156
156
  children: [
157
157
  /*#__PURE__*/ _jsx(Header, {
158
158
  variant: "h2",
@@ -169,7 +169,7 @@ export function SentryCallbackPage() {
169
169
  role: "alert",
170
170
  type: "error",
171
171
  children: /*#__PURE__*/ _jsxs("div", {
172
- className: "flex flex-col gap-8",
172
+ className: "flex flex-col gap-inline",
173
173
  children: [
174
174
  /*#__PURE__*/ _jsx(Text, {
175
175
  size: "sm",
@@ -200,12 +200,12 @@ export function SentryCallbackPage() {
200
200
  })
201
201
  }) : null,
202
202
  /*#__PURE__*/ _jsx("section", {
203
- className: "flex flex-col gap-8",
203
+ className: "flex flex-col gap-inline",
204
204
  "aria-label": "Choose a workspace",
205
205
  children: orderedWorkspaces.map((workspace)=>/*#__PURE__*/ _jsx(Card, {
206
- className: "p-16",
206
+ className: "p-panel-compact",
207
207
  children: /*#__PURE__*/ _jsxs("div", {
208
- className: "flex items-center justify-between gap-12",
208
+ className: "flex items-center justify-between gap-cluster",
209
209
  children: [
210
210
  /*#__PURE__*/ _jsx(Text, {
211
211
  size: "md",
@@ -241,9 +241,9 @@ export function SentryCallbackPage() {
241
241
  }
242
242
  function CallbackColumn({ children }) {
243
243
  return /*#__PURE__*/ _jsx("main", {
244
- className: "flex min-h-screen bg-background-subtle-base px-16 py-32",
244
+ className: "flex min-h-screen bg-background-subtle-base px-row py-frame",
245
245
  children: /*#__PURE__*/ _jsx("div", {
246
- className: "mx-auto flex w-full max-w-[480px] flex-col justify-center gap-20",
246
+ className: "mx-auto flex w-full max-w-[480px] flex-col justify-center gap-section",
247
247
  children: children
248
248
  })
249
249
  });
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/pages/sentry-callback-page.tsx"],"sourcesContent":["import {useAuthState, useRefreshAuth} from '@shipfox/client-auth';\nimport {useRouteSearch} from '@shipfox/client-shell/runtime';\nimport {createSingleFlight, sessionStorageOrUndefined} from '@shipfox/client-ui';\nimport {Button, ButtonLink} from '@shipfox/react-ui/button';\nimport {Callout} from '@shipfox/react-ui/callout';\nimport {Card} from '@shipfox/react-ui/card';\nimport {FullPageLoader} from '@shipfox/react-ui/loader';\nimport {toast} from '@shipfox/react-ui/toast';\nimport {Header, Text} from '@shipfox/react-ui/typography';\nimport {useQueryClient} from '@tanstack/react-query';\nimport {Link, useNavigate} from '@tanstack/react-router';\nimport {useEffect, useMemo, useRef, useState} from 'react';\nimport {useCompleteIntegrationCallback} from '#application/complete-integration-callback.js';\nimport type {IntegrationConnection} from '#core/models.js';\nimport {connectSentry} from '#hooks/api/integrations.js';\nimport {\n classifySentryConnectError,\n clearSentryInstallWorkspace,\n parseSentryCallbackParams,\n preselectSentryWorkspace,\n readSentryInstallWorkspace,\n type SentryConnectFailure,\n} from '#sentry-callback.js';\nimport {resolveWorkspaceSlug} from '#workspace-navigation.js';\n\nconst connectRequests = createSingleFlight<string, IntegrationConnection>();\n\nexport function SentryCallbackPage() {\n const navigate = useNavigate();\n const queryClient = useQueryClient();\n const refreshAuth = useRefreshAuth();\n const {workspaces, isLoading} = useAuthState();\n const completeIntegrationCallback = useCompleteIntegrationCallback();\n\n const params = useRouteSearch(parseSentryCallbackParams);\n const storedWorkspaceId = useMemo(\n () => readSentryInstallWorkspace(sessionStorageOrUndefined()),\n [],\n );\n const preselection = preselectSentryWorkspace(storedWorkspaceId, workspaces);\n const preselectedId = preselection.kind === 'pick' ? preselection.preselectedId : undefined;\n\n const [connectingId, setConnectingId] = useState<string | undefined>();\n const [failure, setFailure] = useState<\n {workspaceId: string; failure: SentryConnectFailure} | undefined\n >();\n const [retryLocked, setRetryLocked] = useState(false);\n const disposedRef = useRef(false);\n\n useEffect(() => {\n disposedRef.current = false;\n return () => {\n disposedRef.current = true;\n };\n }, []);\n\n // Wait for auth before treating an empty workspace list as \"no workspace\": on\n // a cold return from Sentry, `workspaces` is [] until the session refresh\n // resolves, and bouncing to `/` then would discard the one-shot grant code.\n const noWorkspace = !isLoading && preselection.kind === 'none';\n useEffect(() => {\n if (!noWorkspace) return;\n toast.error('You need a workspace before installing Sentry.');\n navigate({to: '/', replace: true});\n }, [noWorkspace, navigate]);\n\n const retryAfterSeconds =\n failure?.failure.kind === 'retryable' ? failure.failure.retryAfterSeconds : undefined;\n useEffect(() => {\n // No backoff window (any non-rate-limited failure) re-enables Retry, so a\n // prior rate-limit lock can never strand the button in a disabled state.\n if (!retryAfterSeconds) {\n setRetryLocked(false);\n return;\n }\n setRetryLocked(true);\n const timer = setTimeout(() => setRetryLocked(false), retryAfterSeconds * 1000);\n return () => clearTimeout(timer);\n }, [retryAfterSeconds]);\n\n if (!params) {\n return (\n <CallbackColumn>\n <Callout role=\"alert\" type=\"error\">\n <Text size=\"sm\">\n This Sentry link is missing required parameters. Start the install again from your\n workspace settings.\n </Text>\n </Callout>\n <ButtonLink asChild variant=\"muted\" className=\"w-fit\">\n <Link to=\"/\">Back to Shipfox</Link>\n </ButtonLink>\n </CallbackColumn>\n );\n }\n\n // Hold the loader until auth resolves; the workspace list and the\n // noWorkspace redirect both depend on a settled `workspaces`.\n if (isLoading) return <FullPageLoader />;\n\n if (noWorkspace) return null;\n\n const connect = (workspaceId: string) => {\n setConnectingId(workspaceId);\n setFailure(undefined);\n const key = `${params.installationId}|${workspaceId}|${params.code}`;\n const request = connectRequests.run(\n key,\n async () =>\n await completeIntegrationCallback({\n input: workspaceId,\n refreshAuth,\n complete: async (selectedWorkspaceId, token) =>\n await connectSentry({\n body: {\n workspace_id: selectedWorkspaceId,\n code: params.code,\n installation_id: params.installationId,\n },\n token,\n }),\n }),\n );\n\n request\n .then(async () => {\n clearSentryInstallWorkspace(sessionStorageOrUndefined());\n if (disposedRef.current) return;\n toast.success('Sentry installed.');\n const workspaceSlug = await resolveWorkspaceSlug({\n workspaceId,\n fallbackWorkspaces: workspaces,\n queryClient,\n });\n if (disposedRef.current) return;\n await navigate(\n workspaceSlug\n ? {\n to: '/w/$workspaceSlug/settings/integrations',\n params: {workspaceSlug},\n replace: true,\n }\n : {to: '/', replace: true},\n );\n })\n .catch((error: unknown) => {\n if (disposedRef.current) return;\n const classified = classifySentryConnectError(error);\n if (classified.kind === 'terminal') {\n // Only a fresh install (new grant code) can recover; the stored\n // handoff has served its purpose either way.\n clearSentryInstallWorkspace(sessionStorageOrUndefined());\n }\n setConnectingId(undefined);\n setFailure({workspaceId, failure: classified});\n });\n };\n\n const orderedWorkspaces = preselectedId\n ? [\n ...workspaces.filter((workspace) => workspace.id === preselectedId),\n ...workspaces.filter((workspace) => workspace.id !== preselectedId),\n ]\n : workspaces;\n\n const failureWorkspaceId = failure?.workspaceId ?? preselectedId ?? workspaces[0]?.id;\n const failureWorkspace = failureWorkspaceId\n ? workspaces.find(({id}) => id === failureWorkspaceId)\n : undefined;\n\n return (\n <CallbackColumn>\n <header className=\"flex flex-col gap-8\">\n <Header variant=\"h2\">Install Sentry</Header>\n <Text size=\"sm\" className=\"text-foreground-neutral-muted\">\n {params.orgSlug\n ? `Install the Sentry org \"${params.orgSlug}\" in a workspace.`\n : 'Install this Sentry integration in a workspace.'}\n </Text>\n </header>\n\n {failure ? (\n <Callout role=\"alert\" type=\"error\">\n <div className=\"flex flex-col gap-8\">\n <Text size=\"sm\">{failure.failure.message}</Text>\n {failure.failure.kind === 'retryable' ? (\n <Button\n size=\"sm\"\n variant=\"secondary\"\n className=\"w-fit\"\n disabled={retryLocked || connectingId !== undefined}\n onClick={() => connect(failure.workspaceId)}\n >\n Retry\n </Button>\n ) : null}\n {failure.failure.kind === 'terminal' &&\n failure.failure.startOver &&\n failureWorkspace ? (\n <Button asChild size=\"sm\" variant=\"secondary\" className=\"w-fit\">\n <Link\n to=\"/w/$workspaceSlug/integrations/sentry\"\n params={{workspaceSlug: failureWorkspace.slug}}\n >\n Start over\n </Link>\n </Button>\n ) : null}\n </div>\n </Callout>\n ) : null}\n\n <section className=\"flex flex-col gap-8\" aria-label=\"Choose a workspace\">\n {orderedWorkspaces.map((workspace) => (\n <Card key={workspace.id} className=\"p-16\">\n <div className=\"flex items-center justify-between gap-12\">\n <Text size=\"md\" bold className=\"truncate\">\n {workspace.name}\n </Text>\n <Button\n variant=\"secondary\"\n disabled={connectingId !== undefined}\n isLoading={connectingId === workspace.id}\n onClick={() => connect(workspace.id)}\n >\n Install\n </Button>\n </div>\n </Card>\n ))}\n </section>\n\n {failureWorkspace ? (\n <ButtonLink asChild variant=\"muted\" className=\"w-fit\">\n <Link\n to=\"/w/$workspaceSlug/settings/integrations\"\n params={{workspaceSlug: failureWorkspace.slug}}\n >\n Back to settings\n </Link>\n </ButtonLink>\n ) : null}\n </CallbackColumn>\n );\n}\n\nfunction CallbackColumn({children}: {children: React.ReactNode}) {\n return (\n <main className=\"flex min-h-screen bg-background-subtle-base px-16 py-32\">\n <div className=\"mx-auto flex w-full max-w-[480px] flex-col justify-center gap-20\">\n {children}\n </div>\n </main>\n );\n}\n"],"names":["useAuthState","useRefreshAuth","useRouteSearch","createSingleFlight","sessionStorageOrUndefined","Button","ButtonLink","Callout","Card","FullPageLoader","toast","Header","Text","useQueryClient","Link","useNavigate","useEffect","useMemo","useRef","useState","useCompleteIntegrationCallback","connectSentry","classifySentryConnectError","clearSentryInstallWorkspace","parseSentryCallbackParams","preselectSentryWorkspace","readSentryInstallWorkspace","resolveWorkspaceSlug","connectRequests","SentryCallbackPage","navigate","queryClient","refreshAuth","workspaces","isLoading","completeIntegrationCallback","params","storedWorkspaceId","preselection","preselectedId","kind","undefined","connectingId","setConnectingId","failure","setFailure","retryLocked","setRetryLocked","disposedRef","current","noWorkspace","error","to","replace","retryAfterSeconds","timer","setTimeout","clearTimeout","CallbackColumn","role","type","size","asChild","variant","className","connect","workspaceId","key","installationId","code","request","run","input","complete","selectedWorkspaceId","token","body","workspace_id","installation_id","then","success","workspaceSlug","fallbackWorkspaces","catch","classified","orderedWorkspaces","filter","workspace","id","failureWorkspaceId","failureWorkspace","find","header","orgSlug","div","message","disabled","onClick","startOver","slug","section","aria-label","map","bold","name","children","main"],"mappings":"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"}
1
+ {"version":3,"sources":["../../src/pages/sentry-callback-page.tsx"],"sourcesContent":["import {useAuthState, useRefreshAuth} from '@shipfox/client-auth';\nimport {useRouteSearch} from '@shipfox/client-shell/runtime';\nimport {createSingleFlight, sessionStorageOrUndefined} from '@shipfox/client-ui';\nimport {Button, ButtonLink} from '@shipfox/react-ui/button';\nimport {Callout} from '@shipfox/react-ui/callout';\nimport {Card} from '@shipfox/react-ui/card';\nimport {FullPageLoader} from '@shipfox/react-ui/loader';\nimport {toast} from '@shipfox/react-ui/toast';\nimport {Header, Text} from '@shipfox/react-ui/typography';\nimport {useQueryClient} from '@tanstack/react-query';\nimport {Link, useNavigate} from '@tanstack/react-router';\nimport {useEffect, useMemo, useRef, useState} from 'react';\nimport {useCompleteIntegrationCallback} from '#application/complete-integration-callback.js';\nimport type {IntegrationConnection} from '#core/models.js';\nimport {connectSentry} from '#hooks/api/integrations.js';\nimport {\n classifySentryConnectError,\n clearSentryInstallWorkspace,\n parseSentryCallbackParams,\n preselectSentryWorkspace,\n readSentryInstallWorkspace,\n type SentryConnectFailure,\n} from '#sentry-callback.js';\nimport {resolveWorkspaceSlug} from '#workspace-navigation.js';\n\nconst connectRequests = createSingleFlight<string, IntegrationConnection>();\n\nexport function SentryCallbackPage() {\n const navigate = useNavigate();\n const queryClient = useQueryClient();\n const refreshAuth = useRefreshAuth();\n const {workspaces, isLoading} = useAuthState();\n const completeIntegrationCallback = useCompleteIntegrationCallback();\n\n const params = useRouteSearch(parseSentryCallbackParams);\n const storedWorkspaceId = useMemo(\n () => readSentryInstallWorkspace(sessionStorageOrUndefined()),\n [],\n );\n const preselection = preselectSentryWorkspace(storedWorkspaceId, workspaces);\n const preselectedId = preselection.kind === 'pick' ? preselection.preselectedId : undefined;\n\n const [connectingId, setConnectingId] = useState<string | undefined>();\n const [failure, setFailure] = useState<\n {workspaceId: string; failure: SentryConnectFailure} | undefined\n >();\n const [retryLocked, setRetryLocked] = useState(false);\n const disposedRef = useRef(false);\n\n useEffect(() => {\n disposedRef.current = false;\n return () => {\n disposedRef.current = true;\n };\n }, []);\n\n // Wait for auth before treating an empty workspace list as \"no workspace\": on\n // a cold return from Sentry, `workspaces` is [] until the session refresh\n // resolves, and bouncing to `/` then would discard the one-shot grant code.\n const noWorkspace = !isLoading && preselection.kind === 'none';\n useEffect(() => {\n if (!noWorkspace) return;\n toast.error('You need a workspace before installing Sentry.');\n navigate({to: '/', replace: true});\n }, [noWorkspace, navigate]);\n\n const retryAfterSeconds =\n failure?.failure.kind === 'retryable' ? failure.failure.retryAfterSeconds : undefined;\n useEffect(() => {\n // No backoff window (any non-rate-limited failure) re-enables Retry, so a\n // prior rate-limit lock can never strand the button in a disabled state.\n if (!retryAfterSeconds) {\n setRetryLocked(false);\n return;\n }\n setRetryLocked(true);\n const timer = setTimeout(() => setRetryLocked(false), retryAfterSeconds * 1000);\n return () => clearTimeout(timer);\n }, [retryAfterSeconds]);\n\n if (!params) {\n return (\n <CallbackColumn>\n <Callout role=\"alert\" type=\"error\">\n <Text size=\"sm\">\n This Sentry link is missing required parameters. Start the install again from your\n workspace settings.\n </Text>\n </Callout>\n <ButtonLink asChild variant=\"muted\" className=\"w-fit\">\n <Link to=\"/\">Back to Shipfox</Link>\n </ButtonLink>\n </CallbackColumn>\n );\n }\n\n // Hold the loader until auth resolves; the workspace list and the\n // noWorkspace redirect both depend on a settled `workspaces`.\n if (isLoading) return <FullPageLoader />;\n\n if (noWorkspace) return null;\n\n const connect = (workspaceId: string) => {\n setConnectingId(workspaceId);\n setFailure(undefined);\n const key = `${params.installationId}|${workspaceId}|${params.code}`;\n const request = connectRequests.run(\n key,\n async () =>\n await completeIntegrationCallback({\n input: workspaceId,\n refreshAuth,\n complete: async (selectedWorkspaceId, token) =>\n await connectSentry({\n body: {\n workspace_id: selectedWorkspaceId,\n code: params.code,\n installation_id: params.installationId,\n },\n token,\n }),\n }),\n );\n\n request\n .then(async () => {\n clearSentryInstallWorkspace(sessionStorageOrUndefined());\n if (disposedRef.current) return;\n toast.success('Sentry installed.');\n const workspaceSlug = await resolveWorkspaceSlug({\n workspaceId,\n fallbackWorkspaces: workspaces,\n queryClient,\n });\n if (disposedRef.current) return;\n await navigate(\n workspaceSlug\n ? {\n to: '/w/$workspaceSlug/settings/integrations',\n params: {workspaceSlug},\n replace: true,\n }\n : {to: '/', replace: true},\n );\n })\n .catch((error: unknown) => {\n if (disposedRef.current) return;\n const classified = classifySentryConnectError(error);\n if (classified.kind === 'terminal') {\n // Only a fresh install (new grant code) can recover; the stored\n // handoff has served its purpose either way.\n clearSentryInstallWorkspace(sessionStorageOrUndefined());\n }\n setConnectingId(undefined);\n setFailure({workspaceId, failure: classified});\n });\n };\n\n const orderedWorkspaces = preselectedId\n ? [\n ...workspaces.filter((workspace) => workspace.id === preselectedId),\n ...workspaces.filter((workspace) => workspace.id !== preselectedId),\n ]\n : workspaces;\n\n const failureWorkspaceId = failure?.workspaceId ?? preselectedId ?? workspaces[0]?.id;\n const failureWorkspace = failureWorkspaceId\n ? workspaces.find(({id}) => id === failureWorkspaceId)\n : undefined;\n\n return (\n <CallbackColumn>\n <header className=\"flex flex-col gap-inline\">\n <Header variant=\"h2\">Install Sentry</Header>\n <Text size=\"sm\" className=\"text-foreground-neutral-muted\">\n {params.orgSlug\n ? `Install the Sentry org \"${params.orgSlug}\" in a workspace.`\n : 'Install this Sentry integration in a workspace.'}\n </Text>\n </header>\n\n {failure ? (\n <Callout role=\"alert\" type=\"error\">\n <div className=\"flex flex-col gap-inline\">\n <Text size=\"sm\">{failure.failure.message}</Text>\n {failure.failure.kind === 'retryable' ? (\n <Button\n size=\"sm\"\n variant=\"secondary\"\n className=\"w-fit\"\n disabled={retryLocked || connectingId !== undefined}\n onClick={() => connect(failure.workspaceId)}\n >\n Retry\n </Button>\n ) : null}\n {failure.failure.kind === 'terminal' &&\n failure.failure.startOver &&\n failureWorkspace ? (\n <Button asChild size=\"sm\" variant=\"secondary\" className=\"w-fit\">\n <Link\n to=\"/w/$workspaceSlug/integrations/sentry\"\n params={{workspaceSlug: failureWorkspace.slug}}\n >\n Start over\n </Link>\n </Button>\n ) : null}\n </div>\n </Callout>\n ) : null}\n\n <section className=\"flex flex-col gap-inline\" aria-label=\"Choose a workspace\">\n {orderedWorkspaces.map((workspace) => (\n <Card key={workspace.id} className=\"p-panel-compact\">\n <div className=\"flex items-center justify-between gap-cluster\">\n <Text size=\"md\" bold className=\"truncate\">\n {workspace.name}\n </Text>\n <Button\n variant=\"secondary\"\n disabled={connectingId !== undefined}\n isLoading={connectingId === workspace.id}\n onClick={() => connect(workspace.id)}\n >\n Install\n </Button>\n </div>\n </Card>\n ))}\n </section>\n\n {failureWorkspace ? (\n <ButtonLink asChild variant=\"muted\" className=\"w-fit\">\n <Link\n to=\"/w/$workspaceSlug/settings/integrations\"\n params={{workspaceSlug: failureWorkspace.slug}}\n >\n Back to settings\n </Link>\n </ButtonLink>\n ) : null}\n </CallbackColumn>\n );\n}\n\nfunction CallbackColumn({children}: {children: React.ReactNode}) {\n return (\n <main className=\"flex min-h-screen bg-background-subtle-base px-row py-frame\">\n <div className=\"mx-auto flex w-full max-w-[480px] flex-col justify-center gap-section\">\n {children}\n </div>\n </main>\n );\n}\n"],"names":["useAuthState","useRefreshAuth","useRouteSearch","createSingleFlight","sessionStorageOrUndefined","Button","ButtonLink","Callout","Card","FullPageLoader","toast","Header","Text","useQueryClient","Link","useNavigate","useEffect","useMemo","useRef","useState","useCompleteIntegrationCallback","connectSentry","classifySentryConnectError","clearSentryInstallWorkspace","parseSentryCallbackParams","preselectSentryWorkspace","readSentryInstallWorkspace","resolveWorkspaceSlug","connectRequests","SentryCallbackPage","navigate","queryClient","refreshAuth","workspaces","isLoading","completeIntegrationCallback","params","storedWorkspaceId","preselection","preselectedId","kind","undefined","connectingId","setConnectingId","failure","setFailure","retryLocked","setRetryLocked","disposedRef","current","noWorkspace","error","to","replace","retryAfterSeconds","timer","setTimeout","clearTimeout","CallbackColumn","role","type","size","asChild","variant","className","connect","workspaceId","key","installationId","code","request","run","input","complete","selectedWorkspaceId","token","body","workspace_id","installation_id","then","success","workspaceSlug","fallbackWorkspaces","catch","classified","orderedWorkspaces","filter","workspace","id","failureWorkspaceId","failureWorkspace","find","header","orgSlug","div","message","disabled","onClick","startOver","slug","section","aria-label","map","bold","name","children","main"],"mappings":"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"}
@@ -9,10 +9,10 @@ export function SourceControlOnboardingPage() {
9
9
  capability: 'source_control'
10
10
  });
11
11
  return /*#__PURE__*/ _jsxs("div", {
12
- className: "mx-auto flex w-full max-w-[640px] flex-col gap-20",
12
+ className: "mx-auto flex w-full max-w-[640px] flex-col gap-section",
13
13
  children: [
14
14
  /*#__PURE__*/ _jsxs("header", {
15
- className: "flex flex-col gap-8",
15
+ className: "flex flex-col gap-inline",
16
16
  children: [
17
17
  /*#__PURE__*/ _jsx(Header, {
18
18
  variant: "h1",
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/pages/source-control-onboarding-page.tsx"],"sourcesContent":["import {useActiveWorkspace} from '@shipfox/client-auth';\nimport {Header, Text} from '@shipfox/react-ui/typography';\nimport {ProviderGrid} from '#components/provider-grid.js';\nimport {useIntegrationProvidersQuery} from '#hooks/api/integrations.js';\n\nexport function SourceControlOnboardingPage() {\n const workspace = useActiveWorkspace();\n const providersQuery = useIntegrationProvidersQuery({capability: 'source_control'});\n\n return (\n <div className=\"mx-auto flex w-full max-w-[640px] flex-col gap-20\">\n <header className=\"flex flex-col gap-8\">\n <Header variant=\"h1\">Install source control</Header>\n <Text size=\"md\" className=\"text-foreground-neutral-muted\">\n Shipfox needs a source control integration to import your repositories.\n </Text>\n </header>\n\n <ProviderGrid\n workspaceSlug={workspace.slug}\n providers={providersQuery.data ?? []}\n isPending={providersQuery.isPending}\n isFetching={providersQuery.isFetching}\n error={providersQuery.isError ? providersQuery.error : undefined}\n onRetry={() => void providersQuery.refetch()}\n emptyMessage=\"Enable at least one source-control provider in the application settings.\"\n />\n </div>\n );\n}\n"],"names":["useActiveWorkspace","Header","Text","ProviderGrid","useIntegrationProvidersQuery","SourceControlOnboardingPage","workspace","providersQuery","capability","div","className","header","variant","size","workspaceSlug","slug","providers","data","isPending","isFetching","error","isError","undefined","onRetry","refetch","emptyMessage"],"mappings":";AAAA,SAAQA,kBAAkB,QAAO,uBAAuB;AACxD,SAAQC,MAAM,EAAEC,IAAI,QAAO,+BAA+B;AAC1D,SAAQC,YAAY,QAAO,+BAA+B;AAC1D,SAAQC,4BAA4B,QAAO,6BAA6B;AAExE,OAAO,SAASC;IACd,MAAMC,YAAYN;IAClB,MAAMO,iBAAiBH,6BAA6B;QAACI,YAAY;IAAgB;IAEjF,qBACE,MAACC;QAAIC,WAAU;;0BACb,MAACC;gBAAOD,WAAU;;kCAChB,KAACT;wBAAOW,SAAQ;kCAAK;;kCACrB,KAACV;wBAAKW,MAAK;wBAAKH,WAAU;kCAAgC;;;;0BAK5D,KAACP;gBACCW,eAAeR,UAAUS,IAAI;gBAC7BC,WAAWT,eAAeU,IAAI,IAAI,EAAE;gBACpCC,WAAWX,eAAeW,SAAS;gBACnCC,YAAYZ,eAAeY,UAAU;gBACrCC,OAAOb,eAAec,OAAO,GAAGd,eAAea,KAAK,GAAGE;gBACvDC,SAAS,IAAM,KAAKhB,eAAeiB,OAAO;gBAC1CC,cAAa;;;;AAIrB"}
1
+ {"version":3,"sources":["../../src/pages/source-control-onboarding-page.tsx"],"sourcesContent":["import {useActiveWorkspace} from '@shipfox/client-auth';\nimport {Header, Text} from '@shipfox/react-ui/typography';\nimport {ProviderGrid} from '#components/provider-grid.js';\nimport {useIntegrationProvidersQuery} from '#hooks/api/integrations.js';\n\nexport function SourceControlOnboardingPage() {\n const workspace = useActiveWorkspace();\n const providersQuery = useIntegrationProvidersQuery({capability: 'source_control'});\n\n return (\n <div className=\"mx-auto flex w-full max-w-[640px] flex-col gap-section\">\n <header className=\"flex flex-col gap-inline\">\n <Header variant=\"h1\">Install source control</Header>\n <Text size=\"md\" className=\"text-foreground-neutral-muted\">\n Shipfox needs a source control integration to import your repositories.\n </Text>\n </header>\n\n <ProviderGrid\n workspaceSlug={workspace.slug}\n providers={providersQuery.data ?? []}\n isPending={providersQuery.isPending}\n isFetching={providersQuery.isFetching}\n error={providersQuery.isError ? providersQuery.error : undefined}\n onRetry={() => void providersQuery.refetch()}\n emptyMessage=\"Enable at least one source-control provider in the application settings.\"\n />\n </div>\n );\n}\n"],"names":["useActiveWorkspace","Header","Text","ProviderGrid","useIntegrationProvidersQuery","SourceControlOnboardingPage","workspace","providersQuery","capability","div","className","header","variant","size","workspaceSlug","slug","providers","data","isPending","isFetching","error","isError","undefined","onRetry","refetch","emptyMessage"],"mappings":";AAAA,SAAQA,kBAAkB,QAAO,uBAAuB;AACxD,SAAQC,MAAM,EAAEC,IAAI,QAAO,+BAA+B;AAC1D,SAAQC,YAAY,QAAO,+BAA+B;AAC1D,SAAQC,4BAA4B,QAAO,6BAA6B;AAExE,OAAO,SAASC;IACd,MAAMC,YAAYN;IAClB,MAAMO,iBAAiBH,6BAA6B;QAACI,YAAY;IAAgB;IAEjF,qBACE,MAACC;QAAIC,WAAU;;0BACb,MAACC;gBAAOD,WAAU;;kCAChB,KAACT;wBAAOW,SAAQ;kCAAK;;kCACrB,KAACV;wBAAKW,MAAK;wBAAKH,WAAU;kCAAgC;;;;0BAK5D,KAACP;gBACCW,eAAeR,UAAUS,IAAI;gBAC7BC,WAAWT,eAAeU,IAAI,IAAI,EAAE;gBACpCC,WAAWX,eAAeW,SAAS;gBACnCC,YAAYZ,eAAeY,UAAU;gBACrCC,OAAOb,eAAec,OAAO,GAAGd,eAAea,KAAK,GAAGE;gBACvDC,SAAS,IAAM,KAAKhB,eAAeiB,OAAO;gBAC1CC,cAAa;;;;AAIrB"}
@@ -1,5 +1,5 @@
1
1
  import type { IconName } from '@shipfox/react-ui/icon';
2
- export type ProviderSetupPath = '/w/$workspaceSlug/integrations/github' | '/w/$workspaceSlug/integrations/gitea' | '/w/$workspaceSlug/integrations/sentry' | '/w/$workspaceSlug/integrations/linear' | '/w/$workspaceSlug/integrations/slack';
2
+ export type ProviderSetupPath = '/w/$workspaceSlug/integrations/github' | '/w/$workspaceSlug/integrations/gitea' | '/w/$workspaceSlug/integrations/sentry' | '/w/$workspaceSlug/integrations/linear' | '/w/$workspaceSlug/integrations/slack' | '/w/$workspaceSlug/integrations/jira';
3
3
  interface RouteProviderCatalogEntry {
4
4
  kind: 'redirect-install' | 'direct-connect';
5
5
  iconName: IconName;
@@ -1 +1 @@
1
- {"version":3,"file":"provider-catalog.d.ts","sourceRoot":"","sources":["../src/provider-catalog.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAC,QAAQ,EAAC,MAAM,wBAAwB,CAAC;AAIrD,MAAM,MAAM,iBAAiB,GACzB,uCAAuC,GACvC,sCAAsC,GACtC,uCAAuC,GACvC,uCAAuC,GACvC,sCAAsC,CAAC;AAE3C,UAAU,yBAAyB;IACjC,IAAI,EAAE,kBAAkB,GAAG,gBAAgB,CAAC;IAC5C,QAAQ,EAAE,QAAQ,CAAC;IACnB,SAAS,EAAE,iBAAiB,CAAC;CAC9B;AAED,UAAU,yBAAyB;IACjC,IAAI,EAAE,eAAe,CAAC;IACtB,QAAQ,EAAE,QAAQ,CAAC;CACpB;AAED,MAAM,MAAM,oBAAoB,GAAG,yBAAyB,GAAG,yBAAyB,CAAC;AAEzF,eAAO,MAAM,gBAAgB,EAAE,MAAM,CAAC,MAAM,EAAE,oBAAoB,CA8BjE,CAAC"}
1
+ {"version":3,"file":"provider-catalog.d.ts","sourceRoot":"","sources":["../src/provider-catalog.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAC,QAAQ,EAAC,MAAM,wBAAwB,CAAC;AAIrD,MAAM,MAAM,iBAAiB,GACzB,uCAAuC,GACvC,sCAAsC,GACtC,uCAAuC,GACvC,uCAAuC,GACvC,sCAAsC,GACtC,qCAAqC,CAAC;AAE1C,UAAU,yBAAyB;IACjC,IAAI,EAAE,kBAAkB,GAAG,gBAAgB,CAAC;IAC5C,QAAQ,EAAE,QAAQ,CAAC;IACnB,SAAS,EAAE,iBAAiB,CAAC;CAC9B;AAED,UAAU,yBAAyB;IACjC,IAAI,EAAE,eAAe,CAAC;IACtB,QAAQ,EAAE,QAAQ,CAAC;CACpB;AAED,MAAM,MAAM,oBAAoB,GAAG,yBAAyB,GAAG,yBAAyB,CAAC;AAEzF,eAAO,MAAM,gBAAgB,EAAE,MAAM,CAAC,MAAM,EAAE,oBAAoB,CAmCjE,CAAC"}
@@ -20,6 +20,11 @@ export const PROVIDER_CATALOG = {
20
20
  iconName: PROVIDER_ICONS.slack,
21
21
  setupPath: '/w/$workspaceSlug/integrations/slack'
22
22
  },
23
+ jira: {
24
+ kind: 'redirect-install',
25
+ iconName: PROVIDER_ICONS.jira,
26
+ setupPath: '/w/$workspaceSlug/integrations/jira'
27
+ },
23
28
  gitea: {
24
29
  kind: 'direct-connect',
25
30
  iconName: PROVIDER_ICONS.gitea,
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/provider-catalog.ts"],"sourcesContent":["import {PROVIDER_ICONS} from '@shipfox/integration-icons';\nimport type {IconName} from '@shipfox/react-ui/icon';\n\n// Literal union (not string) so `<Link to={catalog.setupPath}>` stays typed\n// against TanStack Router's route tree.\nexport type ProviderSetupPath =\n | '/w/$workspaceSlug/integrations/github'\n | '/w/$workspaceSlug/integrations/gitea'\n | '/w/$workspaceSlug/integrations/sentry'\n | '/w/$workspaceSlug/integrations/linear'\n | '/w/$workspaceSlug/integrations/slack';\n\ninterface RouteProviderCatalogEntry {\n kind: 'redirect-install' | 'direct-connect';\n iconName: IconName;\n setupPath: ProviderSetupPath;\n}\n\ninterface ModalProviderCatalogEntry {\n kind: 'modal-connect';\n iconName: IconName;\n}\n\nexport type ProviderCatalogEntry = RouteProviderCatalogEntry | ModalProviderCatalogEntry;\n\nexport const PROVIDER_CATALOG: Record<string, ProviderCatalogEntry> = {\n github: {\n kind: 'redirect-install',\n iconName: PROVIDER_ICONS.github,\n setupPath: '/w/$workspaceSlug/integrations/github',\n },\n sentry: {\n kind: 'redirect-install',\n iconName: PROVIDER_ICONS.sentry,\n setupPath: '/w/$workspaceSlug/integrations/sentry',\n },\n linear: {\n kind: 'redirect-install',\n iconName: PROVIDER_ICONS.linear,\n setupPath: '/w/$workspaceSlug/integrations/linear',\n },\n slack: {\n kind: 'redirect-install',\n iconName: PROVIDER_ICONS.slack,\n setupPath: '/w/$workspaceSlug/integrations/slack',\n },\n gitea: {\n kind: 'direct-connect',\n iconName: PROVIDER_ICONS.gitea,\n setupPath: '/w/$workspaceSlug/integrations/gitea',\n },\n webhook: {\n kind: 'modal-connect',\n iconName: PROVIDER_ICONS.webhook,\n },\n};\n"],"names":["PROVIDER_ICONS","PROVIDER_CATALOG","github","kind","iconName","setupPath","sentry","linear","slack","gitea","webhook"],"mappings":"AAAA,SAAQA,cAAc,QAAO,6BAA6B;AAyB1D,OAAO,MAAMC,mBAAyD;IACpEC,QAAQ;QACNC,MAAM;QACNC,UAAUJ,eAAeE,MAAM;QAC/BG,WAAW;IACb;IACAC,QAAQ;QACNH,MAAM;QACNC,UAAUJ,eAAeM,MAAM;QAC/BD,WAAW;IACb;IACAE,QAAQ;QACNJ,MAAM;QACNC,UAAUJ,eAAeO,MAAM;QAC/BF,WAAW;IACb;IACAG,OAAO;QACLL,MAAM;QACNC,UAAUJ,eAAeQ,KAAK;QAC9BH,WAAW;IACb;IACAI,OAAO;QACLN,MAAM;QACNC,UAAUJ,eAAeS,KAAK;QAC9BJ,WAAW;IACb;IACAK,SAAS;QACPP,MAAM;QACNC,UAAUJ,eAAeU,OAAO;IAClC;AACF,EAAE"}
1
+ {"version":3,"sources":["../src/provider-catalog.ts"],"sourcesContent":["import {PROVIDER_ICONS} from '@shipfox/integration-icons';\nimport type {IconName} from '@shipfox/react-ui/icon';\n\n// Literal union (not string) so `<Link to={catalog.setupPath}>` stays typed\n// against TanStack Router's route tree.\nexport type ProviderSetupPath =\n | '/w/$workspaceSlug/integrations/github'\n | '/w/$workspaceSlug/integrations/gitea'\n | '/w/$workspaceSlug/integrations/sentry'\n | '/w/$workspaceSlug/integrations/linear'\n | '/w/$workspaceSlug/integrations/slack'\n | '/w/$workspaceSlug/integrations/jira';\n\ninterface RouteProviderCatalogEntry {\n kind: 'redirect-install' | 'direct-connect';\n iconName: IconName;\n setupPath: ProviderSetupPath;\n}\n\ninterface ModalProviderCatalogEntry {\n kind: 'modal-connect';\n iconName: IconName;\n}\n\nexport type ProviderCatalogEntry = RouteProviderCatalogEntry | ModalProviderCatalogEntry;\n\nexport const PROVIDER_CATALOG: Record<string, ProviderCatalogEntry> = {\n github: {\n kind: 'redirect-install',\n iconName: PROVIDER_ICONS.github,\n setupPath: '/w/$workspaceSlug/integrations/github',\n },\n sentry: {\n kind: 'redirect-install',\n iconName: PROVIDER_ICONS.sentry,\n setupPath: '/w/$workspaceSlug/integrations/sentry',\n },\n linear: {\n kind: 'redirect-install',\n iconName: PROVIDER_ICONS.linear,\n setupPath: '/w/$workspaceSlug/integrations/linear',\n },\n slack: {\n kind: 'redirect-install',\n iconName: PROVIDER_ICONS.slack,\n setupPath: '/w/$workspaceSlug/integrations/slack',\n },\n jira: {\n kind: 'redirect-install',\n iconName: PROVIDER_ICONS.jira,\n setupPath: '/w/$workspaceSlug/integrations/jira',\n },\n gitea: {\n kind: 'direct-connect',\n iconName: PROVIDER_ICONS.gitea,\n setupPath: '/w/$workspaceSlug/integrations/gitea',\n },\n webhook: {\n kind: 'modal-connect',\n iconName: PROVIDER_ICONS.webhook,\n },\n};\n"],"names":["PROVIDER_ICONS","PROVIDER_CATALOG","github","kind","iconName","setupPath","sentry","linear","slack","jira","gitea","webhook"],"mappings":"AAAA,SAAQA,cAAc,QAAO,6BAA6B;AA0B1D,OAAO,MAAMC,mBAAyD;IACpEC,QAAQ;QACNC,MAAM;QACNC,UAAUJ,eAAeE,MAAM;QAC/BG,WAAW;IACb;IACAC,QAAQ;QACNH,MAAM;QACNC,UAAUJ,eAAeM,MAAM;QAC/BD,WAAW;IACb;IACAE,QAAQ;QACNJ,MAAM;QACNC,UAAUJ,eAAeO,MAAM;QAC/BF,WAAW;IACb;IACAG,OAAO;QACLL,MAAM;QACNC,UAAUJ,eAAeQ,KAAK;QAC9BH,WAAW;IACb;IACAI,MAAM;QACJN,MAAM;QACNC,UAAUJ,eAAeS,IAAI;QAC7BJ,WAAW;IACb;IACAK,OAAO;QACLP,MAAM;QACNC,UAAUJ,eAAeU,KAAK;QAC9BL,WAAW;IACb;IACAM,SAAS;QACPR,MAAM;QACNC,UAAUJ,eAAeW,OAAO;IAClC;AACF,EAAE"}
@@ -0,0 +1,8 @@
1
+ import { JiraCallbackPage } from '#pages/jira-callback-page.js';
2
+ import { parseJiraCallbackQuery } from '../jira-callback.js';
3
+ declare const _default: import("@shipfox/client-shell/runtime").RouteImpl<{
4
+ readonly validateSearch: typeof parseJiraCallbackQuery;
5
+ readonly component: typeof JiraCallbackPage;
6
+ }>;
7
+ export default _default;
8
+ //# sourceMappingURL=jira-callback.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jira-callback.d.ts","sourceRoot":"","sources":["../../src/routes/jira-callback.tsx"],"names":[],"mappings":"AACA,OAAO,EAAC,gBAAgB,EAAC,MAAM,8BAA8B,CAAC;AAC9D,OAAO,EAAC,sBAAsB,EAAC,MAAM,qBAAqB,CAAC;;;;;AAE3D,wBAGG"}
@@ -0,0 +1,9 @@
1
+ import { defineRoute } from '@shipfox/client-shell/runtime';
2
+ import { JiraCallbackPage } from '#pages/jira-callback-page.js';
3
+ import { parseJiraCallbackQuery } from '../jira-callback.js';
4
+ export default defineRoute({
5
+ validateSearch: parseJiraCallbackQuery,
6
+ component: JiraCallbackPage
7
+ });
8
+
9
+ //# sourceMappingURL=jira-callback.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/routes/jira-callback.tsx"],"sourcesContent":["import {defineRoute} from '@shipfox/client-shell/runtime';\nimport {JiraCallbackPage} from '#pages/jira-callback-page.js';\nimport {parseJiraCallbackQuery} from '../jira-callback.js';\n\nexport default defineRoute({\n validateSearch: parseJiraCallbackQuery,\n component: JiraCallbackPage,\n});\n"],"names":["defineRoute","JiraCallbackPage","parseJiraCallbackQuery","validateSearch","component"],"mappings":"AAAA,SAAQA,WAAW,QAAO,gCAAgC;AAC1D,SAAQC,gBAAgB,QAAO,+BAA+B;AAC9D,SAAQC,sBAAsB,QAAO,sBAAsB;AAE3D,eAAeF,YAAY;IACzBG,gBAAgBD;IAChBE,WAAWH;AACb,GAAG"}
@@ -0,0 +1,6 @@
1
+ import { JiraInstallPage } from '#pages/jira-install-page.js';
2
+ declare const _default: import("@shipfox/client-shell/runtime").RouteImpl<{
3
+ readonly component: typeof JiraInstallPage;
4
+ }>;
5
+ export default _default;
6
+ //# sourceMappingURL=jira.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jira.d.ts","sourceRoot":"","sources":["../../src/routes/jira.tsx"],"names":[],"mappings":"AACA,OAAO,EAAC,eAAe,EAAC,MAAM,6BAA6B,CAAC;;;;AAE5D,wBAAyD"}
@@ -0,0 +1,7 @@
1
+ import { defineRoute } from '@shipfox/client-shell/runtime';
2
+ import { JiraInstallPage } from '#pages/jira-install-page.js';
3
+ export default defineRoute({
4
+ component: JiraInstallPage
5
+ });
6
+
7
+ //# sourceMappingURL=jira.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/routes/jira.tsx"],"sourcesContent":["import {defineRoute} from '@shipfox/client-shell/runtime';\nimport {JiraInstallPage} from '#pages/jira-install-page.js';\n\nexport default defineRoute({component: JiraInstallPage});\n"],"names":["defineRoute","JiraInstallPage","component"],"mappings":"AAAA,SAAQA,WAAW,QAAO,gCAAgC;AAC1D,SAAQC,eAAe,QAAO,8BAA8B;AAE5D,eAAeD,YAAY;IAACE,WAAWD;AAAe,GAAG"}