@domainkit/react 0.11.0 → 0.12.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.
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":["Context","Root","mergeMessages","State","Root","Header","Status","Body","Root","Card","Reason","Root","Status","Outcome","describeOutcome","OutcomeUi.Provider","OutcomeUi.Root","OutcomeUi.Composition","Actions","Operations.List","Dialog","BaseDialog","useController","Root","Dialog","Review.Dialog","Actions","Review.Actions","Outcome","Review.Outcome","Status","Review.Status","Flow","State","useController","Root","Outcome","describeOutcome","OutcomeUi.Provider","OutcomeUi.Root","OutcomeUi.Composition","Status","BaseCollapsible","Provider.Mark","Dialog","BaseDialog","BaseMenu","Cleanup.useController","BaseSwitch","Operations.List","Cleanup.Status","Cleanup.Outcome","Flow","Records.requirementsKey","useController","Root","Dialog","Review.Dialog","Review.Actions","Outcome","Review.Outcome","Status","Review.Status","Flow","RecordStatus","describeOutcome","OutcomeUi.Provider","OutcomeUi.Root","OutcomeUi.Composition","BasePopover","Connect.hostProvider","Connect.offering","Connect.holdsConnection","Connect.Card","Connect.Status","Connect.Prompt","Connect.answeredInPlace","Connect.Outcome","Provision.Dialog","Provision.Outcome","Connect.useController","Provision.useController","Cleanup.useController","Verify.useController","offering","Records.Table","Verify.Status"],"sources":["../src/composition.tsx","../src/icons.tsx","../src/messages.ts","../src/theme.ts","../src/domain-kit.tsx","../src/events.ts","../src/task.ts","../src/attempt.ts","../src/outcome.tsx","../src/records.tsx","../src/operations.tsx","../src/review.tsx","../src/cleanup.tsx","../src/provider.tsx","../src/connect.tsx","../src/provision.tsx","../src/verify.tsx","../src/domain.tsx","../src/testing.ts","../src/failure.ts"],"sourcesContent":["import { useRender } from \"@base-ui/react/use-render\";\nimport type { CSSProperties, ElementType, ReactElement } from \"react\";\n\nexport type ClassName<State> = string | ((state: State) => string | undefined);\nexport type Style<State> = CSSProperties | ((state: State) => CSSProperties | undefined);\n\n/**\n * What every rendered part accepts: the element's own props, a state-aware `className` and\n * `style`, and Base UI's `render` for replacing the element outright.\n */\nexport type PartProps<\n Tag extends ElementType = \"div\",\n State extends Record<string, unknown> = Record<string, unknown>,\n> = Omit<useRender.ElementProps<Tag>, \"className\" | \"style\"> & {\n readonly className?: ClassName<State>;\n readonly render?: useRender.RenderProp<State>;\n readonly style?: Style<State>;\n};\n\nexport function usePart<\n Tag extends keyof React.JSX.IntrinsicElements,\n State extends Record<string, unknown>,\n>(\n defaultTagName: Tag,\n componentProps: PartProps<Tag, State>,\n state: State,\n internalProps: Record<string, unknown>,\n): ReactElement {\n const { className, render, style, ...externalProps } = componentProps;\n const parameters: useRender.Parameters<State, Element, undefined> & {\n readonly className?: ClassName<State>;\n readonly style?: Style<State>;\n } = {\n ...(className === undefined ? {} : { className }),\n defaultTagName,\n props: [internalProps, externalProps] as unknown as Record<string, unknown>,\n ...(render === undefined ? {} : { render }),\n state,\n ...(style === undefined ? {} : { style }),\n };\n return useRender(parameters);\n}\n\n/** A part with no state of its own: one tag, one `data-domainkit-part`, host props on top. */\nexport function leafPart<Tag extends keyof React.JSX.IntrinsicElements>(\n defaultTagName: Tag,\n part: string,\n) {\n return function Leaf(props: PartProps<Tag, Record<string, unknown>>): ReactElement {\n return usePart(defaultTagName, props, {}, { \"data-domainkit-part\": part });\n };\n}\n","import { createContext, useContext, useMemo, type ReactNode } from \"react\";\n\n/**\n * Every glyph the package draws, in one place. Parts read them from context; none of them takes\n * an icon prop of its own, so a host swaps the whole set once on `DomainKit.Root`.\n */\nexport interface Icons {\n /** Points at what a control opens: the provider menu's own marker. */\n readonly chevron: ReactNode;\n readonly close: ReactNode;\n readonly copied: ReactNode;\n readonly copy: ReactNode;\n readonly download: ReactNode;\n readonly external: ReactNode;\n readonly failure: ReactNode;\n readonly pending: ReactNode;\n readonly success: ReactNode;\n readonly warning: ReactNode;\n}\n\nfunction Glyph({ children }: { readonly children: ReactNode }) {\n return (\n <svg\n aria-hidden=\"true\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n viewBox=\"0 0 24 24\"\n >\n {children}\n </svg>\n );\n}\n\nexport const defaultIcons = {\n chevron: (\n <Glyph>\n <path d=\"m6 9 6 6 6-6\" />\n </Glyph>\n ),\n close: (\n <Glyph>\n <path d=\"M18 6 6 18\" />\n <path d=\"m6 6 12 12\" />\n </Glyph>\n ),\n copied: (\n <Glyph>\n <path d=\"M20 6 9 17l-5-5\" />\n </Glyph>\n ),\n copy: (\n <Glyph>\n <rect height=\"14\" rx=\"2\" width=\"14\" x=\"8\" y=\"8\" />\n <path d=\"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2\" />\n </Glyph>\n ),\n download: (\n <Glyph>\n <path d=\"M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4\" />\n <path d=\"m7 10 5 5 5-5\" />\n <path d=\"M12 15V3\" />\n </Glyph>\n ),\n external: (\n <Glyph>\n <path d=\"M15 3h6v6\" />\n <path d=\"M10 14 21 3\" />\n <path d=\"M21 14v5a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h5\" />\n </Glyph>\n ),\n failure: (\n <Glyph>\n <circle cx=\"12\" cy=\"12\" r=\"9\" />\n <path d=\"M15 9 9 15\" />\n <path d=\"m9 9 6 6\" />\n </Glyph>\n ),\n pending: (\n <Glyph>\n <circle cx=\"12\" cy=\"12\" r=\"9\" />\n <path d=\"M12 7v5l3 2\" />\n </Glyph>\n ),\n success: (\n <Glyph>\n <circle cx=\"12\" cy=\"12\" r=\"9\" />\n <path d=\"m8.5 12.5 2.5 2.5 4.5-5\" />\n </Glyph>\n ),\n warning: (\n <Glyph>\n <path d=\"M10.3 3.9 2.4 17.5a2 2 0 0 0 1.7 3h15.8a2 2 0 0 0 1.7-3L13.7 3.9a2 2 0 0 0-3.4 0Z\" />\n <path d=\"M12 9v4\" />\n <path d=\"M12 17h.01\" />\n </Glyph>\n ),\n} as const satisfies Icons;\n\nconst IconsContext = createContext<Icons>(defaultIcons);\n\nexport function IconsProvider({\n children,\n icons,\n}: {\n readonly children: ReactNode;\n readonly icons?: Partial<Icons>;\n}) {\n const value = useMemo<Icons>(() => ({ ...defaultIcons, ...icons }), [icons]);\n return <IconsContext.Provider value={value}>{children}</IconsContext.Provider>;\n}\n\nexport function useIcons(): Icons {\n return useContext(IconsContext);\n}\n","/**\n * Every string the package can put on screen. Nothing renders a `_tag`, a reason name, or a\n * status literal directly: each one arrives here first, so a host translates the whole surface by\n * passing `messages` to `DomainKit.Root`.\n */\nimport type { DnsRecord, DomainKit, Plan, Reason, Receipt, Storage } from \"domainkit\";\n\nexport interface Catalog {\n // Actions\n readonly connect: string;\n /** The token method's button, which carries the verb rather than the method's own label. */\n readonly methodToken: string;\n readonly methodOAuth: (provider: string) => string;\n readonly methodIntegration: (provider: string) => string;\n readonly disconnect: string;\n readonly detach: string;\n readonly cancel: string;\n readonly close: string;\n readonly retry: string;\n readonly approve: string;\n /** The provisioning dialog's primary action: what it adds, and how many. */\n readonly addRecords: (count: number) => string;\n readonly decline: string;\n /** Why the primary action is unavailable: every operation the plan holds is blocked. */\n readonly everyRecordConflicts: string;\n readonly reviewChanges: string;\n readonly cleanUp: string;\n readonly checkDns: string;\n readonly checkAgain: string;\n readonly moreActions: string;\n /** Reveals the fields a provider does not need, such as an account id. */\n readonly moreOptions: string;\n /** Reveals the providers the dialog narrowed away. */\n readonly useAnotherProvider: string;\n /** Opens the token form where a provider also offers a method the customer clicks through. */\n readonly useTokenInstead: string;\n /** Returns from one method's form to the provider's methods. */\n readonly back: string;\n /** The connected card's own line, beside the provider's name. */\n readonly connected: string;\n readonly needsReconnect: string;\n /** The disconnect dialog's scope question, when the connection serves other domains too. */\n readonly disconnectScope: string;\n readonly disconnectThisDomain: string;\n readonly disconnectEveryDomain: (count: number) => string;\n readonly copy: string;\n readonly copied: string;\n readonly copyZone: string;\n readonly download: string;\n readonly useConnection: (label: string) => string;\n readonly chooseZone: string;\n readonly getToken: string;\n\n // Progress\n readonly loading: string;\n readonly connecting: string;\n readonly redirecting: string;\n readonly detaching: string;\n readonly disconnecting: string;\n readonly planning: string;\n readonly approving: string;\n readonly applying: string;\n readonly rejecting: string;\n readonly planningCleanup: string;\n readonly cleaning: string;\n readonly observing: string;\n\n // Connection\n readonly connectTitle: (provider: string) => string;\n /** The dialog heading, and the trigger, when no provider is named yet. */\n readonly connectAnyTitle: string;\n /** What the disconnected prompt says about the provider whose nameservers serve the domain. */\n readonly hostOwnsZone: string;\n readonly connectDescription: (domain: string) => string;\n readonly connectedTo: (provider: string) => string;\n /** Shown where a connect control would be when the customer may not connect. */\n readonly notConnected: string;\n readonly reconnectRequired: (provider: string) => string;\n readonly disconnectTitle: (provider: string) => string;\n /**\n * What disconnecting means, in the present. The default names DomainKit as what stops managing\n * the records; a host application overrides the key to name itself.\n */\n readonly disconnectConsent: (domain: string, provider: string) => string;\n /**\n * The option inside the disconnect dialog, over the records it would remove. Only this domain's\n * apply receipt proves what DomainKit created, so the words say which records go.\n */\n readonly disconnectWithCleanup: (count: number) => string;\n /** What the listed records do when that option is off. */\n readonly disconnectKeepsRecords: (provider: string) => string;\n readonly detachConsent: string;\n readonly detached: string;\n readonly reusableConnections: string;\n readonly authenticationAlternative: string;\n readonly discoveredConnection: (label: string) => string;\n readonly discoveryAmbiguous: string;\n readonly discoveryNotFound: (nameservers: ReadonlyArray<string>) => string;\n readonly noProviders: string;\n readonly fieldLabel: (name: string) => string;\n readonly optionalField: string;\n\n // Plan review\n readonly planTitle: string;\n readonly planConsent: string;\n readonly cleanupTitle: string;\n readonly cleanupConsent: string;\n readonly noChanges: string;\n readonly planExpires: (at: string) => string;\n readonly declinedBy: (actor: string) => string;\n readonly declineReason: (reason: string) => string;\n readonly operation: (operation: Plan.Operation) => string;\n readonly conflictReason: (reason: Plan.Conflict[\"reason\"]) => string;\n readonly attemptStatus: (status: Storage.AttemptStatus) => string;\n\n // Records\n readonly recordsCaption: (domain: string) => string;\n readonly headingType: string;\n readonly headingName: string;\n readonly headingValue: string;\n readonly headingStatus: string;\n readonly headingPurpose: string;\n readonly priority: (priority: number) => string;\n readonly ttl: (seconds: number) => string;\n readonly recordType: (record: DnsRecord.Observed) => string;\n\n // Receipts\n readonly applied: (receipt: Receipt.Model) => string;\n readonly cleaned: (receipt: Receipt.Model) => string;\n readonly partiallyAppliedTitle: string;\n readonly partiallyApplied: string;\n readonly partiallyCleanedTitle: string;\n readonly partiallyCleaned: string;\n readonly receiptOutcome: (outcome: Receipt.Outcome) => string;\n readonly skippedReason: (reason: Receipt.Skipped[\"reason\"]) => string;\n\n // Verification\n readonly requirementStatus: (status: Storage.RequirementStatus) => string;\n readonly overall: (overall: Storage.Overall) => string;\n readonly evidenceSource: (evidence: EvidenceLike) => string;\n readonly hostEvidenceStatus: (status: \"failed\" | \"ok\" | \"pending\") => string;\n /** What the requirement asks for, shown when an observation disagrees with it. */\n readonly expectedValue: (value: string) => string;\n /** What one observer actually read back for that name. */\n readonly observedValues: (values: ReadonlyArray<string>) => string;\n readonly observedNothing: string;\n readonly checkedAt: (at: string) => string;\n readonly nextCheckAt: (at: string) => string;\n readonly hostEvidence: string;\n readonly noEvidence: string;\n\n // Failures, rendered from the error's reason: a heading and the sentence under it\n readonly invalidInput: (reason: Reason.InvalidInput, context: OutcomeContext) => Outcome;\n readonly unauthenticated: (reason: Reason.Unauthenticated, context: OutcomeContext) => Outcome;\n readonly forbidden: (reason: Reason.Forbidden, context: OutcomeContext) => Outcome;\n readonly notFound: (reason: Reason.NotFound, context: OutcomeContext) => Outcome;\n readonly conflict: (reason: Reason.Conflict, context: OutcomeContext) => Outcome;\n readonly stale: (reason: Reason.Stale, context: OutcomeContext) => Outcome;\n readonly expired: (reason: Reason.Expired, context: OutcomeContext) => Outcome;\n readonly busy: (reason: Reason.Busy, context: OutcomeContext) => Outcome;\n readonly providerRejected: (reason: Reason.ProviderRejected, context: OutcomeContext) => Outcome;\n readonly providerUnavailable: (\n reason: Reason.ProviderUnavailable,\n context: OutcomeContext,\n ) => Outcome;\n readonly providerConflict: (reason: Reason.ProviderConflict, context: OutcomeContext) => Outcome;\n readonly unsupported: (reason: Reason.Unsupported, context: OutcomeContext) => Outcome;\n readonly reconnect: (reason: Reason.Reconnect, context: OutcomeContext) => Outcome;\n readonly storageFailed: (reason: Reason.StorageFailed, context: OutcomeContext) => Outcome;\n readonly cryptoFailed: (reason: Reason.CryptoFailed, context: OutcomeContext) => Outcome;\n readonly resolverFailed: (reason: Reason.ResolverFailed, context: OutcomeContext) => Outcome;\n}\n\n/** What an outcome says: a heading the customer reads first, then what to do about it. */\nexport interface Outcome {\n readonly title: string;\n /** What to do about it. Absent where the title has already said the whole of it. */\n readonly description?: string;\n}\n\n/**\n * What the flow was doing when it failed. The reason alone cannot name the provider a customer\n * typed a token for, so the part that renders the outcome supplies it.\n */\nexport interface OutcomeContext {\n /** The provider's display name, when the flow knows which one the customer acted on. */\n readonly provider?: string;\n readonly domain?: string;\n}\n\n/** The evidence shapes `Verify` produces, structurally, so the catalog needs no service import. */\nexport type EvidenceLike =\n | { readonly _tag: \"Host\"; readonly source: string; readonly label: string }\n | { readonly _tag: \"Provider\"; readonly provider: string }\n | { readonly _tag: \"PublicDns\"; readonly resolver: string };\n\nconst entity: Readonly<Record<Reason.NotFound[\"entity\"], string>> = {\n approval: \"approval\",\n attachment: \"domain attachment\",\n authorization: \"provider authorization\",\n connection: \"provider connection\",\n continuation: \"sign-in attempt\",\n plan: \"plan\",\n provider: \"provider\",\n receipt: \"receipt\",\n record: \"DNS record\",\n zone: \"DNS zone\",\n};\n\nconst expiredEntity: Readonly<Record<Reason.Expired[\"entity\"], string>> = {\n approval: \"approval\",\n continuation: \"sign-in attempt\",\n credential: \"provider credential\",\n plan: \"plan\",\n};\n\nconst recordTypes: Readonly<Record<Exclude<DnsRecord.Observed[\"_tag\"], \"Opaque\">, string>> = {\n A: \"A\",\n AAAA: \"AAAA\",\n CAA: \"CAA\",\n CNAME: \"CNAME\",\n MX: \"MX\",\n NS: \"NS\",\n SRV: \"SRV\",\n TXT: \"TXT\",\n};\n\n/** The provider the customer acted on, or a neutral stand-in when the flow does not know it. */\nconst named = (provider: string | undefined): string => provider ?? \"The provider\";\n\n/** The domain the failure is about, or a neutral stand-in. */\nconst where = (domain: string | undefined): string => domain ?? \"this domain\";\n\n/** `accountId` reads as \"Account id\" until a host names the field itself. */\nconst humanize = (name: string): string => {\n const spaced = name\n .replaceAll(/([a-z0-9])([A-Z])/g, \"$1 $2\")\n .replaceAll(/[_-]+/g, \" \")\n .trim();\n return spaced.charAt(0).toUpperCase() + spaced.slice(1).toLowerCase();\n};\n\nexport const english: Catalog = {\n connect: \"Connect\",\n methodToken: \"Connect with an API token\",\n methodOAuth: (provider) => `Continue with ${provider}`,\n methodIntegration: (provider) => `Install the ${provider} integration`,\n disconnect: \"Disconnect\",\n detach: \"Detach domain\",\n cancel: \"Cancel\",\n close: \"Close\",\n retry: \"Try again\",\n approve: \"Approve\",\n addRecords: (count) => (count === 1 ? \"Add 1 record\" : `Add ${count} records`),\n decline: \"Decline\",\n everyRecordConflicts: \"Resolve the records above at your provider, then review again.\",\n reviewChanges: \"Review changes\",\n cleanUp: \"Remove records\",\n checkDns: \"Check DNS\",\n checkAgain: \"Check again\",\n moreActions: \"More actions\",\n moreOptions: \"Add an account id\",\n useAnotherProvider: \"Use a different provider\",\n useTokenInstead: \"Use an API token instead\",\n back: \"Back\",\n connected: \"Connected\",\n needsReconnect: \"Needs reconnecting\",\n disconnectScope: \"This connection serves other domains.\",\n disconnectThisDomain: \"Only this domain\",\n disconnectEveryDomain: (count) => `All ${count} domains`,\n copy: \"Copy\",\n copied: \"Copied\",\n copyZone: \"Copy zone file\",\n download: \"Download\",\n useConnection: (label) => `Use ${label}`,\n chooseZone: \"Choose the zone that serves this domain\",\n getToken: \"Where do I find this?\",\n\n loading: \"Loading…\",\n connecting: \"Connecting…\",\n redirecting: \"Opening the provider…\",\n detaching: \"Detaching…\",\n disconnecting: \"Disconnecting…\",\n planning: \"Preparing DNS changes…\",\n approving: \"Approving…\",\n applying: \"Adding records…\",\n rejecting: \"Declining…\",\n planningCleanup: \"Preparing cleanup…\",\n cleaning: \"Removing records…\",\n observing: \"Checking DNS…\",\n\n connectTitle: (provider) => `Connect ${provider}`,\n connectAnyTitle: \"Connect a DNS provider\",\n hostOwnsZone: \"Owns DNS for this domain.\",\n connectDescription: (domain) => `Authorize DNS changes for ${domain}.`,\n connectedTo: (provider) => `${provider} connected`,\n notConnected: \"No DNS provider is connected.\",\n reconnectRequired: (provider) => `${provider} needs to be reconnected`,\n disconnectTitle: (provider) => `Disconnect ${provider}?`,\n disconnectConsent: (domain, provider) =>\n `DomainKit stops managing DNS for ${domain} through ${provider}.`,\n disconnectWithCleanup: (count) =>\n count === 1\n ? \"Remove the 1 record DomainKit added\"\n : `Remove the ${count} records DomainKit added`,\n disconnectKeepsRecords: (provider) => `Records stay in ${provider}.`,\n detachConsent: \"This domain is detached from the provider. Existing DNS records are preserved.\",\n detached: \"Domain detached. DNS records were preserved.\",\n reusableConnections: \"Connections you already have\",\n authenticationAlternative: \"or\",\n discoveredConnection: (label) => `${label} already serves this domain`,\n discoveryAmbiguous: \"More than one connection can serve this domain. Pick one.\",\n discoveryNotFound: (nameservers) =>\n nameservers.length === 0\n ? \"No connected provider serves this domain yet.\"\n : `No connected provider serves this domain. Its nameservers are ${nameservers.join(\", \")}.`,\n noProviders: \"No DNS providers are available.\",\n fieldLabel: humanize,\n optionalField: \"optional\",\n\n planTitle: \"Review DNS changes\",\n planConsent: \"Review the exact DNS operations before approving this plan.\",\n cleanupTitle: \"Review the records to remove\",\n cleanupConsent: \"Only records the apply receipt proves DomainKit created will be deleted.\",\n noChanges: \"No changes needed\",\n planExpires: (at) => `This plan expires at ${at}.`,\n declinedBy: (actor) => `Declined by ${actor}. Build a new plan to continue.`,\n declineReason: (reason) => `Reason: ${reason}`,\n operation: (operation) => {\n switch (operation._tag) {\n case \"Create\":\n return \"Add\";\n case \"Noop\":\n return \"Already in place\";\n case \"Delete\":\n return \"Remove\";\n case \"Conflict\":\n return \"Blocked\";\n }\n },\n conflictReason: (reason) => {\n switch (reason) {\n case \"exclusive-name\":\n return \"Another record already owns this name.\";\n case \"cname-collision\":\n return \"A CNAME cannot share a name with other records.\";\n case \"value-mismatch\":\n return \"A record with this name holds a different value.\";\n case \"opaque\":\n return \"A record here uses a form DomainKit will not overwrite.\";\n case \"missing\":\n return \"The record this plan expected is gone.\";\n }\n },\n attemptStatus: (status) => {\n switch (status) {\n case \"planned\":\n return \"Awaiting review\";\n case \"approved\":\n return \"Approved\";\n case \"applying\":\n return \"Applying\";\n case \"complete\":\n return \"Applied\";\n case \"partial\":\n return \"Partly applied\";\n case \"failed\":\n return \"Failed\";\n case \"expired\":\n return \"Expired\";\n case \"rejected\":\n return \"Declined\";\n }\n },\n\n recordsCaption: (domain) => `DNS records for ${domain}`,\n headingType: \"Type\",\n headingName: \"Name\",\n headingValue: \"Value\",\n headingStatus: \"Status\",\n headingPurpose: \"Purpose\",\n priority: (priority) => `Priority ${priority}`,\n ttl: (seconds) => `TTL ${seconds}s`,\n recordType: (record) => (record._tag === \"Opaque\" ? record.type : recordTypes[record._tag]),\n\n applied: (receipt) =>\n receipt.status === \"complete\" ? \"DNS records added.\" : \"Some DNS records were not added.\",\n cleaned: (receipt) =>\n receipt.status === \"complete\" ? \"DNS records removed.\" : \"Some DNS records were not removed.\",\n partiallyAppliedTitle: \"Some DNS changes did not land\",\n partiallyApplied: \"Review what applied, then retry. Retrying is safe.\",\n partiallyCleanedTitle: \"Some DNS records are still there\",\n partiallyCleaned: \"Review what is left, then retry. Retrying is safe.\",\n receiptOutcome: (outcome) => {\n switch (outcome._tag) {\n case \"Applied\":\n return \"Done\";\n case \"Skipped\":\n return \"Skipped\";\n case \"Failed\":\n return outcome.message;\n }\n },\n skippedReason: (reason) => {\n switch (reason) {\n case \"noop\":\n return \"The record was already in place.\";\n case \"not-approved\":\n return \"The approval left this operation out.\";\n case \"not-attempted\":\n return \"An earlier operation failed before this one ran.\";\n }\n },\n\n requirementStatus: (status) => {\n switch (status) {\n case \"satisfied\":\n return \"Found\";\n case \"missing\":\n return \"Missing\";\n case \"mismatch\":\n return \"Different value\";\n case \"unknown\":\n return \"Not checked\";\n }\n },\n overall: (overall) => {\n switch (overall) {\n case \"ready\":\n return \"Ready\";\n case \"pending\":\n return \"Pending\";\n case \"failed\":\n return \"Failed\";\n }\n },\n evidenceSource: (evidence) => {\n switch (evidence._tag) {\n case \"Host\":\n return evidence.label;\n case \"Provider\":\n return `${evidence.provider} records`;\n case \"PublicDns\":\n return `Public DNS via ${evidence.resolver}`;\n }\n },\n hostEvidenceStatus: (status) => {\n switch (status) {\n case \"ok\":\n return \"Ready\";\n case \"pending\":\n return \"Pending\";\n case \"failed\":\n return \"Failed\";\n }\n },\n expectedValue: (value) => `Expected ${value}`,\n observedValues: (values) => `Found ${values.join(\", \")}`,\n observedNothing: \"Found nothing\",\n checkedAt: (at) => `Checked ${at}`,\n nextCheckAt: (at) => `Next check ${at}`,\n hostEvidence: \"Other checks\",\n noEvidence: \"Nothing has been checked yet.\",\n\n invalidInput: (reason) => ({\n description: reason.message,\n title:\n reason.field === undefined\n ? \"Check what you entered\"\n : `Check the ${humanize(reason.field).toLowerCase()}`,\n }),\n // The dialog's heading already names the provider, so the outcome answers about the credential\n // and nothing else. A longer title wraps in the column beside the retry, and a second line under\n // it repeats what the title said.\n unauthenticated: () => ({\n title: \"Token not accepted\",\n }),\n forbidden: (_reason, context) => ({\n description: `The connection needs permission to edit DNS for ${where(context.domain)}.`,\n title: \"This connection can't change DNS here\",\n }),\n notFound: (reason) => ({\n description: \"Reload the page and start this step again.\",\n title: `That ${entity[reason.entity]} no longer exists`,\n }),\n conflict: (reason) => ({\n description: \"Review what the zone already holds, then build a new plan.\",\n title:\n reason.operations.length === 1\n ? \"A record is in the way\"\n : `${reason.operations.length} records are in the way`,\n }),\n stale: () => ({\n description: \"Review the new plan before you apply it.\",\n title: \"The zone changed since you reviewed\",\n }),\n expired: (reason) => ({\n description: \"Start this step again.\",\n title: `That ${expiredEntity[reason.entity]} expired`,\n }),\n busy: () => ({\n description: \"Wait for it to finish, then try again.\",\n title: \"Another change is running\",\n }),\n providerRejected: (reason, context) => ({\n description: reason.message,\n title: `${named(context.provider ?? reason.provider)} refused the change`,\n }),\n providerUnavailable: (reason, context) => ({\n description: \"Nothing changed. Try again in a minute.\",\n title: `${named(context.provider ?? reason.provider)} isn't responding`,\n }),\n providerConflict: (reason, context) => ({\n description: \"Remove or rename that record at the provider, then try again.\",\n title: `${named(context.provider ?? reason.provider)} already holds a conflicting record`,\n }),\n unsupported: (reason, context) => ({\n description: \"Nothing changed. This step needs a provider that can do it.\",\n title: `${named(context.provider ?? reason.provider)} cannot ${reason.operation}`,\n }),\n reconnect: (reason, context) => ({\n description: \"The stored credential no longer works. Connect again to continue.\",\n title: `Reconnect ${named(context.provider ?? reason.provider)}`,\n }),\n storageFailed: () => ({\n description: \"Nothing changed. Try again.\",\n title: \"The change could not be saved\",\n }),\n cryptoFailed: () => ({\n description: \"Connect the provider again to replace it.\",\n title: \"A stored credential could not be read\",\n }),\n resolverFailed: (reason) => ({\n description: \"The lookup failed, which says nothing about your DNS. Try again in a moment.\",\n title: `DNS lookups through ${reason.resolver} failed`,\n }),\n};\n\nexport const merge = (overrides: Partial<Catalog> = {}): Catalog => ({ ...english, ...overrides });\n\n/** The title and description for a failure, chosen by the error's reason. */\nexport const outcome = (\n error: DomainKit.Error,\n catalog: Catalog,\n context: OutcomeContext = {},\n): Outcome => {\n const reason = error.reason;\n switch (reason._tag) {\n case \"InvalidInput\":\n return catalog.invalidInput(reason, context);\n case \"Unauthenticated\":\n return catalog.unauthenticated(reason, context);\n case \"Forbidden\":\n return catalog.forbidden(reason, context);\n case \"NotFound\":\n return catalog.notFound(reason, context);\n case \"Conflict\":\n return catalog.conflict(reason, context);\n case \"Stale\":\n return catalog.stale(reason, context);\n case \"Expired\":\n return catalog.expired(reason, context);\n case \"Busy\":\n return catalog.busy(reason, context);\n case \"ProviderRejected\":\n return catalog.providerRejected(reason, context);\n case \"ProviderUnavailable\":\n return catalog.providerUnavailable(reason, context);\n case \"ProviderConflict\":\n return catalog.providerConflict(reason, context);\n case \"Unsupported\":\n return catalog.unsupported(reason, context);\n case \"Reconnect\":\n return catalog.reconnect(reason, context);\n case \"StorageFailed\":\n return catalog.storageFailed(reason, context);\n case \"CryptoFailed\":\n return catalog.cryptoFailed(reason, context);\n case \"ResolverFailed\":\n return catalog.resolverFailed(reason, context);\n }\n};\n\n/** The same failure as one sentence, for a host that renders text rather than a card. */\nexport const failure = (\n error: DomainKit.Error,\n catalog: Catalog,\n context: OutcomeContext = {},\n): string => {\n const { description, title } = outcome(error, catalog, context);\n return description === undefined ? `${title}.` : `${title}. ${description}`;\n};\n","import type { CSSProperties } from \"react\";\n\nexport interface Theme {\n readonly accent?: string;\n readonly accentContrast?: string;\n readonly backdrop?: string;\n readonly background?: string;\n readonly border?: string;\n readonly danger?: string;\n readonly dangerContrast?: string;\n readonly fill?: string;\n readonly fontFamily?: string;\n readonly muted?: string;\n readonly radius?: string;\n readonly shadow?: string;\n readonly success?: string;\n readonly text?: string;\n readonly warning?: string;\n}\n\nconst variables = {\n accent: \"--domainkit-accent\",\n accentContrast: \"--domainkit-accent-contrast\",\n backdrop: \"--domainkit-backdrop\",\n background: \"--domainkit-background\",\n border: \"--domainkit-border\",\n danger: \"--domainkit-danger\",\n dangerContrast: \"--domainkit-danger-contrast\",\n fill: \"--domainkit-fill\",\n fontFamily: \"--domainkit-font-family\",\n muted: \"--domainkit-muted\",\n radius: \"--domainkit-radius\",\n shadow: \"--domainkit-shadow\",\n success: \"--domainkit-success\",\n text: \"--domainkit-text\",\n warning: \"--domainkit-warning\",\n} as const satisfies Record<keyof Theme, string>;\n\nexport function toStyle(theme: Theme = {}): CSSProperties {\n return Object.fromEntries(\n Object.entries(theme).flatMap(([key, value]) =>\n value === undefined ? [] : [[variables[key as keyof Theme], value]],\n ),\n ) as CSSProperties;\n}\n","import { Transport } from \"domainkit/client\";\nimport * as Effect from \"effect/Effect\";\nimport {\n createContext,\n useCallback,\n useContext,\n useLayoutEffect,\n useMemo,\n useRef,\n useSyncExternalStore,\n type ReactNode,\n type RefObject,\n} from \"react\";\n\nimport type { PartProps } from \"./composition.tsx\";\nimport { usePart } from \"./composition.tsx\";\nimport type { Listener } from \"./events.ts\";\nimport type { Icons } from \"./icons.tsx\";\nimport { IconsProvider } from \"./icons.tsx\";\nimport type { Catalog } from \"./messages.ts\";\nimport { merge as mergeMessages } from \"./messages.ts\";\nimport type { Marks } from \"./provider.tsx\";\nimport type { Theme } from \"./theme.ts\";\nimport { toStyle } from \"./theme.ts\";\n\nexport interface RootState extends Record<string, unknown> {\n readonly colorScheme: \"dark\" | \"inherit\" | \"light\";\n}\n\nexport interface RootProps extends Omit<PartProps<\"div\", RootState>, \"children\"> {\n readonly children: ReactNode;\n readonly colorScheme?: RootState[\"colorScheme\"];\n readonly icons?: Partial<Icons>;\n readonly marks?: Marks;\n readonly messages?: Partial<Catalog>;\n /** Where an interactive provider flow sends the customer. Defaults to `window.location`. */\n readonly navigate?: (url: string) => void;\n readonly onEvent?: Listener;\n readonly portalContainer?: HTMLElement | null;\n /**\n * Render the state without the controls that change it, for a customer who may read the domain\n * but not write to it. Capability gating already hides a group the transport does not declare;\n * this covers authorization the transport cannot express, such as a member of an organisation.\n */\n readonly readOnly?: boolean;\n /** Bump to re-inspect every mounted domain after a change the UI did not make. */\n readonly revision?: number;\n readonly theme?: Theme;\n /** The transport, by value. Rebuilding it inline on every render does not restart controllers. */\n readonly transport: Transport.Interface;\n}\n\ninterface ContextValue {\n readonly capabilities: ReadonlyArray<Transport.Capability>;\n readonly colorScheme: RootState[\"colorScheme\"];\n readonly emit: Listener;\n readonly marks: Marks;\n readonly messages: Catalog;\n readonly navigate: (url: string) => void;\n readonly portalContainer: RefObject<HTMLElement | null>;\n readonly readOnly: boolean;\n readonly revision: number;\n readonly themeStyle: ReturnType<typeof toStyle>;\n readonly transport: Transport.Interface;\n}\n\nconst Context = createContext<ContextValue | null>(null);\n\nconst navigateInBrowser = (url: string): void => {\n if (typeof window === \"undefined\") {\n throw new Error(\"DomainKit provider authorization requires a browser or a `navigate` prop\");\n }\n window.location.assign(url);\n};\n\nexport interface StableTransport {\n readonly transport: Transport.Interface;\n readonly capabilities: ReadonlyArray<Transport.Capability>;\n}\n\ntype Method = (...args: ReadonlyArray<never>) => Effect.Effect<unknown, unknown>;\n\n/**\n * A transport whose identity survives re-renders. Each method reads the newest transport when it\n * runs, so a host may write `<DomainKit.Root transport={Transport.fromFetch(\"/api/domainkit\")}>`\n * inline and controllers still see one transport for the whole mount. Swapping in a transport\n * that declares different capability groups rebuilds it, and every controller re-runs.\n */\nconst useStableTransport = (transport: Transport.Interface): StableTransport => {\n const latest = useRef(transport);\n useLayoutEffect(() => {\n latest.current = transport;\n });\n const signature = Transport.capabilities(transport).join(\",\");\n return useMemo(() => {\n const capabilities = Transport.capabilities(latest.current);\n const stable = Object.fromEntries(\n capabilities.map((capability) => {\n const group = latest.current[capability] as unknown as Record<string, Method>;\n return [\n capability,\n Object.fromEntries(\n Object.keys(group).map((name) => [\n name,\n (...args: ReadonlyArray<never>) =>\n Effect.suspend(() => {\n const live = latest.current[capability] as unknown as Record<string, Method>;\n const method = live[name];\n if (method === undefined) {\n throw new Error(`The transport no longer declares ${capability}.${name}`);\n }\n return method(...args);\n }),\n ]),\n ),\n ];\n }),\n ) as Transport.Interface;\n return { capabilities, transport: stable };\n }, [signature]);\n};\n\nconst resolvePortalContainer = (\n container: HTMLElement | null,\n ownerDocument: Document | null,\n): HTMLElement | null => {\n if (container === null || ownerDocument === null) return null;\n return container.ownerDocument === ownerDocument && container.getRootNode() === ownerDocument\n ? container\n : null;\n};\n\nconst usePortalContainer = (container: HTMLElement | null): HTMLElement | null => {\n const ownerDocument = useMemo(() => container?.ownerDocument ?? null, [container]);\n const subscribe = useCallback(\n (notify: () => void) => {\n if (ownerDocument === null || typeof MutationObserver === \"undefined\") return () => {};\n const observer = new MutationObserver(notify);\n observer.observe(ownerDocument, { childList: true, subtree: true });\n return () => observer.disconnect();\n },\n [ownerDocument],\n );\n const getSnapshot = useCallback(\n () => resolvePortalContainer(container, ownerDocument),\n [container, ownerDocument],\n );\n return useSyncExternalStore(subscribe, getSnapshot, getSnapshot);\n};\n\nexport function Root({\n children,\n colorScheme = \"inherit\",\n icons,\n marks = {},\n messages,\n navigate = navigateInBrowser,\n onEvent,\n portalContainer = null,\n readOnly = false,\n revision = 0,\n theme,\n transport,\n ...props\n}: RootProps) {\n const { capabilities, transport: stable } = useStableTransport(transport);\n const onEventRef = useRef(onEvent);\n useLayoutEffect(() => {\n onEventRef.current = onEvent;\n }, [onEvent]);\n const emit = useCallback<Listener>((event) => {\n try {\n onEventRef.current?.(event);\n } catch {\n // Host observers are best-effort and cannot change a completed operation's outcome.\n }\n }, []);\n const themeStyle = toStyle(theme);\n const resolvedPortalContainer = usePortalContainer(portalContainer);\n const portalContainerRef = useMemo<RefObject<HTMLElement | null>>(\n () => ({ current: resolvedPortalContainer }),\n [resolvedPortalContainer],\n );\n const value: ContextValue = {\n capabilities,\n colorScheme,\n emit,\n marks,\n messages: mergeMessages(messages),\n navigate,\n portalContainer: portalContainerRef,\n readOnly,\n revision,\n themeStyle,\n transport: stable,\n };\n const content = usePart(\n \"div\",\n props,\n { colorScheme },\n {\n children,\n \"data-color-scheme\": colorScheme,\n \"data-domainkit-root\": \"\",\n style: themeStyle,\n },\n );\n return (\n <Context.Provider value={value}>\n <IconsProvider {...(icons === undefined ? {} : { icons })}>{content}</IconsProvider>\n </Context.Provider>\n );\n}\n\nexport function useDomainKit(): ContextValue {\n const value = useContext(Context);\n if (value === null) {\n throw new Error(\"DomainKit components must be rendered inside DomainKit.Root\");\n }\n return value;\n}\n\n/** The transport `DomainKit.Root` holds, with the identity it keeps for the whole mount. */\nexport function useTransport(): Transport.Interface {\n return useDomainKit().transport;\n}\n\nconst ReadOnlyContext = createContext<boolean | null>(null);\n\n/** Narrow one subtree to read-only without touching the rest of the page. */\nexport function ReadOnly({\n children,\n value,\n}: {\n readonly children: ReactNode;\n readonly value: boolean;\n}) {\n return <ReadOnlyContext.Provider value={value}>{children}</ReadOnlyContext.Provider>;\n}\n\n/** Whether this part may offer controls that change the domain. */\nexport function useReadOnly(): boolean {\n const scoped = useContext(ReadOnlyContext);\n const root = useDomainKit().readOnly;\n return scoped ?? root;\n}\n\n/** Which capability groups the host's transport declares, for gating a custom part. */\nexport function useCapabilities(): ReadonlyArray<Transport.Capability> {\n return useDomainKit().capabilities;\n}\n","import type { DomainKit, Receipt } from \"domainkit\";\nimport type { Transport } from \"domainkit/client\";\nimport * as Data from \"effect/Data\";\n\n/** What a customer finished doing, for host notifications, analytics, and audit trails. */\nexport type Event = Data.TaggedEnum<{\n Connected: {\n readonly domain: string;\n readonly connectionId: string;\n readonly snapshot: Transport.Snapshot;\n };\n Detached: { readonly domain: string };\n Disconnected: { readonly domain: string; readonly connectionId: string };\n Applied: { readonly domain: string; readonly receipt: Receipt.Model };\n Cleaned: { readonly domain: string; readonly receipt: Receipt.Model };\n Declined: { readonly domain: string; readonly attempt: Transport.Attempt };\n Failed: { readonly domain: string; readonly error: DomainKit.Error };\n}>;\nexport const Event = Data.taggedEnum<Event>();\n\nexport type Listener = (event: Event) => void;\n","/**\n * The one place the package leaves Effect. Every controller runs its transport calls through\n * `useRunner`, which interrupts the call in flight when a newer one starts or the component\n * unmounts, and drops results that arrive after either.\n */\nimport { DomainKit, Reason } from \"domainkit\";\nimport * as Effect from \"effect/Effect\";\nimport * as Exit from \"effect/Exit\";\nimport * as Option from \"effect/Option\";\nimport { useEffect, useMemo, useRef } from \"react\";\n\nexport interface Runner {\n /**\n * Run `effect`, replacing whatever this runner had in flight. `onSuccess` and `onFailure` fire\n * only while this call is still the newest and the component is mounted.\n */\n readonly run: <A>(\n effect: Effect.Effect<A, DomainKit.Error>,\n handlers: {\n readonly onSuccess: (value: A) => void;\n readonly onFailure: (error: DomainKit.Error) => void;\n },\n ) => void;\n /** Stop the call in flight without starting another. */\n readonly cancel: () => void;\n}\n\n/** A defect is not a lifecycle failure; report it in the shape the UI already renders. */\nconst defect = (cause: unknown): DomainKit.Error =>\n new DomainKit.Error({\n reason: new Reason.ProviderUnavailable({\n provider: \"domainkit\",\n message: `The transport failed: ${String(cause)}`,\n }),\n });\n\ninterface Live {\n readonly id: number;\n interrupt: (() => void) | null;\n}\n\nexport function useRunner(): Runner {\n const state = useRef<{ mounted: boolean; next: number; live: Live | null }>({\n live: null,\n mounted: true,\n next: 0,\n });\n useEffect(() => {\n const current = state.current;\n current.mounted = true;\n return () => {\n current.mounted = false;\n current.live?.interrupt?.();\n current.live = null;\n };\n }, []);\n return useMemo<Runner>(() => {\n const stop = () => {\n state.current.live?.interrupt?.();\n state.current.live = null;\n };\n return {\n cancel: stop,\n run: (effect, handlers) => {\n stop();\n const live: Live = { id: (state.current.next += 1), interrupt: null };\n state.current.live = live;\n const interrupt = Effect.runCallback(effect, {\n onExit: (exit) => {\n if (state.current.live?.id !== live.id || !state.current.mounted) return;\n state.current.live = null;\n if (Exit.isSuccess(exit)) {\n handlers.onSuccess(exit.value);\n return;\n }\n // Read both before the interrupt guard: it narrows `exit` to the success side.\n const cause = exit.cause;\n const error = Exit.findErrorOption(exit);\n if (Exit.hasInterrupts(exit)) return;\n handlers.onFailure(Option.isSome(error) ? error.value : defect(cause));\n },\n });\n // A synchronous effect already ran `onExit` and cleared `live`; only a call still in\n // flight needs an interrupt handle.\n if (state.current.live?.id === live.id) live.interrupt = () => interrupt();\n },\n };\n }, []);\n}\n","/**\n * The plan -> approve -> apply machine both `Provision` and `Cleanup` run. They differ only in\n * which plan they build and which event they emit when the receipt lands, so the machine lives\n * here once and each namespace exports its own controller over it.\n */\nimport type { Approval, DomainKit, Plan, Receipt } from \"domainkit\";\nimport type { Transport } from \"domainkit/client\";\nimport * as Data from \"effect/Data\";\nimport * as Effect from \"effect/Effect\";\nimport { useCallback, useEffect, useRef, useState } from \"react\";\n\nimport { useDomainKit, useReadOnly } from \"./domain-kit.tsx\";\nimport { Event } from \"./events.ts\";\nimport { useRunner } from \"./task.ts\";\n\nexport type State = Data.TaggedEnum<{\n Idle: {};\n Planning: {};\n Planned: { readonly plan: Plan.Model };\n Approving: { readonly plan: Plan.Model };\n Applying: { readonly plan: Plan.Model; readonly approval: Approval.Model };\n Applied: { readonly plan: Plan.Model | null; readonly receipt: Receipt.Model };\n Rejecting: { readonly plan: Plan.Model };\n Rejected: { readonly plan: Plan.Model; readonly attempt: Transport.Attempt };\n Failure: { readonly error: DomainKit.Error };\n}>;\nexport const State = Data.taggedEnum<State>();\n\n/** The verbs `Provision` and `Cleanup` share on the wire. */\nexport interface Group {\n readonly approve: (input: {\n readonly planId: Plan.PlanId;\n readonly operationIds?: ReadonlyArray<Plan.OperationId>;\n }) => Effect.Effect<Approval.Model, DomainKit.Error>;\n readonly reject: (input: {\n readonly planId: Plan.PlanId;\n readonly reason?: string;\n }) => Effect.Effect<Transport.Attempt, DomainKit.Error>;\n readonly apply: (\n approvalId: Approval.ApprovalId,\n ) => Effect.Effect<Receipt.Model, DomainKit.Error>;\n}\n\nexport interface Controller {\n readonly state: State;\n /** Build a plan. The plan itself rides on the state, from `Planned` through `Applied`. */\n readonly plan: () => void;\n /** Authorize the digest and apply it. Pass `operationIds` to approve part of the plan. */\n readonly approve: (operationIds?: ReadonlyArray<Plan.OperationId>) => void;\n /** Decline the plan. Terminal: approving it afterwards fails `Stale`. */\n readonly reject: (reason?: string) => void;\n /** Apply the approval this controller already holds. */\n readonly apply: () => void;\n /** Re-plan when the zone moved under the plan, otherwise re-run the step that failed. */\n readonly retry: () => void;\n readonly reset: () => void;\n}\n\nexport interface Options {\n readonly domain: string;\n /**\n * Identifies the inputs this attempt is for. When it changes the attempt is abandoned, because a\n * plan, approval, and receipt only mean anything for the inputs that produced them.\n */\n readonly key: string;\n readonly group: Group | undefined;\n /** The plan call, or `null` when this flow has nothing to plan yet. */\n readonly plan: () => Effect.Effect<Plan.Model, DomainKit.Error> | null;\n readonly done: (receipt: Receipt.Model) => Event;\n readonly onDone: ((receipt: Receipt.Model) => void) | undefined;\n}\n\n/** Reasons that mean the plan itself is gone: retrying the same step would fail the same way. */\nconst needsNewPlan = (error: DomainKit.Error): boolean =>\n error.reason._tag === \"Stale\" ||\n error.reason._tag === \"Expired\" ||\n error.reason._tag === \"Conflict\";\n\nexport function useAttempt(options: Options): Controller {\n const { domain, done, group, key, onDone } = options;\n const { emit } = useDomainKit();\n const readOnly = useReadOnly();\n const runner = useRunner();\n const [state, setState] = useState<State>(State.Idle());\n // The key travels with what it produced, so a command raised before the reset commits still\n // refuses to run: a plan built for one domain must never be approved for another.\n const held = useRef<{\n key: string;\n plan: Plan.Model | null;\n approval: Approval.Model | null;\n }>({ approval: null, key, plan: null });\n const lastCommand = useRef<{ key: string; run: () => void } | null>(null);\n const build = useRef(options.plan);\n useEffect(() => {\n build.current = options.plan;\n });\n\n // Abandoning while rendering, not one effect later, is what makes the guards below sound: a\n // reply that lands in between finds the new key already recorded and drops itself.\n const [current, setCurrent] = useState(key);\n if (current !== key) {\n setCurrent(key);\n runner.cancel();\n held.current = { approval: null, key, plan: null };\n lastCommand.current = null;\n setState(State.Idle());\n }\n\n const onFailure = useCallback(\n (error: DomainKit.Error) => {\n setState(State.Failure({ error }));\n emit(Event.Failed({ domain, error }));\n },\n [domain, emit],\n );\n\n const applyWith = useCallback(\n (plan: Plan.Model, approval: Approval.Model) => {\n if (group === undefined || held.current.key !== key) return;\n const command = () => {\n setState(State.Applying({ approval, plan }));\n runner.run(group.apply(approval.id), {\n onFailure,\n onSuccess: (receipt) => {\n setState(State.Applied({ plan, receipt }));\n emit(done(receipt));\n onDone?.(receipt);\n },\n });\n };\n lastCommand.current = { key, run: command };\n command();\n },\n [done, emit, group, key, onDone, onFailure, runner],\n );\n\n const buildPlan = useCallback(() => {\n const effect = build.current();\n if (effect === null) return;\n const command = () => {\n setState(State.Planning());\n runner.run(effect, {\n onFailure,\n onSuccess: (plan) => {\n if (held.current.key !== key) return;\n held.current = { approval: null, key, plan };\n setState(State.Planned({ plan }));\n },\n });\n };\n lastCommand.current = { key, run: command };\n command();\n }, [key, onFailure, runner]);\n\n const approve = useCallback(\n (operationIds?: ReadonlyArray<Plan.OperationId>) => {\n const plan = held.current.plan;\n if (group === undefined || plan === null || held.current.key !== key) return;\n const command = () => {\n setState(State.Approving({ plan }));\n runner.run(\n group.approve({\n planId: plan.id,\n ...(operationIds === undefined ? {} : { operationIds }),\n }),\n {\n onFailure,\n onSuccess: (approval) => {\n if (held.current.key !== key) return;\n held.current = { approval, key, plan };\n applyWith(plan, approval);\n },\n },\n );\n };\n lastCommand.current = { key, run: command };\n command();\n },\n [applyWith, group, key, onFailure, runner],\n );\n\n const reject = useCallback(\n (reason?: string) => {\n const plan = held.current.plan;\n if (group === undefined || plan === null || held.current.key !== key) return;\n const command = () => {\n setState(State.Rejecting({ plan }));\n runner.run(group.reject({ planId: plan.id, ...(reason === undefined ? {} : { reason }) }), {\n onFailure,\n onSuccess: (attempt) => {\n setState(State.Rejected({ attempt, plan }));\n emit(Event.Declined({ attempt, domain }));\n },\n });\n };\n lastCommand.current = { key, run: command };\n command();\n },\n [domain, emit, group, key, onFailure, runner],\n );\n\n const apply = useCallback(() => {\n const { approval, plan } = held.current;\n if (approval === null || plan === null) return;\n applyWith(plan, approval);\n }, [applyWith]);\n\n const retry = useCallback(() => {\n // Every step of an attempt is a write, so read-only has nothing to retry.\n if (readOnly) return;\n if (state._tag === \"Failure\" && needsNewPlan(state.error)) {\n held.current = { approval: null, key, plan: null };\n buildPlan();\n return;\n }\n const command = lastCommand.current;\n if (command === null || command.key !== key) buildPlan();\n else command.run();\n }, [buildPlan, key, readOnly, state]);\n\n const reset = useCallback(() => {\n runner.cancel();\n held.current = { approval: null, key, plan: null };\n lastCommand.current = null;\n setState(State.Idle());\n }, [key, runner]);\n\n return { apply, approve, plan: buildPlan, reject, reset, retry, state };\n}\n","/**\n * What a flow says when a step ends badly: media, title, description, and the action that follows.\n * Every flow's `Outcome` binds its controller to these parts, so a failure reads the same way in\n * the connect dialog, the review dialog, and the verification popover.\n *\n * <Connect.Outcome controller={connection} /> the default composition\n *\n * <Connect.Outcome controller={connection}> a composition of your own\n * <Outcome.Header>\n * <Outcome.Media><MyIcon /></Outcome.Media>\n * <Outcome.Title />\n * <Outcome.Description />\n * </Outcome.Header>\n * <Outcome.Content />\n * </Connect.Outcome>\n */\nimport { createContext, useContext, type ReactElement, type ReactNode } from \"react\";\n\nimport type { PartProps } from \"./composition.tsx\";\nimport { usePart } from \"./composition.tsx\";\nimport { useDomainKit } from \"./domain-kit.tsx\";\nimport { useIcons } from \"./icons.tsx\";\n\n/** How the outcome reads: a problem, a caution, or a step that went through. */\nexport type Tone = \"danger\" | \"success\" | \"warning\";\n\n/** `card` is the panel a flow shows on its own; `inline` sits under a field or in a busy row. */\nexport type Layout = \"card\" | \"inline\";\n\n/** What a flow resolved for the outcome its parts render. */\nexport interface Value {\n readonly tone: Tone;\n readonly layout: Layout;\n readonly title: string;\n readonly description: string;\n /** The retry the flow allows, or `null` when it allows none. */\n readonly retry: (() => void) | null;\n /** The part name the flow's retry carries, so a host's selectors keep working. */\n readonly retryPart: string;\n}\n\nconst fallback: Value = {\n description: \"\",\n layout: \"card\",\n retry: null,\n retryPart: \"flow-retry\",\n title: \"\",\n tone: \"danger\",\n};\n\nconst Context = createContext<Value | null>(null);\n\n/** What the surrounding flow resolved, for a part of your own inside `X.Outcome`. */\nexport function useOutcome(): Value {\n return useContext(Context) ?? fallback;\n}\n\n/** Binds a resolved outcome to the parts below it. Flows render this; hosts rarely do. */\nexport function Provider({\n children,\n value,\n}: {\n readonly children: ReactNode;\n readonly value: Value;\n}): ReactElement {\n return <Context.Provider value={value}>{children}</Context.Provider>;\n}\n\nexport interface State extends Record<string, unknown> {\n readonly tone: Tone;\n readonly layout: Layout;\n}\n\nexport interface RootProps extends PartProps<\"div\", State> {\n readonly tone?: Tone;\n readonly layout?: Layout;\n}\n\n/**\n * The outcome itself. It announces, so a customer reading with assistive tech hears it. A `tone`\n * or `layout` of its own reaches every part below it, so the glyph and the words agree with the\n * root's own attributes.\n */\nexport function Root({ layout, tone, ...props }: RootProps): ReactElement {\n const value = useOutcome();\n const resolved: Value = { ...value, layout: layout ?? value.layout, tone: tone ?? value.tone };\n const element = usePart(\n \"div\",\n props,\n { layout: resolved.layout, tone: resolved.tone },\n {\n \"data-domainkit-part\": \"outcome\",\n \"data-layout\": resolved.layout,\n \"data-tone\": resolved.tone,\n role: \"alert\",\n },\n );\n return <Provider value={resolved}>{element}</Provider>;\n}\n\nexport interface HeaderProps extends PartProps<\"div\", State> {}\n\n/** Media, title, and description together, so the action below them can move on its own. */\nexport function Header(props: HeaderProps): ReactElement {\n const { layout, tone } = useOutcome();\n return usePart(\"div\", props, { layout, tone }, { \"data-domainkit-part\": \"outcome-header\" });\n}\n\nexport interface MediaProps extends PartProps<\"div\", State> {\n /** `icon` frames the glyph the way shadcn's `EmptyMedia` does; `default` draws it bare. */\n readonly variant?: \"default\" | \"icon\";\n}\n\n/** The glyph for the tone. Children replace it; `icons` on `DomainKit.Root` replaces the set. */\nexport function Media({ variant = \"icon\", ...props }: MediaProps): ReactElement {\n const { layout, tone } = useOutcome();\n const icons = useIcons();\n const glyph =\n tone === \"success\" ? icons.success : tone === \"warning\" ? icons.warning : icons.failure;\n return usePart(\n \"div\",\n props,\n { layout, tone },\n {\n \"aria-hidden\": \"true\",\n children: glyph,\n \"data-domainkit-part\": \"outcome-media\",\n \"data-variant\": variant,\n },\n );\n}\n\nexport interface TitleProps extends PartProps<\"div\", State> {}\n\n/** The heading from the catalog. Children win, for a host that words it itself. */\nexport function Title(props: TitleProps): ReactElement {\n const { layout, title, tone } = useOutcome();\n return usePart(\n \"div\",\n props,\n { layout, tone },\n { children: title, \"data-domainkit-part\": \"outcome-title\" },\n );\n}\n\nexport interface DescriptionProps extends PartProps<\"p\", State> {}\n\n/** What to do about it, from the catalog. An outcome whose title says everything renders none. */\nexport function Description(props: DescriptionProps): ReactElement | null {\n const { description, layout, tone } = useOutcome();\n const element = usePart(\n \"p\",\n props,\n { layout, tone },\n { children: description, \"data-domainkit-part\": \"outcome-description\" },\n );\n return description === \"\" && props.children === undefined ? null : element;\n}\n\nexport interface ContentProps extends PartProps<\"div\", State> {}\n\n/**\n * The actions under the header. Without children it is the flow's retry, and a flow that allows\n * none renders nothing: read-only hides every control that would start a write again.\n */\nexport function Content(props: ContentProps): ReactElement | null {\n const { messages } = useDomainKit();\n const { layout, retry, retryPart, tone } = useOutcome();\n const element = usePart(\n \"div\",\n props,\n { layout, tone },\n {\n children:\n retry === null ? null : (\n <button data-domainkit-part={retryPart} onClick={retry} type=\"button\">\n {messages.retry}\n </button>\n ),\n \"data-domainkit-part\": \"outcome-content\",\n },\n );\n return retry === null && props.children === undefined ? null : element;\n}\n\n/** Media, title, and description in a header, then the action. What `X.Outcome` renders alone. */\nexport function Composition(): ReactElement {\n return (\n <>\n <Header>\n <Media />\n <Title />\n <Description />\n </Header>\n <Content />\n </>\n );\n}\n","import { DnsRecord } from \"domainkit\";\nimport type { Transport } from \"domainkit/client\";\nimport { useEffect, useRef, useState, type ReactElement } from \"react\";\n\nimport type { PartProps } from \"./composition.tsx\";\nimport { leafPart, usePart } from \"./composition.tsx\";\nimport { useDomainKit } from \"./domain-kit.tsx\";\nimport { useIcons } from \"./icons.tsx\";\n\nexport type Readiness = Transport.Readiness;\nexport type RequirementStatus = Readiness[\"requirements\"][number][\"status\"];\n\n// ---------------------------------------------------------------------------------------------\n// Zone file\n// ---------------------------------------------------------------------------------------------\n\nconst absolute = (value: string): string => (value.endsWith(\".\") ? value : `${value}.`);\n\nconst textEncoder = new TextEncoder();\n\nconst escapeTxtCharacter = (character: string): string => {\n if (character === '\"' || character === \"\\\\\") return `\\\\${character}`;\n const codePoint = character.codePointAt(0);\n if (codePoint !== undefined && (codePoint < 32 || codePoint === 127)) {\n return `\\\\${codePoint.toString().padStart(3, \"0\")}`;\n }\n return character;\n};\n\n/** TXT strings are capped at 255 bytes each, so long values are split and quoted per chunk. */\nconst txtValue = (value: string): string => {\n const chunks: Array<string> = [];\n let chunk = \"\";\n let byteLength = 0;\n for (const character of value) {\n const characterByteLength = textEncoder.encode(character).byteLength;\n if (byteLength + characterByteLength > 255) {\n chunks.push(chunk);\n chunk = \"\";\n byteLength = 0;\n }\n chunk += escapeTxtCharacter(character);\n byteLength += characterByteLength;\n }\n chunks.push(chunk);\n return chunks.map((part) => `\"${part}\"`).join(\" \");\n};\n\n/** The RR type as a zone file spells it. The tag and the type name are the same string. */\nconst rrType = (record: DnsRecord.Model): string => record._tag;\n\nconst zoneData = (record: DnsRecord.Model): string => {\n switch (record._tag) {\n case \"A\":\n case \"AAAA\":\n return record.address;\n case \"CNAME\":\n return absolute(record.target);\n case \"NS\":\n return absolute(record.nameserver);\n case \"TXT\":\n return txtValue(record.value);\n case \"MX\":\n return `${record.priority} ${absolute(record.exchange)}`;\n case \"CAA\":\n return `${record.flags} ${record.tag} \"${record.value}\"`;\n case \"SRV\":\n return `${record.priority} ${record.weight} ${record.port} ${absolute(record.target)}`;\n }\n};\n\nexport const toZoneFile = (records: ReadonlyArray<DnsRecord.Model>): string =>\n `${records\n .map(\n (record) =>\n `${absolute(record.name)}${record.ttl === null ? \"\" : ` ${record.ttl}`} IN ${rrType(record)} ${zoneData(record)}`,\n )\n .join(\"\\n\")}\\n`;\n\nconst downloadText = (filename: string, contents: string): void => {\n if (typeof document === \"undefined\") return;\n const blob = new Blob([contents], { type: \"text/plain;charset=utf-8\" });\n const url = URL.createObjectURL(blob);\n const anchor = document.createElement(\"a\");\n anchor.download = filename;\n anchor.href = url;\n document.body.append(anchor);\n anchor.click();\n anchor.remove();\n URL.revokeObjectURL(url);\n};\n\nexport const downloadZoneFile = (domain: string, records: ReadonlyArray<DnsRecord.Model>): void =>\n downloadText(`${domain}.txt`, toZoneFile(records));\n\n// ---------------------------------------------------------------------------------------------\n// Copy\n// ---------------------------------------------------------------------------------------------\n\nexport const copyText = (value: string): Promise<boolean> => {\n if (typeof navigator === \"undefined\" || navigator.clipboard === undefined) {\n return Promise.resolve(false);\n }\n return navigator.clipboard.writeText(value).then(\n () => true,\n () => false,\n );\n};\n\nexport interface CopyController {\n readonly copied: boolean;\n readonly copy: () => void;\n}\n\nexport function useCopy(value: string, resetAfter = 2000): CopyController {\n const [copied, setCopied] = useState(false);\n const reset = useRef<ReturnType<typeof setTimeout>>(undefined);\n useEffect(() => () => clearTimeout(reset.current), []);\n return {\n copied,\n copy: () => {\n void copyText(value).then((ok) => {\n if (!ok) return;\n setCopied(true);\n clearTimeout(reset.current);\n reset.current = setTimeout(() => setCopied(false), resetAfter);\n });\n },\n };\n}\n\nexport interface CopyValueProps extends PartProps<\"span\", { readonly copied: boolean }> {\n readonly value: string;\n}\n\nexport function CopyValue({ value, ...props }: CopyValueProps) {\n const { messages } = useDomainKit();\n const icons = useIcons();\n const { copied, copy } = useCopy(value);\n return usePart(\n \"span\",\n props,\n { copied },\n {\n children: (\n <>\n <code>{value}</code>\n <button\n aria-label={`${copied ? messages.copied : messages.copy} ${value}`}\n data-domainkit-part=\"copy-action\"\n onClick={copy}\n type=\"button\"\n >\n <span\n aria-hidden=\"true\"\n data-domainkit-part=\"copy-glyph\"\n data-icon=\"\"\n data-state=\"idle\"\n >\n {icons.copy}\n </span>\n <span\n aria-hidden=\"true\"\n data-domainkit-part=\"copy-glyph\"\n data-icon=\"\"\n data-state=\"done\"\n >\n {icons.copied}\n </span>\n </button>\n </>\n ),\n \"data-copied\": copied ? \"\" : undefined,\n \"data-domainkit-part\": \"copy-value\",\n },\n );\n}\n\nexport interface ZoneFileProps extends PartProps<\"div\", { readonly count: number }> {\n readonly domain: string;\n readonly records: ReadonlyArray<DnsRecord.Model>;\n}\n\nexport function ZoneFile({ domain, records, ...props }: ZoneFileProps) {\n const { messages } = useDomainKit();\n const icons = useIcons();\n const zone = toZoneFile(records);\n const { copied, copy } = useCopy(zone);\n return usePart(\n \"div\",\n props,\n { count: records.length },\n {\n children: (\n <>\n <button\n aria-label={copied ? messages.copied : messages.copyZone}\n data-domainkit-part=\"zone-copy\"\n onClick={copy}\n type=\"button\"\n >\n <span aria-hidden=\"true\" data-icon=\"inline-start\">\n {copied ? icons.copied : icons.copy}\n </span>\n {copied ? messages.copied : messages.copyZone}\n </button>\n <button\n aria-label={messages.download}\n data-domainkit-part=\"zone-download\"\n onClick={() => downloadZoneFile(domain, records)}\n type=\"button\"\n >\n <span aria-hidden=\"true\" data-icon=\"inline-start\">\n {icons.download}\n </span>\n {messages.download}\n </button>\n </>\n ),\n \"data-domainkit-part\": \"zone-file\",\n },\n );\n}\n\n// ---------------------------------------------------------------------------------------------\n// Status\n// ---------------------------------------------------------------------------------------------\n\n/** The readiness this record reached, or `null` when nothing has observed it. */\nexport const statusOf = (\n record: DnsRecord.Model,\n readiness: Readiness | null | undefined,\n): RequirementStatus | null =>\n readiness?.requirements.find((requirement) => DnsRecord.equals(requirement.record, record))\n ?.status ?? null;\n\nexport interface StatusProps extends PartProps<\"span\", { readonly status: RequirementStatus }> {\n readonly status: RequirementStatus;\n}\n\nexport function Status({ status, ...props }: StatusProps) {\n const { messages } = useDomainKit();\n const icons = useIcons();\n const glyph =\n status === \"satisfied\" ? icons.success : status === \"unknown\" ? icons.pending : icons.failure;\n return usePart(\n \"span\",\n props,\n { status },\n {\n children: (\n <>\n <span aria-hidden=\"true\" data-icon=\"inline-start\">\n {glyph}\n </span>\n {messages.requirementStatus(status)}\n </>\n ),\n \"data-domainkit-part\": \"record-status\",\n \"data-status\": status,\n },\n );\n}\n\n// ---------------------------------------------------------------------------------------------\n// Parts\n// ---------------------------------------------------------------------------------------------\n\nexport const Header = leafPart(\"thead\", \"records-header\");\nexport const Body = leafPart(\"tbody\", \"records-body\");\nexport const Footer = leafPart(\"tfoot\", \"records-footer\");\nexport const Row = leafPart(\"tr\", \"records-row\");\nexport const Head = leafPart(\"th\", \"records-head\");\nexport const Cell = leafPart(\"td\", \"records-cell\");\nexport const Caption = leafPart(\"caption\", \"records-caption\");\nexport const Value = leafPart(\"span\", \"record-value\");\nexport const Purpose = leafPart(\"span\", \"record-purpose\");\nexport const CardHeader = leafPart(\"div\", \"record-card-head\");\nexport const CardTitle = leafPart(\"strong\", \"record-card-title\");\nexport const CardContent = leafPart(\"dl\", \"record-card-content\");\n\nexport interface RootProps extends PartProps<\"table\", { readonly count: number }> {\n readonly count?: number;\n}\n\nexport function Root({ count = 0, ...props }: RootProps) {\n return (\n <div data-domainkit-part=\"records-panel\">\n {usePart(\"table\", props, { count }, { \"data-domainkit-part\": \"records-table\" })}\n </div>\n );\n}\n\n/** A stable React key for a requirement: type, name, and data identify a record. */\nexport const identity = (record: DnsRecord.Model): string =>\n [rrType(record), record.name, DnsRecord.data(record)].join(\":\");\n\n/**\n * A requirement set keyed by everything it carries, for memos that decide whether to re-send it.\n * `identity` is deliberately narrower: it answers \"is this the same record\" for a React key, while\n * a plan and an observation are built from `ttl`, `policy`, and `purpose` as well. `policy` in\n * particular decides whether a name may hold anything else, so readiness turns on it.\n */\nexport const requirementsKey = (records: ReadonlyArray<DnsRecord.Model>): string =>\n JSON.stringify(records);\n\nexport interface CardProps extends PartProps<\"section\", { readonly record: string }> {\n readonly readiness?: Readiness | null;\n readonly record: DnsRecord.Model;\n}\n\nexport function Card({ readiness, record, ...props }: CardProps): ReactElement {\n const { messages } = useDomainKit();\n const status = statusOf(record, readiness);\n return usePart(\n \"section\",\n props,\n { record: identity(record) },\n {\n children: (\n <>\n <CardHeader>\n <CardTitle>{messages.recordType(record)}</CardTitle>\n {status === null ? null : <Status status={status} />}\n </CardHeader>\n <CardContent>\n <div>\n <dt>{messages.headingName}</dt>\n <dd>\n <CopyValue value={record.name} />\n </dd>\n </div>\n <div>\n <dt>{messages.headingValue}</dt>\n <dd>\n <CopyValue value={DnsRecord.data(record)} />\n </dd>\n </div>\n {record.purpose === undefined ? null : (\n <div>\n <dt>{messages.headingPurpose}</dt>\n <dd>\n <Purpose>{record.purpose}</Purpose>\n </dd>\n </div>\n )}\n </CardContent>\n </>\n ),\n \"data-domainkit-part\": \"record-card\",\n },\n );\n}\n\nexport interface TableProps extends PartProps<\"table\", { readonly count: number }> {\n readonly caption?: string;\n readonly readiness?: Readiness | null;\n readonly records: ReadonlyArray<DnsRecord.Model>;\n}\n\n/** The default records presentation: one row per requirement, with readiness when there is any. */\nexport function Table({ caption, readiness, records, ...props }: TableProps): ReactElement {\n const { messages } = useDomainKit();\n const withStatus = readiness !== null && readiness !== undefined;\n return (\n <Root count={records.length} {...props}>\n {caption === undefined ? null : <Caption>{caption}</Caption>}\n <Header>\n <Row>\n <Head scope=\"col\">{messages.headingType}</Head>\n <Head scope=\"col\">{messages.headingName}</Head>\n <Head scope=\"col\">{messages.headingValue}</Head>\n {withStatus ? (\n <Head data-column=\"status\" scope=\"col\">\n {messages.headingStatus}\n </Head>\n ) : null}\n </Row>\n </Header>\n <Body>\n {records.map((record) => {\n const status = statusOf(record, readiness);\n return (\n <Row key={identity(record)}>\n <Cell>{messages.recordType(record)}</Cell>\n <Cell>\n <CopyValue value={record.name} />\n </Cell>\n <Cell>\n <Value>\n <CopyValue value={DnsRecord.data(record)} />\n {record.purpose === undefined ? null : <Purpose>{record.purpose}</Purpose>}\n </Value>\n </Cell>\n {withStatus ? (\n <Cell data-column=\"status\">\n {status === null ? null : <Status status={status} />}\n </Cell>\n ) : null}\n </Row>\n );\n })}\n </Body>\n </Root>\n );\n}\n","import { DnsRecord, type Plan } from \"domainkit\";\nimport type { ReactElement } from \"react\";\n\nimport type { PartProps } from \"./composition.tsx\";\nimport { leafPart, usePart } from \"./composition.tsx\";\nimport { useDomainKit } from \"./domain-kit.tsx\";\nimport { CopyValue } from \"./records.tsx\";\n\nexport const Kind = leafPart(\"span\", \"operation-kind\");\nexport const Type = leafPart(\"strong\", \"operation-type\");\nexport const Record = leafPart(\"span\", \"operation-record\");\nexport const Name = leafPart(\"span\", \"operation-name\");\nexport const Reason = leafPart(\"span\", \"operation-reason\");\n\nexport interface ItemProps extends PartProps<\"li\", { readonly operation: Plan.Operation[\"_tag\"] }> {\n readonly operation: Plan.Operation;\n}\n\nexport function Item({ operation, ...props }: ItemProps): ReactElement {\n const { messages } = useDomainKit();\n return usePart(\n \"li\",\n props,\n { operation: operation._tag },\n {\n children: (\n <>\n <Kind>{messages.operation(operation)}</Kind>{\" \"}\n <Type>{messages.recordType(operation.record)}</Type>{\" \"}\n <Record>\n <Name>{operation.record.name}</Name>\n <CopyValue value={DnsRecord.data(operation.record)} />\n </Record>\n {operation._tag === \"Conflict\" ? (\n <Reason>{messages.conflictReason(operation.reason)}</Reason>\n ) : null}\n </>\n ),\n \"data-domainkit-part\": \"operation-item\",\n \"data-operation\": operation._tag,\n },\n );\n}\n\nexport interface RootProps extends PartProps<\n \"ul\",\n { readonly count: number; readonly kind: Plan.Kind }\n> {\n readonly count?: number;\n readonly kind: Plan.Kind;\n}\n\nexport function Root({ count = 0, kind, ...props }: RootProps): ReactElement {\n return usePart(\n \"ul\",\n props,\n { count, kind },\n {\n \"data-domainkit-part\": kind === \"provisioning\" ? \"plan-operations\" : \"cleanup-operations\",\n \"data-kind\": kind,\n },\n );\n}\n\nexport interface ListProps extends Omit<RootProps, \"children\" | \"count\" | \"kind\"> {\n readonly plan: Plan.Model;\n}\n\n/** Every operation the plan holds, in plan order, so a customer reviews exactly what will run. */\nexport function List({ plan, ...props }: ListProps): ReactElement {\n return (\n <Root count={plan.operations.length} kind={plan.kind} {...props}>\n {plan.operations.map((operation) => (\n <Item key={operation.id} operation={operation} />\n ))}\n </Root>\n );\n}\n","/**\n * The review surface both `Provision` and `Cleanup` render: what the plan will do, the Approve\n * and Decline actions D35 defines, and the outcome. `kind` picks the wording; nothing else about\n * the two flows differs on screen.\n */\nimport { Dialog as BaseDialog } from \"@base-ui/react/dialog\";\nimport type { Plan } from \"domainkit\";\nimport { useEffect, useRef, useState, type ReactElement, type ReactNode } from \"react\";\n\nimport type { Controller } from \"./attempt.ts\";\nimport type { PartProps } from \"./composition.tsx\";\nimport { usePart } from \"./composition.tsx\";\nimport { useDomainKit, useReadOnly } from \"./domain-kit.tsx\";\nimport { outcome as describeOutcome } from \"./messages.ts\";\nimport * as OutcomeUi from \"./outcome.tsx\";\nimport * as Operations from \"./operations.tsx\";\n\nexport interface ReviewState extends Record<string, unknown> {\n readonly status: Controller[\"state\"][\"_tag\"];\n}\n\nexport interface KindProps {\n readonly controller: Controller;\n readonly kind: Plan.Kind;\n}\n\nconst busy = (status: Controller[\"state\"][\"_tag\"]): boolean =>\n status === \"Planning\" ||\n status === \"Approving\" ||\n status === \"Applying\" ||\n status === \"Rejecting\";\n\nexport interface StatusProps extends PartProps<\"p\", ReviewState>, KindProps {}\n\n/** What the flow is doing right now, or what it finished doing. */\nexport function Status({ controller, kind, ...props }: StatusProps): ReactElement {\n const { messages } = useDomainKit();\n const state = controller.state;\n const text = (): string => {\n switch (state._tag) {\n case \"Idle\":\n return \"\";\n case \"Planning\":\n return kind === \"provisioning\" ? messages.planning : messages.planningCleanup;\n // What a plan is for is the dialog's own description; the status line is for progress, and\n // saying it twice under it is how the review read before the operations moved in.\n case \"Planned\":\n return \"\";\n case \"Approving\":\n return messages.approving;\n case \"Applying\":\n return kind === \"provisioning\" ? messages.applying : messages.cleaning;\n case \"Rejecting\":\n return messages.rejecting;\n case \"Rejected\":\n return messages.declinedBy(state.attempt.rejection?.actorId ?? \"\");\n // What an apply landed is an outcome, not a progress line: `Outcome` says it.\n case \"Applied\":\n return \"\";\n case \"Failure\":\n return \"\";\n }\n };\n return usePart(\n \"p\",\n props,\n { status: state._tag },\n {\n children: text(),\n \"data-domainkit-part\": kind === \"provisioning\" ? \"provisioning-status\" : \"cleanup-status\",\n \"data-state\": state._tag,\n role: busy(state._tag) ? \"status\" : undefined,\n },\n );\n}\n\nexport interface OutcomeProps extends OutcomeUi.RootProps, KindProps {}\n\n/**\n * How the attempt ended: a failure, a receipt that only partly landed, or one that landed whole.\n * Media, title, description, and the retry the flow allows. Children replace the composition and\n * keep the binding.\n */\nexport function Outcome({\n children,\n controller,\n kind,\n ...props\n}: OutcomeProps): ReactElement | null {\n const { messages } = useDomainKit();\n const readOnly = useReadOnly();\n const state = controller.state;\n const retryPart = kind === \"provisioning\" ? \"provisioning-retry\" : \"cleanup-retry\";\n if (state._tag !== \"Failure\" && state._tag !== \"Applied\") return null;\n const partial = state._tag === \"Applied\" && state.receipt.status === \"partial\";\n const words =\n state._tag === \"Failure\"\n ? describeOutcome(state.error, messages)\n : partial\n ? {\n description:\n kind === \"provisioning\" ? messages.partiallyApplied : messages.partiallyCleaned,\n title:\n kind === \"provisioning\"\n ? messages.partiallyAppliedTitle\n : messages.partiallyCleanedTitle,\n }\n : {\n description: \"\",\n title:\n kind === \"provisioning\"\n ? messages.applied(state.receipt)\n : messages.cleaned(state.receipt),\n };\n return (\n <OutcomeUi.Provider\n value={{\n description: words.description ?? \"\",\n layout: props.layout ?? \"card\",\n retry: readOnly || state._tag !== \"Failure\" ? null : controller.retry,\n retryPart,\n title: words.title,\n tone: state._tag === \"Failure\" ? \"danger\" : partial ? \"warning\" : \"success\",\n }}\n >\n <OutcomeUi.Root {...props}>{children ?? <OutcomeUi.Composition />}</OutcomeUi.Root>\n </OutcomeUi.Provider>\n );\n}\n\nexport interface ActionsProps extends PartProps<\"div\", ReviewState>, KindProps {}\n\n/** What a plan would actually write: an operation blocked by a conflict is not one of them. */\nconst addable = (plan: Plan.Model | null): ReadonlyArray<Plan.Operation> =>\n plan === null ? [] : plan.operations.filter((operation) => operation._tag !== \"Conflict\");\n\n/**\n * The primary action, and Decline. The primary authorizes the digest and applies it in one step,\n * so it says what it will do; where a conflict blocks part of a plan it approves the rest by id,\n * and where every operation is blocked it says what to fix instead. Neither renders until there is\n * a plan to act on.\n */\nexport function Actions({ controller, kind, ...props }: ActionsProps): ReactElement | null {\n const { messages } = useDomainKit();\n const readOnly = useReadOnly();\n const state = controller.state;\n const plan = state._tag === \"Planned\" ? state.plan : null;\n const running = busy(state._tag);\n const writes = addable(plan);\n const blocked = plan !== null && writes.length === 0;\n const element = usePart(\n \"div\",\n props,\n { status: state._tag },\n {\n children: (\n <>\n <button\n data-domainkit-part={kind === \"provisioning\" ? \"plan-apply\" : \"cleanup-apply\"}\n disabled={running || plan === null || writes.length === 0}\n onClick={() =>\n // Naming the ids is what leaves a conflict out; approving the whole plan would not.\n controller.approve(\n writes.length === plan?.operations.length\n ? undefined\n : writes.map((operation) => operation.id),\n )\n }\n type=\"button\"\n >\n {kind === \"provisioning\" ? messages.addRecords(writes.length) : messages.approve}\n </button>\n {blocked ? (\n <p data-domainkit-part=\"plan-blocked\">{messages.everyRecordConflicts}</p>\n ) : null}\n <button\n data-domainkit-part=\"plan-decline\"\n disabled={running || plan === null}\n onClick={() => controller.reject()}\n type=\"button\"\n >\n {messages.decline}\n </button>\n </>\n ),\n \"data-domainkit-part\": \"review-actions\",\n },\n );\n if (readOnly) return null;\n // Nothing to act on yet, or nothing left to act on: while a command runs the body carries the\n // progress, and an action that names a count it does not have yet would be lying about it.\n return plan === null ? null : element;\n}\n\nexport interface BodyProps extends KindProps {}\n\n/** The operations under review, or the reason there is nothing to review. */\nexport function Body({ controller, kind }: BodyProps): ReactElement {\n const { messages } = useDomainKit();\n const state = controller.state;\n const plan =\n state._tag === \"Planned\" ||\n state._tag === \"Approving\" ||\n state._tag === \"Applying\" ||\n state._tag === \"Rejecting\" ||\n state._tag === \"Rejected\"\n ? state.plan\n : state._tag === \"Applied\"\n ? state.plan\n : null;\n return (\n <div data-domainkit-part=\"dialog-body\">\n <Status controller={controller} kind={kind} />\n {plan === null ? null : plan.operations.length === 0 ? (\n <p data-domainkit-part=\"plan-empty\">{messages.noChanges}</p>\n ) : (\n <Operations.List plan={plan} />\n )}\n {state._tag === \"Rejected\" && state.attempt.rejection?.reason != null ? (\n <p data-domainkit-part=\"plan-decline-reason\">\n {messages.declineReason(state.attempt.rejection.reason)}\n </p>\n ) : null}\n <Outcome controller={controller} kind={kind} />\n </div>\n );\n}\n\nexport interface DialogProps extends KindProps {\n readonly children?: ReactNode;\n readonly onOpenChange?: (open: boolean) => void;\n readonly open?: boolean;\n /** Replace the dialog surface entirely: a drawer, an inline panel, a host modal. */\n readonly render?: (props: { readonly open: boolean; readonly children: ReactNode }) => ReactNode;\n readonly trigger?: ReactNode;\n}\n\n/** The review dialog. `render` swaps the surface; the contents stay the flow's. */\nexport function Dialog({\n children,\n controller,\n kind,\n onOpenChange,\n open,\n render,\n trigger,\n}: DialogProps): ReactElement {\n const { colorScheme, messages, portalContainer, themeStyle } = useDomainKit();\n const readOnly = useReadOnly();\n const [uncontrolled, setUncontrolled] = useState(false);\n const isOpen = open ?? uncontrolled;\n const close = useRef<(next: boolean) => void>(() => {});\n close.current = (next: boolean) => {\n if (open === undefined) setUncontrolled(next);\n onOpenChange?.(next);\n };\n const setOpen = (next: boolean) => close.current(next);\n const state = controller.state;\n // An apply that landed whole is done being reviewed: the receipt reads on the page. A partial\n // one and a failure keep the surface, because there is still something to answer there.\n const landed = state._tag === \"Applied\" && state.receipt.status === \"complete\";\n useEffect(() => {\n if (landed) close.current(false);\n }, [landed]);\n const running = busy(controller.state._tag);\n const body = children ?? <Body controller={controller} kind={kind} />;\n const title = kind === \"provisioning\" ? messages.planTitle : messages.cleanupTitle;\n const label = trigger ?? (kind === \"provisioning\" ? messages.reviewChanges : messages.cleanUp);\n // Reviewing exists to authorize a write, so the whole surface goes rather than a dead trigger.\n if (readOnly) return <></>;\n if (render !== undefined) {\n return (\n <>\n <button\n data-domainkit-part={kind === \"provisioning\" ? \"plan-trigger\" : \"cleanup-trigger\"}\n onClick={() => {\n setOpen(true);\n controller.plan();\n }}\n type=\"button\"\n >\n {label}\n </button>\n {render({ children: body, open: isOpen })}\n </>\n );\n }\n return (\n <BaseDialog.Root\n onOpenChange={(next, details) => {\n if (!next && running) {\n details.cancel();\n return;\n }\n setOpen(next);\n }}\n open={isOpen}\n >\n <BaseDialog.Trigger\n data-domainkit-part={kind === \"provisioning\" ? \"plan-trigger\" : \"cleanup-trigger\"}\n onClick={controller.plan}\n >\n {label}\n </BaseDialog.Trigger>\n <BaseDialog.Portal container={portalContainer}>\n <BaseDialog.Backdrop\n data-color-scheme={colorScheme}\n data-domainkit-part=\"dialog-backdrop\"\n data-domainkit-root=\"\"\n style={themeStyle}\n />\n <BaseDialog.Popup\n data-color-scheme={colorScheme}\n data-domainkit-part={kind === \"provisioning\" ? \"plan-dialog\" : \"cleanup-dialog\"}\n data-domainkit-root=\"\"\n style={themeStyle}\n >\n <div data-domainkit-part=\"dialog-header\">\n <div data-domainkit-part=\"dialog-heading\">\n <BaseDialog.Title data-domainkit-part=\"dialog-title\">{title}</BaseDialog.Title>\n <BaseDialog.Description data-domainkit-part=\"dialog-description\">\n {kind === \"provisioning\" ? messages.planConsent : messages.cleanupConsent}\n </BaseDialog.Description>\n </div>\n {running ? null : (\n <BaseDialog.Close aria-label={messages.close} data-domainkit-part=\"dialog-close\">\n ×\n </BaseDialog.Close>\n )}\n </div>\n {body}\n <div data-domainkit-part=\"dialog-footer\">\n <Actions controller={controller} kind={kind} />\n {/*\n * The close in the header and a press outside already set a plan aside, so the footer\n * of a provisioning plan carries only the two decisions about the plan itself.\n */}\n {running || kind === \"provisioning\" ? null : (\n <BaseDialog.Close data-domainkit-part=\"dialog-cancel\">\n {messages.cancel}\n </BaseDialog.Close>\n )}\n </div>\n </BaseDialog.Popup>\n </BaseDialog.Portal>\n </BaseDialog.Root>\n );\n}\n","import { DomainKit, Reason, Receipt } from \"domainkit\";\nimport * as Effect from \"effect/Effect\";\nimport { useCallback, useState, type ReactElement, type ReactNode } from \"react\";\n\nimport { State, useAttempt, type Controller } from \"./attempt.ts\";\nimport type { PartProps } from \"./composition.tsx\";\nimport { usePart } from \"./composition.tsx\";\nimport { useDomainKit } from \"./domain-kit.tsx\";\nimport { Event } from \"./events.ts\";\nimport * as Review from \"./review.tsx\";\n\nexport { State };\nexport type { Controller };\n\nexport interface Options {\n readonly domain: string;\n /** Which apply to undo. Without it, the domain's latest provisioning receipt. */\n readonly receiptId?: Receipt.ReceiptId;\n readonly onCleaned?: (receipt: Receipt.Model) => void;\n}\n\n/**\n * Cleanup is bound to a receipt: it removes only what an apply proved DomainKit created. When the\n * host does not name one, the controller reads the domain's latest from the snapshot.\n */\nexport function useController({ domain, onCleaned, receiptId }: Options): Controller {\n const { transport } = useDomainKit();\n const group = transport.cleanup;\n const connection = transport.connection;\n return useAttempt({\n domain,\n key: [domain, receiptId ?? \"\"].join(\"|\"),\n done: (receipt) => Event.Cleaned({ domain, receipt }),\n group,\n onDone: onCleaned,\n plan: useCallback(() => {\n if (group === undefined) return null;\n if (receiptId !== undefined) return group.plan(receiptId);\n if (connection === undefined) return null;\n return Effect.flatMap(connection.inspect(domain), (snapshot) =>\n snapshot.lastReceiptId === null\n ? Effect.fail(\n new DomainKit.Error({\n reason: new Reason.NotFound({ entity: \"receipt\", id: snapshot.domain }),\n }),\n )\n : group.plan(Receipt.ReceiptId.make(snapshot.lastReceiptId)),\n );\n }, [connection, domain, group, receiptId]),\n });\n}\n\nexport interface RootState extends Record<string, unknown> {\n readonly status: State[\"_tag\"];\n}\n\nexport interface RootProps extends PartProps<\"div\", RootState> {\n readonly controller: Controller;\n}\n\nexport function Root({ controller, ...props }: RootProps): ReactElement {\n return usePart(\n \"div\",\n props,\n { status: controller.state._tag },\n { \"data-domainkit-part\": \"cleanup-flow\", \"data-state\": controller.state._tag },\n );\n}\n\nexport interface DialogProps extends Omit<Review.DialogProps, \"kind\"> {}\n\nexport function Dialog(props: DialogProps): ReactElement {\n return <Review.Dialog {...props} kind=\"cleanup\" />;\n}\n\nexport interface ActionsProps extends Omit<Review.ActionsProps, \"kind\"> {}\n\nexport function Actions(props: ActionsProps): ReactElement | null {\n return <Review.Actions {...props} kind=\"cleanup\" />;\n}\n\nexport interface OutcomeProps extends Omit<Review.OutcomeProps, \"kind\"> {}\n\nexport function Outcome(props: OutcomeProps): ReactElement | null {\n return <Review.Outcome {...props} kind=\"cleanup\" />;\n}\n\nexport interface StatusProps extends Omit<Review.StatusProps, \"kind\"> {}\n\nexport function Status(props: StatusProps): ReactElement {\n return <Review.Status {...props} kind=\"cleanup\" />;\n}\n\nexport interface FlowProps extends Omit<RootProps, \"controller\"> {\n readonly domain: string;\n readonly onCleaned?: (receipt: Receipt.Model) => void;\n readonly receiptId?: Receipt.ReceiptId;\n readonly trigger?: ReactNode;\n}\n\n/** Cleanup on its own: a trigger that plans the removal, then the same review dialog. */\nexport function Flow({ domain, onCleaned, receiptId, trigger, ...props }: FlowProps) {\n const controller = useController({\n domain,\n ...(onCleaned === undefined ? {} : { onCleaned }),\n ...(receiptId === undefined ? {} : { receiptId }),\n });\n // The dialog carries its own outcome, so the one on the page is for after it closes.\n const [open, setOpen] = useState(false);\n return (\n <Root controller={controller} {...props}>\n <Dialog\n controller={controller}\n onOpenChange={setOpen}\n open={open}\n {...(trigger === undefined ? {} : { trigger })}\n />\n {open ? null : <Outcome controller={controller} />}\n </Root>\n );\n}\n","import type { Transport } from \"domainkit/client\";\nimport type { ReactNode } from \"react\";\n\nimport type { PartProps } from \"./composition.tsx\";\nimport { usePart } from \"./composition.tsx\";\nimport { useDomainKit } from \"./domain-kit.tsx\";\n\n/** A provider as the snapshot describes it: an id, a display name, and its auth methods. */\nexport type Descriptor = Transport.Snapshot[\"providers\"][number];\n\n/** Host-supplied artwork per provider id. A function receives the descriptor it renders for. */\nexport type Marks = Readonly<Record<string, ReactNode | ((provider: Descriptor) => ReactNode)>>;\n\nexport interface MarkState extends Record<string, unknown> {\n readonly providerId: string;\n}\n\nexport interface MarkProps extends PartProps<\"span\", MarkState> {\n readonly provider: Descriptor;\n}\n\nconst key = (providerId: string): string =>\n providerId\n .trim()\n .toLowerCase()\n .replaceAll(/[^a-z0-9]+/g, \"\");\n\n/** No network call: the fallback is the provider's own initial, drawn with the theme's tokens. */\nconst monogram = (provider: Descriptor): string =>\n provider.name.trim().charAt(0).toUpperCase() || \"?\";\n\n/**\n * A provider's artwork. `DomainKit.Root`'s `marks` decides what a provider looks like; without an\n * entry the mark is the provider's initial. Nothing is fetched at render time.\n */\nexport function Mark({ provider, ...props }: MarkProps) {\n const { marks } = useDomainKit();\n const replacement = marks[provider.id];\n const content =\n typeof replacement === \"function\" ? replacement(provider) : (replacement ?? monogram(provider));\n return usePart(\n \"span\",\n props,\n { providerId: provider.id },\n {\n \"aria-label\": provider.name,\n children: content,\n \"data-domainkit-part\": \"provider-mark\",\n \"data-domainkit-provider\": key(provider.id),\n role: \"img\",\n },\n );\n}\n","import { Collapsible as BaseCollapsible } from \"@base-ui/react/collapsible\";\nimport { Dialog as BaseDialog } from \"@base-ui/react/dialog\";\nimport { Switch as BaseSwitch } from \"@base-ui/react/switch\";\nimport { Menu as BaseMenu } from \"@base-ui/react/menu\";\nimport { Receipt, type DomainKit, type Plan, type Storage } from \"domainkit\";\nimport { Transport } from \"domainkit/client\";\nimport * as Data from \"effect/Data\";\nimport * as Effect from \"effect/Effect\";\nimport {\n useCallback,\n useEffect,\n useId,\n useRef,\n useState,\n type ReactElement,\n type ReactNode,\n} from \"react\";\n\nimport * as Cleanup from \"./cleanup.tsx\";\nimport type { PartProps } from \"./composition.tsx\";\nimport { usePart } from \"./composition.tsx\";\nimport { useDomainKit, useReadOnly } from \"./domain-kit.tsx\";\nimport { Event } from \"./events.ts\";\nimport { useIcons } from \"./icons.tsx\";\nimport { outcome as describeOutcome } from \"./messages.ts\";\nimport * as OutcomeUi from \"./outcome.tsx\";\nimport * as Operations from \"./operations.tsx\";\nimport * as Provider from \"./provider.tsx\";\nimport { useRunner } from \"./task.ts\";\n\nexport type Snapshot = Transport.Snapshot;\nexport type Discovery = Transport.Discovery;\nexport type Candidate = Transport.Candidate;\nexport type Descriptor = Provider.Descriptor;\nexport type MethodDescriptor = Descriptor[\"methods\"][number];\nexport type Field = NonNullable<MethodDescriptor[\"fields\"]>[number];\n\n/**\n * Where a domain stands with its DNS provider. `Disconnected` carries whatever\n * `connection.discover` found, so the UI can offer a connection the customer already has before\n * asking for another one.\n */\nexport type State = Data.TaggedEnum<{\n Loading: { readonly snapshot: Snapshot | null };\n Disconnected: { readonly snapshot: Snapshot; readonly discovery: Discovery | null };\n Connected: { readonly snapshot: Snapshot };\n Reconnect: { readonly snapshot: Snapshot };\n Submitting: { readonly snapshot: Snapshot | null; readonly discovery: Discovery | null };\n Redirecting: { readonly url: string };\n SelectionRequired: {\n readonly snapshot: Snapshot | null;\n readonly connectionId: string;\n readonly candidates: ReadonlyArray<Candidate>;\n };\n Failure: {\n readonly error: DomainKit.Error;\n readonly snapshot: Snapshot | null;\n readonly discovery: Discovery | null;\n /** The provider and method the customer was using, when a command failed rather than a read. */\n readonly attempt: Attempt | null;\n };\n}>;\nexport const State = Data.taggedEnum<State>();\n\n/** Which provider and method the failed command was for, so the form can answer beside it. */\nexport interface Attempt {\n readonly provider: string;\n readonly method: Storage.AuthMethod;\n}\n\nexport interface ConnectInput {\n readonly provider: string;\n readonly method: Storage.AuthMethod;\n /** Keyed by the descriptor's field names. Ignored by the interactive methods. */\n readonly values?: Readonly<Record<string, string>>;\n /** Where an interactive method returns the customer. */\n readonly returnTo?: string;\n}\n\nexport interface Controller {\n readonly domain: string;\n /**\n * How many times a connection has been established for this domain on this surface: a token\n * connect that landed, or a load that followed this library's own redirect back. It only ever\n * grows, so a flow acts on a change rather than on a state that would fire again every render.\n */\n readonly established: number;\n readonly state: State;\n readonly snapshot: Snapshot | null;\n readonly discovery: Discovery | null;\n readonly providers: ReadonlyArray<Descriptor>;\n readonly connect: (input: ConnectInput) => void;\n /** Attach the domain to a connection this owner already has. */\n readonly reuse: (input: { readonly connectionId: string; readonly zone?: string }) => void;\n /** Answer `SelectionRequired` by naming the zone that serves the domain. */\n readonly select: (zone: string) => void;\n readonly detach: () => void;\n readonly disconnect: () => void;\n /** Re-inspect the domain, discarding any failure. */\n readonly refresh: () => void;\n /** Re-run the step that failed; without one, re-inspect. */\n readonly retry: () => void;\n}\n\nexport interface Options {\n readonly domain: string;\n /**\n * Where an interactive method returns the customer. Defaults to the page they started from;\n * pass `null` to send none and let the server's `defaultReturnTo` decide.\n */\n readonly returnTo?: string | null;\n}\n\n/**\n * An interactive method leaves the page and comes back, so what the library knew is gone with it.\n * It writes down the domain it sent the customer away for, and the load that follows reads it once:\n * that, not a query parameter a host would have to keep, is how a return is told from a reload.\n */\nconst RETURNING = \"domainkit.returning\";\n\nconst markReturn = (domain: string): void => {\n try {\n sessionStorage.setItem(RETURNING, domain);\n } catch {\n // A browser with storage turned off simply loses the one-click return.\n }\n};\n\nconst tookReturn = (domain: string): boolean => {\n try {\n if (sessionStorage.getItem(RETURNING) !== domain) return false;\n sessionStorage.removeItem(RETURNING);\n return true;\n } catch {\n return false;\n }\n};\n\n/** Read at connect time, not at render, so it is the page the customer is actually on. */\nconst currentUrl = (): string | null =>\n typeof window === \"undefined\" ? null : window.location.href;\n\nconst snapshotOf = (state: State): Snapshot | null => {\n switch (state._tag) {\n case \"Connected\":\n case \"Reconnect\":\n case \"Disconnected\":\n return state.snapshot;\n case \"Loading\":\n case \"Submitting\":\n case \"SelectionRequired\":\n case \"Failure\":\n return state.snapshot;\n case \"Redirecting\":\n return null;\n }\n};\n\nconst settled = (snapshot: Snapshot, discovery: Discovery | null): State => {\n switch (snapshot.status) {\n case \"connected\":\n return State.Connected({ snapshot });\n case \"reconnect\":\n return State.Reconnect({ snapshot });\n case \"disconnected\":\n return State.Disconnected({ discovery, snapshot });\n }\n};\n\n/**\n * The domain's connection, and the four ways to change it. Discovery runs on mount whenever the\n * transport declares it and the domain has no connection yet; a discovery failure is not the\n * customer's problem, so the provider list still renders.\n */\nexport function useController({ domain, returnTo }: Options): Controller {\n const { emit, navigate, revision, transport } = useDomainKit();\n const readOnly = useReadOnly();\n const connection = transport.connection;\n const runner = useRunner();\n const [state, setState] = useState<State>(State.Loading({ snapshot: null }));\n\n // The snapshot and the discovery belong to the domain they were read for, so a controller\n // pointed at a new domain drops both while rendering rather than one effect later.\n // What was read travels with the domain it was read for, so a command or a reply that arrives\n // after the controller moved refuses to act: one domain's attachment must never be detached for\n // another.\n const held = useRef<{\n domain: string;\n snapshot: Snapshot | null;\n discovery: Discovery | null;\n }>({ discovery: null, domain, snapshot: null });\n const lastCommand = useRef<{ domain: string; run: () => void } | null>(null);\n // What the customer was doing when it failed, so the dialog can answer beside that method.\n const attempted = useRef<Attempt | null>(null);\n\n const [established, setEstablished] = useState(0);\n const [inspected, setInspected] = useState(domain);\n if (inspected !== domain) {\n setInspected(domain);\n runner.cancel();\n held.current = { discovery: null, domain, snapshot: null };\n lastCommand.current = null;\n setState(State.Loading({ snapshot: null }));\n }\n\n // A failure keeps what was already read: the customer's provider list, the domain in the\n // dialog's description, and the discovery that offered a connection they already have.\n const onFailure = useCallback(\n (error: DomainKit.Error) => {\n setState(\n State.Failure({\n attempt: attempted.current,\n discovery: held.current.discovery,\n error,\n snapshot: held.current.snapshot,\n }),\n );\n emit(Event.Failed({ domain, error }));\n },\n [domain, emit],\n );\n\n const load = useCallback(() => {\n if (connection === undefined) return;\n lastCommand.current = null;\n attempted.current = null;\n held.current = { discovery: null, domain, snapshot: null };\n // A refresh keeps the snapshot on screen; a domain change already cleared it.\n setState((previous) => State.Loading({ snapshot: snapshotOf(previous) }));\n runner.run(\n Effect.flatMap(connection.inspect(domain), (snapshot) =>\n snapshot.status === \"disconnected\"\n ? Effect.map(\n connection.discover(domain).pipe(Effect.catch(() => Effect.succeed(null))),\n (discovery) => ({ discovery, snapshot }),\n )\n : Effect.succeed({ discovery: null, snapshot }),\n ),\n {\n onFailure,\n onSuccess: ({ discovery, snapshot }) => {\n if (held.current.domain !== domain) return;\n held.current = { discovery, domain, snapshot };\n // The marker answers exactly one load: the one that came back. It is spent whatever\n // that load found, so an authorization the customer abandoned cannot leave it lying\n // there for an ordinary page view to read as a return weeks later.\n const returned = tookReturn(domain);\n if (returned && snapshot.status === \"connected\") {\n setEstablished((count) => count + 1);\n }\n setState(settled(snapshot, discovery));\n },\n },\n );\n }, [connection, domain, onFailure, runner]);\n\n useEffect(load, [load, revision]);\n\n const started = useCallback(\n (result: Transport.Started) => {\n if (held.current.domain !== domain) return;\n switch (result._tag) {\n case \"Connected\":\n held.current = { discovery: null, domain, snapshot: result.snapshot };\n setEstablished((count) => count + 1);\n setState(settled(result.snapshot, null));\n if (result.snapshot.connectionId !== null) {\n emit(\n Event.Connected({\n connectionId: result.snapshot.connectionId,\n domain,\n snapshot: result.snapshot,\n }),\n );\n }\n return;\n case \"Redirect\":\n markReturn(domain);\n setState(State.Redirecting({ url: result.authorizationUrl }));\n navigate(result.authorizationUrl);\n return;\n case \"SelectionRequired\":\n setState(\n State.SelectionRequired({\n candidates: result.candidates,\n connectionId: result.connectionId,\n snapshot: held.current.snapshot,\n }),\n );\n return;\n }\n },\n [domain, emit, navigate],\n );\n\n const submit = useCallback(\n (effect: Effect.Effect<Transport.Started, DomainKit.Error>, attempt: Attempt | null) => {\n if (held.current.domain !== domain) return;\n attempted.current = attempt;\n const command = () => {\n setState(\n State.Submitting({\n discovery: held.current.discovery,\n snapshot: held.current.snapshot,\n }),\n );\n runner.run(effect, { onFailure, onSuccess: started });\n };\n lastCommand.current = { domain, run: command };\n command();\n },\n [domain, onFailure, runner, started],\n );\n\n const connect = useCallback(\n (input: ConnectInput) => {\n if (connection === undefined) return;\n const destination = input.returnTo ?? (returnTo === undefined ? currentUrl() : returnTo);\n const interactive = destination === null ? {} : { returnTo: destination };\n const method =\n input.method === \"token\"\n ? Transport.Method.token(input.values ?? {})\n : input.method === \"oauth\"\n ? Transport.Method.oauth(interactive)\n : Transport.Method.integration(interactive);\n submit(connection.start({ domain, method, provider: input.provider }), {\n method: input.method,\n provider: input.provider,\n });\n },\n [connection, domain, returnTo, submit],\n );\n\n const reuse = useCallback(\n (input: { readonly connectionId: string; readonly zone?: string }) => {\n if (connection === undefined) return;\n submit(\n connection.attach({\n connectionId: input.connectionId,\n domain,\n ...(input.zone === undefined ? {} : { zone: input.zone }),\n }),\n null,\n );\n },\n [connection, domain, submit],\n );\n\n const select = useCallback(\n (zone: string) => {\n if (state._tag !== \"SelectionRequired\") return;\n reuse({ connectionId: state.connectionId, zone });\n },\n [reuse, state],\n );\n\n const release = useCallback(\n (effect: Effect.Effect<void, DomainKit.Error>, event: Event) => {\n if (held.current.domain !== domain) return;\n attempted.current = null;\n const command = () => {\n setState(\n State.Submitting({\n discovery: held.current.discovery,\n snapshot: held.current.snapshot,\n }),\n );\n runner.run(effect, {\n onFailure,\n onSuccess: () => {\n emit(event);\n load();\n },\n });\n };\n lastCommand.current = { domain, run: command };\n command();\n },\n [domain, emit, load, onFailure, runner],\n );\n\n const detach = useCallback(() => {\n const attachmentId = held.current.snapshot?.attachmentId;\n if (connection === undefined || attachmentId == null || held.current.domain !== domain) return;\n release(connection.detach(attachmentId), Event.Detached({ domain }));\n }, [connection, domain, release]);\n\n const disconnect = useCallback(() => {\n const connectionId = held.current.snapshot?.connectionId;\n if (connection === undefined || connectionId == null || held.current.domain !== domain) return;\n release(connection.disconnect(connectionId), Event.Disconnected({ connectionId, domain }));\n }, [connection, domain, release]);\n\n const retry = useCallback(() => {\n const command = lastCommand.current;\n // Re-inspecting is a read, so it stays; rerunning the last write does not.\n if (readOnly || command === null || command.domain !== domain) load();\n else command.run();\n }, [domain, load, readOnly]);\n\n return {\n connect,\n detach,\n disconnect,\n domain,\n established,\n discovery:\n state._tag === \"Disconnected\" || state._tag === \"Failure\" || state._tag === \"Submitting\"\n ? state.discovery\n : null,\n providers: snapshotOf(state)?.providers ?? [],\n refresh: load,\n retry,\n reuse,\n select,\n snapshot: snapshotOf(state),\n state,\n };\n}\n\n// ---------------------------------------------------------------------------------------------\n// Parts\n// ---------------------------------------------------------------------------------------------\n\nexport interface RootState extends Record<string, unknown> {\n readonly status: State[\"_tag\"];\n}\n\nexport interface RootProps extends PartProps<\"div\", RootState> {\n readonly controller: Controller;\n}\n\nexport function Root({ controller, ...props }: RootProps): ReactElement {\n return usePart(\n \"div\",\n props,\n { status: controller.state._tag },\n { \"data-domainkit-part\": \"connection-root\", \"data-state\": controller.state._tag },\n );\n}\n\n/**\n * Whether a failure is already answered where it was raised: beside the method the customer used.\n * A flow rendering its own `Outcome` beside the dialog skips it, so the failure announces once.\n */\nexport const answeredInPlace = (controller: Controller): boolean =>\n controller.state._tag === \"Failure\" && controller.state.attempt !== null;\n\n/**\n * Whether the surface should read as connected: it is, or a command it started is in flight over a\n * connection that was. The card and the dialog it opened stay on screen for the length of the\n * command rather than vanishing under the customer half way through it.\n */\nexport const holdsConnection = (controller: Controller): boolean =>\n controller.state._tag === \"Connected\" ||\n (controller.state._tag === \"Submitting\" && controller.snapshot?.status === \"connected\");\n\n/**\n * The provider whose nameservers serve this domain, as the snapshot describes it. Discovery names\n * it by id; without a descriptor there is nothing to draw, so there is no host.\n */\nexport const hostProvider = (controller: Controller): Descriptor | null => {\n const discovery = controller.discovery;\n if (discovery === null || discovery._tag !== \"NotFound\" || discovery.host === null) return null;\n const named = discovery.host.provider;\n return controller.providers.find((entry) => entry.id === named) ?? null;\n};\n\n/** The provider as the customer knows it, falling back to the id when the snapshot has no name. */\nconst displayName = (controller: Controller, provider: string): string =>\n controller.providers.find((entry) => entry.id === provider)?.name ?? provider;\n\nexport interface OutcomeProps extends OutcomeUi.RootProps {\n readonly controller: Controller;\n}\n\n/**\n * The last failure as a card: media, the catalog's title and description, and the retry the flow\n * allows. Children replace the composition and keep the binding.\n */\nexport function Outcome({ children, controller, ...props }: OutcomeProps): ReactElement | null {\n const { messages } = useDomainKit();\n const readOnly = useReadOnly();\n const state = controller.state;\n if (state._tag !== \"Failure\") return null;\n // A reason names an id at best, and a customer knows a provider by the name the descriptor\n // carries, so it is the flow that supplies the name the catalog's titles read.\n const acted =\n state.attempt === null ? undefined : displayName(controller, state.attempt.provider);\n const words = describeOutcome(state.error, messages, {\n ...(controller.snapshot === null ? {} : { domain: controller.snapshot.domain }),\n ...(acted === undefined ? {} : { provider: acted }),\n });\n return (\n <OutcomeUi.Provider\n value={{\n description: words.description ?? \"\",\n layout: props.layout ?? \"card\",\n retry: readOnly ? null : controller.retry,\n retryPart: \"connection-retry\",\n title: words.title,\n tone: \"danger\",\n }}\n >\n <OutcomeUi.Root {...props}>{children ?? <OutcomeUi.Composition />}</OutcomeUi.Root>\n </OutcomeUi.Provider>\n );\n}\n\nexport interface StatusProps extends PartProps<\"p\", RootState> {\n readonly controller: Controller;\n}\n\nexport function Status({ controller, ...props }: StatusProps): ReactElement {\n const { messages } = useDomainKit();\n const state = controller.state;\n const attached = controller.snapshot?.provider ?? null;\n const provider = attached === null ? \"\" : displayName(controller, attached);\n const text = (): string => {\n switch (state._tag) {\n case \"Loading\":\n return messages.loading;\n case \"Submitting\":\n return messages.connecting;\n case \"Redirecting\":\n return messages.redirecting;\n case \"Connected\":\n return messages.connectedTo(provider);\n case \"Reconnect\":\n return messages.reconnectRequired(provider);\n case \"SelectionRequired\":\n return messages.chooseZone;\n case \"Disconnected\":\n return messages.notConnected;\n case \"Failure\":\n return \"\";\n }\n };\n return usePart(\n \"p\",\n props,\n { status: state._tag },\n {\n children: text(),\n \"data-domainkit-part\": \"connection-status\",\n \"data-state\": state._tag,\n role: state._tag === \"Submitting\" || state._tag === \"Loading\" ? \"status\" : undefined,\n },\n );\n}\n\n/**\n * The one field a rejected command was about, if any. A provider that turns down credentials is\n * answering the secret it was given, and it names no field, so the first secret carries the\n * answer; anything else is about the request rather than one input.\n */\nconst rejected = (\n reason: DomainKit.Error[\"reason\"] | null,\n fields: ReadonlyArray<Field>,\n): string | null => {\n if (reason === null) return null;\n if (reason._tag === \"InvalidInput\") {\n return fields.find((field) => field.name === reason.field)?.name ?? null;\n }\n if (reason._tag !== \"Unauthenticated\" && reason._tag !== \"Forbidden\") return null;\n return fields.find((field) => field.secret)?.name ?? null;\n};\n\ninterface MethodProps {\n readonly controller: Controller;\n readonly method: MethodDescriptor;\n readonly provider: Descriptor;\n /** Record one field's value with the form, which owns it across a rejection. */\n readonly onEnter: (name: string, value: string) => void;\n readonly values: Readonly<Record<string, string>>;\n}\n\ninterface FieldProps {\n readonly controller: Controller;\n readonly docsUrl: string | null;\n readonly field: Field;\n readonly invalid: boolean;\n readonly onEnter: (value: string) => void;\n readonly value: string;\n}\n\n/**\n * One declared field in shadcn's `Field` anatomy: the label, the control, the note under it, and\n * the error the provider answered with. The docs link rides the field it explains. The value is\n * the form's, not the input's, so a rejection answers beside what the customer typed.\n */\nfunction TokenField({\n controller,\n docsUrl,\n field,\n invalid,\n onEnter,\n value,\n}: FieldProps): ReactElement {\n const { messages } = useDomainKit();\n const icons = useIcons();\n const id = useId();\n return (\n <div\n data-domainkit-part=\"field\"\n data-invalid={invalid ? \"\" : undefined}\n data-orientation=\"vertical\"\n >\n <label data-domainkit-part=\"field-label\" htmlFor={id}>\n {messages.fieldLabel(field.name)}\n {field.required ? null : (\n <span data-domainkit-part=\"field-optional\">{messages.optionalField}</span>\n )}\n </label>\n <input\n aria-invalid={invalid ? true : undefined}\n autoComplete=\"off\"\n data-domainkit-part=\"field-input\"\n id={id}\n name={field.name}\n onChange={(event) => onEnter(event.target.value)}\n required={field.required}\n type={field.secret ? \"password\" : \"text\"}\n value={value}\n />\n {docsUrl === null ? null : (\n <a data-domainkit-part=\"field-description\" href={docsUrl} rel=\"noreferrer\" target=\"_blank\">\n {messages.getToken}\n <span aria-hidden=\"true\" data-icon=\"inline-end\">\n {icons.external}\n </span>\n </a>\n )}\n {invalid ? (\n <div data-domainkit-part=\"field-error\">\n <Outcome controller={controller} layout=\"inline\" />\n </div>\n ) : null}\n </div>\n );\n}\n\n/**\n * One auth method, rendered from its descriptor. A token method draws an input per declared\n * field, so a provider that needs an account id alongside a token needs no code here. The fields\n * a provider does not need sit behind a disclosure, so the common form is one field.\n */\nfunction Method({ controller, method, onEnter, provider, values }: MethodProps): ReactElement {\n const { messages } = useDomainKit();\n const icons = useIcons();\n // The fields a provider does not need, and whether the customer asked for them.\n const [more, setMore] = useState(false);\n const state = controller.state;\n const busy = state._tag === \"Submitting\";\n // A failed command answers where it was raised, so the customer keeps the form they filled in.\n const failed =\n state._tag === \"Failure\" &&\n state.attempt !== null &&\n state.attempt.provider === provider.id &&\n state.attempt.method === method.kind;\n if (method.fields === null) {\n return (\n <>\n <button\n data-domainkit-part={method.kind === \"oauth\" ? \"oauth-connect\" : \"integration-connect\"}\n data-provider={provider.id}\n disabled={busy}\n onClick={() => controller.connect({ method: method.kind, provider: provider.id })}\n type=\"button\"\n >\n {method.kind === \"oauth\"\n ? messages.methodOAuth(provider.name)\n : messages.methodIntegration(provider.name)}\n </button>\n {failed ? <Outcome controller={controller} layout=\"inline\" /> : null}\n </>\n );\n }\n const fields = method.fields;\n const answered = rejected(failed && state._tag === \"Failure\" ? state.error.reason : null, fields);\n const required = fields.filter((field) => field.required);\n const optional = fields.filter((field) => !field.required);\n // A rejection about one of them opens the panel, so the answer is never behind a closed control.\n const showMore = more || optional.some((field) => field.name === answered);\n // The docs link explains the secret, so it rides that field rather than the form.\n const explains = (required.find((field) => field.secret) ?? required[0] ?? optional[0])?.name;\n const render = (field: Field) => (\n <TokenField\n controller={controller}\n docsUrl={field.name === explains ? method.docsUrl : null}\n field={field}\n invalid={field.name === answered}\n key={field.name}\n onEnter={(value) => onEnter(field.name, value)}\n value={values[field.name] ?? \"\"}\n />\n );\n return (\n <form\n data-domainkit-part=\"token-connect\"\n data-provider={provider.id}\n onSubmit={(event) => {\n event.preventDefault();\n // The form's own values, not the inputs': they are what survives a rejection.\n const submitted: Record<string, string> = {};\n for (const field of fields) {\n const value = values[field.name] ?? \"\";\n if (value !== \"\" || field.required) submitted[field.name] = value;\n }\n controller.connect({ method: method.kind, provider: provider.id, values: submitted });\n }}\n >\n {required.map(render)}\n {optional.length === 0 ? null : (\n <BaseCollapsible.Root\n data-domainkit-part=\"more-options\"\n data-state={showMore ? \"open\" : \"closed\"}\n onOpenChange={setMore}\n open={showMore}\n >\n <BaseCollapsible.Trigger data-domainkit-part=\"more-options-trigger\">\n {messages.moreOptions}\n <span aria-hidden=\"true\" data-icon=\"inline-end\">\n {icons.chevron}\n </span>\n </BaseCollapsible.Trigger>\n <BaseCollapsible.Panel data-domainkit-part=\"more-options-panel\">\n {optional.map(render)}\n </BaseCollapsible.Panel>\n </BaseCollapsible.Root>\n )}\n {failed && answered === null ? <Outcome controller={controller} layout=\"inline\" /> : null}\n <button data-domainkit-part=\"token-submit\" disabled={busy} type=\"submit\">\n {messages.methodToken}\n </button>\n </form>\n );\n}\n\ninterface AuthenticationProps extends Pick<MethodProps, \"onEnter\" | \"values\"> {\n readonly controller: Controller;\n readonly provider: Descriptor;\n /** Whether this provider's methods are showing. A narrowed dialog has one, always open. */\n readonly open: boolean;\n readonly onOpen?: () => void;\n /** Show the token form alone: the customer asked for it and the surface navigated there. */\n readonly typing: boolean;\n /** Ask for the token form. Absent when this surface cannot navigate to one. */\n readonly onType?: () => void;\n}\n\n/**\n * One provider's methods, in the order the descriptor declares them: the interactive ones a\n * customer clicks through, then the token. Where a provider offers both, the interactive method is\n * the offer and a plain button opens the token form in its place, so the dialog asks for one\n * decision at a time. With a heading the whole provider is a disclosure the customer opens; the\n * provider a narrowed dialog is about carries no heading, because the dialog title already names\n * it.\n */\nfunction Authentication({\n controller,\n onEnter,\n onOpen,\n onType,\n open,\n provider,\n typing,\n values,\n}: AuthenticationProps): ReactElement {\n const { messages } = useDomainKit();\n const state = controller.state;\n const render = (method: MethodDescriptor) => (\n <Method\n controller={controller}\n key={`${provider.id}:${method.kind}`}\n method={method}\n onEnter={onEnter}\n provider={provider}\n values={values}\n />\n );\n const interactive = provider.methods.filter((method) => method.fields === null);\n const typed = provider.methods.filter((method) => method.fields !== null);\n const alternate = interactive.length > 0 && typed.length > 0;\n const methods = !alternate ? (\n provider.methods.map(render)\n ) : typing ? (\n typed.map(render)\n ) : (\n <>\n {interactive.map(render)}\n <button\n data-domainkit-part=\"method-alternate\"\n data-provider={provider.id}\n disabled={state._tag === \"Submitting\"}\n onClick={onType}\n type=\"button\"\n >\n {messages.useTokenInstead}\n </button>\n </>\n );\n return (\n <section\n data-domainkit-part=\"provider-authentication\"\n data-provider={provider.id}\n data-state={open ? \"open\" : \"closed\"}\n >\n {onOpen === undefined ? null : (\n <button\n aria-expanded={open}\n data-domainkit-part=\"provider-heading\"\n onClick={onOpen}\n type=\"button\"\n >\n <Provider.Mark provider={provider} />\n <strong>{provider.name}</strong>\n </button>\n )}\n {open ? methods : null}\n </section>\n );\n}\n\nexport interface FormProps extends PartProps<\"div\", RootState> {\n readonly controller: Controller;\n /**\n * Narrow to this provider whatever discovery found. The dialog's header menu sets it, so a\n * customer who picks another provider gets the same one-decision surface for it.\n */\n readonly provider?: string;\n}\n\n/**\n * Everything a disconnected domain can do: a connection discovery already found, the connections\n * this owner already has, then each provider's declared methods.\n */\nexport function Form({ controller, provider: narrowed, ...props }: FormProps): ReactElement {\n const { messages } = useDomainKit();\n // One provider open at a time, so a dialog listing every provider is a list rather than a wall.\n // `null` is the customer choosing nothing yet; `\"\"` is them closing what was open.\n const [opened, setOpened] = useState<string | null>(null);\n // What the customer typed, for the one domain and provider they typed it into. A rejection keeps\n // it, so \"try again\" starts from the value rather than from nothing. Another provider's form is\n // its own, a connection that lands is a form nobody needs again, and a credential never follows\n // the flow to another domain.\n const [entered, setEntered] = useState<{\n readonly domain: string;\n readonly provider: string;\n readonly values: Readonly<Record<string, string>>;\n } | null>(null);\n const state = controller.state;\n const owner = controller.domain;\n // Dropped while rendering, not one effect later, so no frame ever shows one domain's token in\n // another's form.\n if (entered !== null && (entered.domain !== owner || state._tag === \"Connected\")) {\n setEntered(null);\n }\n const kept = entered?.domain === owner ? entered : null;\n const enter = (provider: string, name: string, value: string) =>\n setEntered((previous) => {\n const held = previous?.domain === owner && previous.provider === provider ? previous : null;\n return {\n domain: owner,\n provider,\n values: held === null ? { [name]: value } : { ...held.values, [name]: value },\n };\n });\n const valuesFor = (provider: string): Readonly<Record<string, string>> =>\n kept?.provider === provider ? kept.values : {};\n const snapshot = controller.snapshot;\n const discovery = controller.discovery;\n const candidates =\n state._tag === \"SelectionRequired\"\n ? state.candidates.map((candidate) => ({ ...candidate, connectionId: state.connectionId }))\n : discovery !== null && discovery._tag === \"SelectionRequired\"\n ? discovery.candidates\n : [];\n const resolved = discovery !== null && discovery._tag === \"Resolved\" ? discovery : null;\n const reusable = snapshot?.reusable ?? [];\n const providers = controller.providers;\n // The provider the surface is about: the one a header menu chose, else the one that serves the\n // zone. A known host is the whole offer; without one every provider is listed.\n const host = providers.find((entry) => entry.id === narrowed) ?? hostProvider(controller);\n // Which provider's token form the customer navigated to, so the body is one decision at a time.\n const [typing, setTyping] = useState<string | null>(null);\n const authentication = (provider: Descriptor, open: boolean) => (\n <Authentication\n controller={controller}\n key={provider.id}\n onEnter={(name, value) => enter(provider.id, name, value)}\n onOpen={() => setOpened(open ? \"\" : provider.id)}\n onType={() => setTyping(provider.id)}\n open={open}\n provider={provider}\n typing={typing === provider.id}\n values={valuesFor(provider.id)}\n />\n );\n return usePart(\n \"div\",\n props,\n { status: state._tag },\n {\n children: (\n <>\n {resolved === null ? null : (\n <section data-domainkit-part=\"discovery-resolved\">\n <p>{messages.discoveredConnection(resolved.label)}</p>\n <button\n data-domainkit-part=\"attach-target\"\n onClick={() =>\n controller.reuse({\n connectionId: resolved.connectionId,\n zone: resolved.zone,\n })\n }\n type=\"button\"\n >\n {messages.useConnection(resolved.label)}\n </button>\n </section>\n )}\n {candidates.length === 0 ? null : (\n <section data-domainkit-part=\"discovery-candidates\">\n <p>\n {state._tag === \"SelectionRequired\"\n ? messages.chooseZone\n : messages.discoveryAmbiguous}\n </p>\n <div data-domainkit-part=\"target-list\" data-state=\"ambiguous\">\n {candidates.map((candidate) => (\n <button\n data-domainkit-part=\"attach-target\"\n key={`${candidate.connectionId}:${candidate.zone}`}\n onClick={() =>\n controller.reuse({\n connectionId: candidate.connectionId,\n zone: candidate.zone,\n })\n }\n type=\"button\"\n >\n {messages.useConnection(candidate.label)}\n </button>\n ))}\n </div>\n </section>\n )}\n {reusable.length === 0 ? null : (\n <section data-domainkit-part=\"reusable-connection\">\n <div data-domainkit-part=\"reusable-connection-heading\">\n <strong>{messages.reusableConnections}</strong>\n </div>\n {reusable.map((connection) => (\n <button\n data-connection-id={connection.connectionId}\n data-domainkit-part=\"attach-target\"\n key={connection.connectionId}\n onClick={() => controller.reuse({ connectionId: connection.connectionId })}\n type=\"button\"\n >\n {messages.useConnection(connection.provider)}\n </button>\n ))}\n </section>\n )}\n {providers.length === 0 ? (\n <p data-domainkit-part=\"target-unavailable\">{messages.noProviders}</p>\n ) : host === null ? (\n providers.map((provider) =>\n authentication(\n provider,\n opened === null ? provider.id === providers[0]?.id : opened === provider.id,\n ),\n )\n ) : (\n <>\n {typing === host.id ? (\n <button\n data-domainkit-part=\"dialog-back\"\n onClick={() => setTyping(null)}\n type=\"button\"\n >\n {messages.back}\n </button>\n ) : null}\n <Authentication\n controller={controller}\n onEnter={(name, value) => enter(host.id, name, value)}\n onType={() => setTyping(host.id)}\n open\n provider={host}\n typing={typing === host.id}\n values={valuesFor(host.id)}\n />\n </>\n )}\n </>\n ),\n \"data-domainkit-part\": \"connection-form\",\n },\n );\n}\n\nexport interface DialogProps {\n readonly controller: Controller;\n readonly children?: ReactNode;\n /** Replace the dialog surface: a drawer, a panel, whatever the host already has. */\n readonly render?: (props: { readonly open: boolean; readonly children: ReactNode }) => ReactNode;\n readonly title?: ReactNode;\n readonly trigger?: ReactNode;\n}\n\n/** The connect surface. Without `render` it is a Base UI dialog behind `trigger`. */\nexport function Dialog({\n children,\n controller,\n render,\n title,\n trigger,\n}: DialogProps): ReactElement {\n const { colorScheme, messages, portalContainer, themeStyle } = useDomainKit();\n const icons = useIcons();\n const readOnly = useReadOnly();\n const [open, setOpen] = useState(false);\n const state = controller.state;\n const busy = state._tag === \"Submitting\";\n // A failure a method already answers is not repeated at the foot of the dialog.\n const unattributed = state._tag === \"Failure\" && !answeredInPlace(controller);\n const snapshot = controller.snapshot;\n // The provider the dialog is about: one the customer picked from the header, else the one\n // already attached, else the one that serves the zone.\n const [chosen, setChosen] = useState<string | null>(null);\n const attached = snapshot?.provider ?? null;\n const host = hostProvider(controller);\n const narrowed = controller.providers.find((entry) => entry.id === (chosen ?? attached)) ?? host;\n const named = narrowed?.name ?? null;\n const heading =\n title ?? (named === null ? messages.connectAnyTitle : messages.connectTitle(named));\n // Every other provider the owner could use instead. With none there is nothing to choose from.\n const alternatives =\n narrowed === null ? [] : controller.providers.filter((entry) => entry.id !== narrowed.id);\n const running =\n state._tag === \"Loading\" ||\n state._tag === \"Submitting\" ||\n state._tag === \"Redirecting\" ||\n state._tag === \"SelectionRequired\";\n // A named provider makes the trigger a short \"Connect\"; without one it says what it opens.\n const label = named === null ? messages.connectAnyTitle : messages.connect;\n const body = children ?? (\n <Form controller={controller} {...(chosen === null ? {} : { provider: chosen })} />\n );\n // Connecting is a write, so the whole surface goes rather than a disabled trigger.\n if (readOnly) return <></>;\n if (render !== undefined) {\n return (\n <>\n <button\n data-domainkit-part=\"connection-trigger\"\n onClick={() => setOpen(!open)}\n type=\"button\"\n >\n {trigger ?? label}\n </button>\n {render({ children: body, open })}\n </>\n );\n }\n return (\n <BaseDialog.Root\n onOpenChange={(next, details) => {\n if (!next && busy) {\n details.cancel();\n return;\n }\n setOpen(next);\n }}\n open={open}\n >\n <BaseDialog.Trigger data-domainkit-part=\"connection-trigger\">\n {trigger ?? label}\n </BaseDialog.Trigger>\n <BaseDialog.Portal container={portalContainer}>\n <BaseDialog.Backdrop\n data-color-scheme={colorScheme}\n data-domainkit-part=\"dialog-backdrop\"\n data-domainkit-root=\"\"\n style={themeStyle}\n />\n <BaseDialog.Popup\n data-color-scheme={colorScheme}\n data-domainkit-part=\"connection-dialog\"\n data-domainkit-root=\"\"\n style={themeStyle}\n >\n <div data-domainkit-part=\"dialog-header\">\n {narrowed === null ? null : (\n <div data-domainkit-part=\"dialog-media\">\n <Provider.Mark provider={narrowed} />\n </div>\n )}\n <div data-domainkit-part=\"dialog-heading\">\n <BaseDialog.Title data-domainkit-part=\"dialog-title\">\n {alternatives.length === 0 || title !== undefined ? (\n heading\n ) : (\n <BaseMenu.Root>\n <BaseMenu.Trigger data-domainkit-part=\"dialog-provider-menu\" disabled={busy}>\n {heading}\n <span aria-hidden=\"true\" data-icon=\"inline-end\">\n {icons.chevron}\n </span>\n </BaseMenu.Trigger>\n <BaseMenu.Portal container={portalContainer}>\n <BaseMenu.Positioner\n align=\"start\"\n data-domainkit-part=\"provider-menu-positioner\"\n sideOffset={6}\n >\n <BaseMenu.Popup\n aria-label={messages.useAnotherProvider}\n data-color-scheme={colorScheme}\n data-domainkit-part=\"provider-menu\"\n data-domainkit-root=\"\"\n style={themeStyle}\n >\n {alternatives.map((entry) => (\n <BaseMenu.Item\n data-domainkit-part=\"provider-menu-item\"\n data-provider={entry.id}\n key={entry.id}\n onClick={() => setChosen(entry.id)}\n >\n <Provider.Mark provider={entry} />\n {entry.name}\n </BaseMenu.Item>\n ))}\n </BaseMenu.Popup>\n </BaseMenu.Positioner>\n </BaseMenu.Portal>\n </BaseMenu.Root>\n )}\n </BaseDialog.Title>\n <BaseDialog.Description data-domainkit-part=\"dialog-description\">\n {messages.connectDescription(snapshot?.domain ?? \"\")}\n </BaseDialog.Description>\n </div>\n {busy ? null : (\n <BaseDialog.Close aria-label={messages.close} data-domainkit-part=\"dialog-close\">\n ×\n </BaseDialog.Close>\n )}\n </div>\n <div data-domainkit-part=\"dialog-body\">\n {/* The title and description already say what is connected; this line is progress. */}\n {running ? <Status controller={controller} /> : null}\n {body}\n {unattributed ? <Outcome controller={controller} /> : null}\n </div>\n {busy ? null : (\n <div data-domainkit-part=\"dialog-footer\">\n <BaseDialog.Close data-domainkit-part=\"dialog-cancel\">\n {messages.cancel}\n </BaseDialog.Close>\n </div>\n )}\n </BaseDialog.Popup>\n </BaseDialog.Portal>\n </BaseDialog.Root>\n );\n}\n\n/**\n * Whether the flow offers a connect surface: only when discovery names a host, always, or never.\n * `never` is a host that decides for itself, such as a domain already ready without DomainKit; a\n * connected domain keeps its status and its disconnect either way.\n */\nexport type Invitation = \"always\" | \"detected\" | \"never\";\n\n/**\n * Whether the connect surface has anything to offer for this domain: a provider that serves the\n * zone, a connection discovery already found, one the owner already holds, or a command already\n * running. Never while a connection is held, which is what `holdsConnection` answers. `Prompt`\n * renders on this, and `Domain.Flow` reports it so a host can order its own offers beside\n * DomainKit's rather than competing with them.\n */\nexport const offering = (controller: Controller, connect: Invitation = \"detected\"): boolean => {\n // A surface that holds a connection is not offering one: the card is what renders, and a host\n // reading both must never see them claim different things about the same domain.\n if (holdsConnection(controller)) return false;\n const state = controller.state;\n // A command in flight owns the surface whatever discovery found: it is how the customer answers\n // a zone choice, a reconnect, or a redirect that came back.\n if (\n state._tag === \"Submitting\" ||\n state._tag === \"Redirecting\" ||\n state._tag === \"SelectionRequired\" ||\n state._tag === \"Reconnect\"\n ) {\n return true;\n }\n if (connect !== \"detected\") return connect === \"always\";\n const discovery = controller.discovery;\n return (\n hostProvider(controller) !== null ||\n (discovery !== null && discovery._tag !== \"NotFound\") ||\n (controller.snapshot?.reusable.length ?? 0) > 0\n );\n};\n\nexport interface PromptProps extends PartProps<\"div\", RootState> {\n readonly controller: Controller;\n /**\n * `detected` offers nothing when discovery names no host, which is the honest answer for a\n * domain DomainKit cannot write to. `always` offers the all-providers dialog anyway, and\n * `never` offers none.\n */\n readonly connect?: Invitation;\n}\n\n/**\n * The disconnected offer: the provider whose nameservers serve the domain, what that means, and\n * the trigger that connects it. With no host detected there is nothing to offer, so nothing\n * renders unless the host application asks for the dialog anyway.\n */\nexport function Prompt({\n connect = \"detected\",\n controller,\n ...props\n}: PromptProps): ReactElement | null {\n const { messages } = useDomainKit();\n const readOnly = useReadOnly();\n const state = controller.state;\n const host = hostProvider(controller);\n const element = usePart(\n \"div\",\n props,\n { status: state._tag },\n {\n children: (\n <>\n {host === null ? null : (\n <div data-domainkit-part=\"host-identity\">\n <Provider.Mark provider={host} />\n <span data-domainkit-part=\"host-name\">{host.name}</span>\n <span data-domainkit-part=\"host-statement\">{messages.hostOwnsZone}</span>\n </div>\n )}\n <Dialog controller={controller} />\n </>\n ),\n \"data-domainkit-part\": \"connect-prompt\",\n \"data-host\": host?.id,\n },\n );\n if (!offering(controller, connect)) return null;\n // Read-only keeps the statement and drops the trigger, like every other write surface.\n if (readOnly && host === null) return null;\n return element;\n}\n\n/** The plan an attempt holds, whatever step it is on; `null` before there is one. */\nconst planOf = (state: Cleanup.State): Plan.Model | null => {\n switch (state._tag) {\n case \"Planned\":\n case \"Approving\":\n case \"Applying\":\n case \"Rejecting\":\n case \"Rejected\":\n return state.plan;\n case \"Applied\":\n return state.plan;\n case \"Idle\":\n case \"Planning\":\n case \"Failure\":\n return null;\n }\n};\n\nexport interface DisconnectDialogProps {\n readonly controller: Controller;\n /** The receipt the cleanup this dialog ran produced, for a host that tracks its own state. */\n readonly onCleaned?: (receipt: Receipt.Model) => void;\n readonly trigger?: ReactNode;\n}\n\n/**\n * Letting a provider go, with the records DomainKit added as one decision rather than two.\n * Confirming removes what the domain's apply receipt proves DomainKit created, then releases the\n * connection; a plan with nothing in it is not a failure, so it goes straight to the release.\n *\n * The cleanup is this dialog's own, so nothing re-reads the snapshot in between: the disconnect\n * needs the connection the cleanup just used.\n */\nexport function DisconnectDialog({\n controller,\n onCleaned,\n trigger,\n}: DisconnectDialogProps): ReactElement {\n const { capabilities, colorScheme, messages, portalContainer, themeStyle } = useDomainKit();\n const readOnly = useReadOnly();\n const [open, setOpen] = useState(false);\n const [alsoRemove, setAlsoRemove] = useState(true);\n // The first of the two commands the confirm runs. The second is the controller's own.\n const [removing, setRemoving] = useState(false);\n const snapshot = controller.snapshot;\n const receiptId = snapshot?.lastReceiptId ?? null;\n // Only an apply receipt proves DomainKit created anything, so only then is there a choice. The\n // receipt is this domain's, so releasing a shared connection leaves the other domains' records\n // where they are; the option says so rather than promising more than it can do.\n const removable = capabilities.includes(\"cleanup\") && receiptId !== null;\n // Releasing a connection takes every domain on it, so a shared one asks which the customer meant.\n const shared = (snapshot?.connectionDomains ?? 0) > 1;\n const [everyDomain, setEveryDomain] = useState(false);\n const cleanup = Cleanup.useController({\n domain: controller.domain,\n ...(onCleaned === undefined ? {} : { onCleaned }),\n ...(receiptId === null ? {} : { receiptId: Receipt.ReceiptId.make(receiptId) }),\n });\n const { approve, plan, state: cleaning } = cleanup;\n // The plan is built when the dialog opens, not when the customer confirms, so what would be\n // removed is on screen while they decide rather than after.\n const removals = planOf(cleaning);\n useEffect(() => {\n if (open && removable && cleaning._tag === \"Idle\") plan();\n }, [cleaning, open, plan, removable]);\n const detach = controller.detach;\n const release = controller.disconnect;\n // A shared connection detaches this domain by default; only \"all domains\" ends the connection.\n const disconnect = useCallback(\n () => (shared && !everyDomain ? detach() : release()),\n [detach, everyDomain, release, shared],\n );\n // The release is the controller's own command, so its state says whether one is in flight; a\n // failure ends it and hands the button back with no bookkeeping here.\n const releasing = controller.state._tag === \"Submitting\";\n\n useEffect(() => {\n if (!removing) return;\n if (cleaning._tag === \"Applied\") {\n setRemoving(false);\n disconnect();\n return;\n }\n if (cleaning._tag === \"Failure\" || cleaning._tag === \"Rejected\") setRemoving(false);\n }, [cleaning, disconnect, removing]);\n\n const busy = removing || releasing;\n // No plan, no promise: while one is being built, and after one failed to build, the option this\n // dialog defaults to cannot be honoured, so confirming would release the connection and leave\n // the records behind. The cleanup outcome carries the retry, and cancelling is always there.\n const settling = removable && removals === null;\n const provider = snapshot?.provider ?? null;\n const named = provider === null ? \"\" : displayName(controller, provider);\n const heading = provider === null ? messages.disconnect : messages.disconnectTitle(named);\n // Nothing to remove is not a choice: the switch appears over records, or not at all.\n const count = removals?.operations.length ?? 0;\n const choosable = removable && count > 0;\n if (readOnly) return <></>;\n return (\n <BaseDialog.Root\n onOpenChange={(next, details) => {\n if (!next && busy) {\n details.cancel();\n return;\n }\n setOpen(next);\n }}\n open={open}\n >\n <BaseDialog.Trigger data-domainkit-part=\"disconnect-action\">\n {trigger ?? messages.disconnect}\n </BaseDialog.Trigger>\n <BaseDialog.Portal container={portalContainer}>\n <BaseDialog.Backdrop\n data-color-scheme={colorScheme}\n data-domainkit-part=\"dialog-backdrop\"\n data-domainkit-root=\"\"\n style={themeStyle}\n />\n <BaseDialog.Popup\n data-color-scheme={colorScheme}\n // The records it would remove are what needs the room, so the width follows the list.\n data-cleanup={choosable ? \"offered\" : \"none\"}\n data-domainkit-part=\"disconnect-dialog\"\n data-domainkit-root=\"\"\n style={themeStyle}\n >\n <div data-domainkit-part=\"dialog-header\">\n <div data-domainkit-part=\"dialog-heading\">\n <BaseDialog.Title data-domainkit-part=\"dialog-title\">{heading}</BaseDialog.Title>\n <BaseDialog.Description data-domainkit-part=\"dialog-description\">\n {messages.disconnectConsent(snapshot?.domain ?? \"\", named)}\n </BaseDialog.Description>\n </div>\n {busy ? null : (\n <BaseDialog.Close aria-label={messages.close} data-domainkit-part=\"dialog-close\">\n ×\n </BaseDialog.Close>\n )}\n </div>\n <div data-domainkit-part=\"dialog-body\">\n {shared ? (\n <fieldset data-domainkit-part=\"disconnect-scope\">\n <legend>{messages.disconnectScope}</legend>\n <label>\n <input\n checked={!everyDomain}\n disabled={busy}\n name=\"disconnect-scope\"\n onChange={() => setEveryDomain(false)}\n type=\"radio\"\n />\n {messages.disconnectThisDomain}\n </label>\n <label>\n <input\n checked={everyDomain}\n disabled={busy}\n name=\"disconnect-scope\"\n onChange={() => setEveryDomain(true)}\n type=\"radio\"\n />\n {messages.disconnectEveryDomain(snapshot?.connectionDomains ?? 0)}\n </label>\n </fieldset>\n ) : null}\n {choosable ? (\n <div data-domainkit-part=\"disconnect-cleanup\" data-state={alsoRemove ? \"on\" : \"off\"}>\n <label data-domainkit-part=\"disconnect-cleanup-label\">\n <BaseSwitch.Root\n checked={alsoRemove}\n data-domainkit-part=\"disconnect-cleanup-switch\"\n disabled={busy}\n onCheckedChange={setAlsoRemove}\n >\n <BaseSwitch.Thumb data-domainkit-part=\"disconnect-cleanup-thumb\" />\n </BaseSwitch.Root>\n {messages.disconnectWithCleanup(count)}\n </label>\n <div data-domainkit-part=\"disconnect-cleanup-panel\">\n {removals === null ? null : <Operations.List plan={removals} />}\n {alsoRemove ? null : (\n <p data-domainkit-part=\"disconnect-cleanup-note\">\n {messages.disconnectKeepsRecords(named)}\n </p>\n )}\n </div>\n </div>\n ) : null}\n <Cleanup.Status controller={cleanup} />\n {releasing ? (\n <p data-domainkit-part=\"disconnect-status\" role=\"status\">\n {messages.disconnecting}\n </p>\n ) : null}\n <Cleanup.Outcome controller={cleanup} />\n <Outcome controller={controller} />\n </div>\n <div data-domainkit-part=\"dialog-footer\">\n <button\n data-domainkit-part=\"disconnect-confirm\"\n disabled={busy || settling}\n onClick={() => {\n if (choosable && alsoRemove) {\n setRemoving(true);\n approve();\n return;\n }\n disconnect();\n }}\n type=\"button\"\n >\n {messages.disconnect}\n </button>\n {busy ? null : (\n <BaseDialog.Close data-domainkit-part=\"dialog-cancel\">\n {messages.cancel}\n </BaseDialog.Close>\n )}\n </div>\n </BaseDialog.Popup>\n </BaseDialog.Portal>\n </BaseDialog.Root>\n );\n}\n\nexport interface CardProps extends PartProps<\"div\", RootState> {\n readonly controller: Controller;\n /** The receipt a cleanup run from the disconnect dialog produced. */\n readonly onCleaned?: (receipt: Receipt.Model) => void;\n}\n\n/**\n * A connected domain, with the prompt card's anatomy: the provider's mark, the name the customer\n * knows it by, where the connection stands, and the one action that ends it.\n */\nexport function Card({ controller, onCleaned, ...props }: CardProps): ReactElement {\n const { messages } = useDomainKit();\n const readOnly = useReadOnly();\n const state = controller.state;\n const snapshot = controller.snapshot;\n const provider = controller.providers.find((entry) => entry.id === snapshot?.provider);\n const standing = state._tag === \"Reconnect\" ? messages.needsReconnect : messages.connected;\n return usePart(\n \"div\",\n props,\n { status: state._tag },\n {\n children: (\n <>\n <div data-domainkit-part=\"connected-identity\">\n {provider === undefined ? null : <Provider.Mark provider={provider} />}\n <span data-domainkit-part=\"host-name\">\n {provider?.name ?? snapshot?.provider ?? \"\"}\n </span>\n <span data-domainkit-part=\"host-statement\">{standing}</span>\n </div>\n {readOnly ? null : (\n <div data-domainkit-part=\"connected-actions\">\n <DisconnectDialog\n controller={controller}\n {...(onCleaned === undefined ? {} : { onCleaned })}\n />\n </div>\n )}\n <Outcome controller={controller} />\n </>\n ),\n \"data-domainkit-part\": \"connected-card\",\n },\n );\n}\n\nexport interface FlowProps extends Omit<RootProps, \"controller\"> {\n readonly domain: string;\n readonly returnTo?: string | null;\n /** Offer the connect dialog even when discovery names no host. Defaults to `detected`. */\n readonly connect?: Invitation;\n /** The receipt a cleanup run from the disconnect dialog produced. */\n readonly onCleaned?: (receipt: Receipt.Model) => void;\n}\n\n/** Connection on its own: the card once connected, the prompt until then. */\nexport function Flow({ connect, domain, onCleaned, returnTo, ...props }: FlowProps): ReactElement {\n const controller = useController({ domain, ...(returnTo === undefined ? {} : { returnTo }) });\n return (\n <Root controller={controller} {...props}>\n {holdsConnection(controller) ? (\n <Card controller={controller} {...(onCleaned === undefined ? {} : { onCleaned })} />\n ) : (\n <>\n <Prompt controller={controller} {...(connect === undefined ? {} : { connect })} />\n {answeredInPlace(controller) ? null : <Outcome controller={controller} />}\n </>\n )}\n </Root>\n );\n}\n","import { DnsRecord, type Receipt } from \"domainkit\";\nimport { useCallback, useState, type ReactElement, type ReactNode } from \"react\";\n\nimport { State, useAttempt, type Controller } from \"./attempt.ts\";\nimport type { PartProps } from \"./composition.tsx\";\nimport { usePart } from \"./composition.tsx\";\nimport { useDomainKit } from \"./domain-kit.tsx\";\nimport { Event } from \"./events.ts\";\nimport * as Records from \"./records.tsx\";\nimport * as Review from \"./review.tsx\";\n\nexport { State };\nexport type { Controller };\n\nexport interface Options {\n readonly domain: string;\n readonly requirements: ReadonlyArray<DnsRecord.Model>;\n readonly onApplied?: (receipt: Receipt.Model) => void;\n}\n\n/** Plan, approve, apply. `approve` authorizes the digest and applies it in the same action. */\n/**\n * Requirements identify themselves by content, so an inline array does not abandon the attempt.\n * Every field counts: a plan turns on `policy`, and `ttl` and `purpose` ride the wire with it.\n */\nconst keyOf = (domain: string, requirements: ReadonlyArray<DnsRecord.Model>): string =>\n [domain, Records.requirementsKey(requirements)].join(\"|\");\n\nexport function useController({ domain, onApplied, requirements }: Options): Controller {\n const { transport } = useDomainKit();\n const group = transport.provisioning;\n return useAttempt({\n domain,\n key: keyOf(domain, requirements),\n done: (receipt) => Event.Applied({ domain, receipt }),\n group,\n onDone: onApplied,\n plan: useCallback(\n () => (group === undefined ? null : group.plan({ domain, requirements })),\n [domain, group, requirements],\n ),\n });\n}\n\nexport interface RootState extends Record<string, unknown> {\n readonly status: State[\"_tag\"];\n}\n\nexport interface RootProps extends PartProps<\"div\", RootState> {\n readonly controller: Controller;\n}\n\nexport function Root({ controller, ...props }: RootProps): ReactElement {\n return usePart(\n \"div\",\n props,\n { status: controller.state._tag },\n { \"data-domainkit-part\": \"provisioning-flow\", \"data-state\": controller.state._tag },\n );\n}\n\nexport interface DialogProps extends Omit<Review.DialogProps, \"kind\"> {}\n\nexport function Dialog(props: DialogProps): ReactElement {\n return <Review.Dialog {...props} kind=\"provisioning\" />;\n}\n\nexport interface ActionsProps extends Omit<Review.ActionsProps, \"kind\"> {}\n\n/** Approve and Decline for a plan already under review. */\nexport function Actions(props: ActionsProps): ReactElement | null {\n return <Review.Actions {...props} kind=\"provisioning\" />;\n}\n\nexport interface OutcomeProps extends Omit<Review.OutcomeProps, \"kind\"> {}\n\nexport function Outcome(props: OutcomeProps): ReactElement | null {\n return <Review.Outcome {...props} kind=\"provisioning\" />;\n}\n\nexport interface StatusProps extends Omit<Review.StatusProps, \"kind\"> {}\n\nexport function Status(props: StatusProps): ReactElement {\n return <Review.Status {...props} kind=\"provisioning\" />;\n}\n\nexport interface FlowProps extends Omit<RootProps, \"controller\"> {\n readonly domain: string;\n readonly onApplied?: (receipt: Receipt.Model) => void;\n readonly requirements: ReadonlyArray<DnsRecord.Model>;\n readonly trigger?: ReactNode;\n}\n\n/** Provisioning on its own: a trigger that plans, then the review dialog. */\nexport function Flow({ domain, onApplied, requirements, trigger, ...props }: FlowProps) {\n const controller = useController({\n domain,\n requirements,\n ...(onApplied === undefined ? {} : { onApplied }),\n });\n // The dialog carries its own outcome, so the one on the page is for after it closes.\n const [open, setOpen] = useState(false);\n return (\n <Root controller={controller} {...props}>\n <Dialog\n controller={controller}\n onOpenChange={setOpen}\n open={open}\n {...(trigger === undefined ? {} : { trigger })}\n />\n {open ? null : <Outcome controller={controller} />}\n </Root>\n );\n}\n","import { Popover as BasePopover } from \"@base-ui/react/popover\";\nimport { DnsRecord, type DomainKit } from \"domainkit\";\nimport type { Transport } from \"domainkit/client\";\nimport * as Data from \"effect/Data\";\nimport * as DateTime from \"effect/DateTime\";\nimport {\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n type ReactElement,\n type ReactNode,\n} from \"react\";\n\nimport type { PartProps } from \"./composition.tsx\";\nimport { usePart } from \"./composition.tsx\";\nimport { useDomainKit } from \"./domain-kit.tsx\";\nimport { Event } from \"./events.ts\";\nimport { useIcons } from \"./icons.tsx\";\nimport { outcome as describeOutcome } from \"./messages.ts\";\nimport * as OutcomeUi from \"./outcome.tsx\";\nimport { identity, requirementsKey, Status as RecordStatus } from \"./records.tsx\";\nimport { useRunner } from \"./task.ts\";\n\nexport type Readiness = Transport.Readiness;\nexport type HostEvidence = Readiness[\"host\"][number];\nexport type Requirement = Readiness[\"requirements\"][number];\nexport type Evidence = Requirement[\"evidence\"][number];\n\n/**\n * What the observer read back for the requirement's name, or `null` when it read nothing back at\n * all. Host evidence reports a status the host reached rather than values read off a name, and an\n * `unknown` observation is a lookup that never answered, which is not the same as finding nothing.\n */\nconst valuesOf = (evidence: Evidence): ReadonlyArray<string> | null =>\n evidence._tag === \"Host\" || evidence.status === \"unknown\" ? null : evidence.values;\n\n/**\n * Readiness rides on the state rather than a ref, so it can never outlive the render that\n * produced it: a controller pointed at a new domain has no readiness in the very first frame.\n */\nexport type State = Data.TaggedEnum<{\n Idle: {};\n Observing: { readonly readiness: Readiness | null };\n Observed: { readonly readiness: Readiness };\n Failure: { readonly error: DomainKit.Error; readonly readiness: Readiness | null };\n}>;\nexport const State = Data.taggedEnum<State>();\n\nconst readinessOf = (state: State): Readiness | null =>\n state._tag === \"Idle\" ? null : state.readiness;\n\nexport interface Controller {\n readonly state: State;\n /** The latest readiness, kept while a new observation runs. */\n readonly readiness: Readiness | null;\n readonly observe: () => void;\n /** Observe again after a failure. */\n readonly retry: () => void;\n /** Whether this controller re-observes at `nextCheckAt` while mounted. */\n readonly polling: boolean;\n}\n\nexport interface Options {\n readonly domain: string;\n /**\n * What to look for. Supplied requirements win over the attachment's latest provisioning receipt,\n * which is what lets a domain with no attachment be verified at all.\n */\n readonly requirements?: ReadonlyArray<DnsRecord.Model>;\n /** Re-observe at each `nextCheckAt` while mounted. Default true. */\n readonly polling?: boolean;\n}\n\n/** Observe once on mount, then follow the readiness's own `nextCheckAt` while polling is on. */\nexport function useController({ domain, polling = true, requirements }: Options): Controller {\n const { emit, revision, transport } = useDomainKit();\n const verification = transport.verification;\n const runner = useRunner();\n const [state, setState] = useState<State>(State.Idle());\n const timer = useRef<ReturnType<typeof setTimeout>>(undefined);\n\n // Requirements identify themselves by content, so a host writing the array inline does not\n // rebuild `observe` on every render and set the mount effect observing in a loop. The key covers\n // every field, because `policy` and `ttl` ride the wire and `policy` decides readiness.\n const signature = requirements === undefined ? null : requirementsKey(requirements);\n const requested = useMemo(\n () => (requirements === undefined ? undefined : { requirements }),\n [signature],\n );\n\n // Readiness belongs to the domain that was observed. Dropping it while rendering, rather than\n // in an effect, keeps the first frame for a new domain free of the previous one's evidence.\n const [observed, setObserved] = useState(domain);\n if (observed !== domain) {\n setObserved(domain);\n setState(State.Idle());\n }\n\n const observe = useCallback(() => {\n if (verification === undefined) return;\n clearTimeout(timer.current);\n setState((previous) => State.Observing({ readiness: readinessOf(previous) }));\n runner.run(\n requested === undefined\n ? verification.observe(domain)\n : verification.observe(domain, requested),\n {\n onFailure: (error) => {\n setState((previous) => State.Failure({ error, readiness: readinessOf(previous) }));\n emit(Event.Failed({ domain, error }));\n },\n onSuccess: (readiness) => setState(State.Observed({ readiness })),\n },\n );\n }, [domain, emit, requested, runner, verification]);\n\n useEffect(() => {\n observe();\n }, [observe, revision]);\n\n useEffect(() => {\n if (!polling || state._tag !== \"Observed\") return;\n const next = state.readiness.nextCheckAt;\n if (next === null) return;\n const delay = Math.max(0, DateTime.toEpochMillis(next) - Date.now());\n timer.current = setTimeout(observe, delay);\n return () => clearTimeout(timer.current);\n }, [observe, polling, state]);\n\n useEffect(() => () => clearTimeout(timer.current), []);\n\n return {\n observe,\n polling,\n readiness: readinessOf(state),\n retry: observe,\n state,\n };\n}\n\n// ---------------------------------------------------------------------------------------------\n// Parts\n// ---------------------------------------------------------------------------------------------\n\nexport interface RootState extends Record<string, unknown> {\n readonly status: State[\"_tag\"];\n}\n\nexport interface RootProps extends PartProps<\"div\", RootState> {\n readonly controller: Controller;\n}\n\nexport function Root({ controller, ...props }: RootProps): ReactElement {\n const overall = controller.readiness?.overall ?? null;\n return usePart(\n \"div\",\n props,\n { status: controller.state._tag },\n {\n \"data-domainkit-part\": \"verification-status\",\n \"data-overall\": overall ?? undefined,\n \"data-state\": controller.state._tag,\n },\n );\n}\n\nexport interface ObserveActionProps extends PartProps<\"button\", RootState> {\n readonly controller: Controller;\n}\n\nexport function ObserveAction({ controller, ...props }: ObserveActionProps): ReactElement {\n const { messages } = useDomainKit();\n const observing = controller.state._tag === \"Observing\";\n return usePart(\n \"button\",\n props,\n { status: controller.state._tag },\n {\n \"aria-busy\": observing,\n children: controller.readiness === null ? messages.checkDns : messages.checkAgain,\n \"data-domainkit-part\": \"observe-action\",\n \"data-loading\": observing ? \"\" : undefined,\n disabled: observing,\n onClick: controller.observe,\n type: \"button\",\n },\n );\n}\n\n/** Evidence carries no id; its source and position identify it within one requirement. */\nconst evidenceKey = (evidence: { readonly _tag: string }, index: number): string =>\n [evidence._tag, index].join(\"-\");\n\nexport interface EvidenceProps {\n readonly readiness: Readiness;\n}\n\n/**\n * Per-requirement readiness and, below it, the host's own evidence: an SES identity, a certificate,\n * anything DomainKit cannot observe but the host feeds in.\n */\nexport function Evidence({ readiness }: EvidenceProps): ReactElement {\n const { messages } = useDomainKit();\n const icons = useIcons();\n return (\n <div data-domainkit-part=\"observation-list\">\n {readiness.requirements.map((requirement) => {\n const settled = requirement.status === \"satisfied\";\n return (\n <section data-domainkit-part=\"observation-group\" key={identity(requirement.record)}>\n <div data-domainkit-part=\"observation-row\">\n <span data-domainkit-part=\"observation-record\">\n {messages.recordType(requirement.record)} {requirement.record.name}\n </span>\n <RecordStatus status={requirement.status} />\n </div>\n {settled ? null : (\n <p data-domainkit-part=\"observation-expected\">\n {messages.expectedValue(DnsRecord.data(requirement.record))}\n </p>\n )}\n <ul>\n {requirement.evidence.map((evidence, index) => {\n const values = settled ? null : valuesOf(evidence);\n return (\n <li data-domainkit-part=\"observation-source\" key={evidenceKey(evidence, index)}>\n {messages.evidenceSource(evidence)}\n {values === null ? null : (\n <span data-domainkit-part=\"observation-observed\">\n {values.length === 0\n ? messages.observedNothing\n : messages.observedValues(values)}\n </span>\n )}\n {evidence.detail === null ? null : (\n <p data-domainkit-part=\"observation-note\">{evidence.detail}</p>\n )}\n </li>\n );\n })}\n </ul>\n </section>\n );\n })}\n {readiness.host.length === 0 ? null : (\n <section data-domainkit-part=\"observation-group\" data-source=\"host\">\n <h3 data-domainkit-part=\"observation-source\">{messages.hostEvidence}</h3>\n <ul>\n {readiness.host.map((evidence, index) => (\n <li data-domainkit-part=\"host-evidence\" key={`${evidence.source}-${index}`}>\n <span aria-hidden=\"true\" data-icon=\"inline-start\">\n {evidence.status === \"ok\"\n ? icons.success\n : evidence.status === \"pending\"\n ? icons.pending\n : icons.failure}\n </span>\n <span data-domainkit-part=\"observation-record\">{evidence.label}</span>\n <span data-domainkit-part=\"record-status\" data-status={evidence.status}>\n {messages.hostEvidenceStatus(evidence.status)}\n </span>\n {evidence.detail === null ? null : (\n <p data-domainkit-part=\"observation-note\">{evidence.detail}</p>\n )}\n </li>\n ))}\n </ul>\n </section>\n )}\n </div>\n );\n}\n\nexport interface OutcomeProps extends OutcomeUi.RootProps {\n readonly controller: Controller;\n}\n\n/**\n * The last observation that failed. Observing reads the world rather than changing the domain, so\n * the retry stays even in read-only.\n */\nexport function Outcome({ children, controller, ...props }: OutcomeProps): ReactElement | null {\n const { messages } = useDomainKit();\n const state = controller.state;\n if (state._tag !== \"Failure\") return null;\n const words = describeOutcome(state.error, messages);\n return (\n <OutcomeUi.Provider\n value={{\n description: words.description ?? \"\",\n layout: props.layout ?? \"card\",\n retry: controller.retry,\n retryPart: \"verification-retry\",\n title: words.title,\n tone: \"danger\",\n }}\n >\n <OutcomeUi.Root {...props}>{children ?? <OutcomeUi.Composition />}</OutcomeUi.Root>\n </OutcomeUi.Provider>\n );\n}\n\nexport interface StatusProps extends Omit<RootProps, \"render\"> {\n /** Replace the popover surface with a panel of the host's own. */\n readonly render?: (props: { readonly open: boolean; readonly children: ReactNode }) => ReactNode;\n}\n\n/** The default verification slot: a button that observes, with the evidence behind it. */\nexport function Status({ controller, render, ...props }: StatusProps): ReactElement {\n const { colorScheme, messages, portalContainer, themeStyle } = useDomainKit();\n const readiness = controller.readiness;\n const body = (\n <>\n {controller.state._tag === \"Observing\" ? (\n <p data-domainkit-part=\"verification-progress\" role=\"status\">\n {messages.observing}\n </p>\n ) : null}\n {readiness === null ? (\n <p data-domainkit-part=\"verification-progress\">{messages.noEvidence}</p>\n ) : (\n <Evidence readiness={readiness} />\n )}\n <Outcome controller={controller} />\n </>\n );\n return (\n <Root controller={controller} {...props}>\n {render === undefined ? (\n <BasePopover.Root>\n <BasePopover.Trigger render={<ObserveAction controller={controller} />} />\n <BasePopover.Portal container={portalContainer}>\n <BasePopover.Positioner\n align=\"end\"\n data-domainkit-part=\"verification-positioner\"\n sideOffset={6}\n >\n <BasePopover.Popup\n aria-busy={controller.state._tag === \"Observing\"}\n aria-label={messages.checkDns}\n data-color-scheme={colorScheme}\n data-domainkit-part=\"verification-popover\"\n data-domainkit-root=\"\"\n style={themeStyle}\n >\n <BasePopover.Arrow data-domainkit-part=\"verification-arrow\" />\n {body}\n </BasePopover.Popup>\n </BasePopover.Positioner>\n </BasePopover.Portal>\n </BasePopover.Root>\n ) : (\n <>\n <ObserveAction controller={controller} />\n {render({ children: body, open: controller.state._tag !== \"Idle\" })}\n </>\n )}\n </Root>\n );\n}\n","import { Receipt, type DnsRecord } from \"domainkit\";\nimport { useCallback, useEffect, useRef, useState, type ReactElement, type ReactNode } from \"react\";\n\nimport type { PartProps } from \"./composition.tsx\";\nimport { usePart } from \"./composition.tsx\";\nimport * as Cleanup from \"./cleanup.tsx\";\nimport * as Connect from \"./connect.tsx\";\nimport { ReadOnly, useDomainKit, useReadOnly } from \"./domain-kit.tsx\";\nimport * as Provision from \"./provision.tsx\";\nimport * as Records from \"./records.tsx\";\nimport * as Verify from \"./verify.tsx\";\n\nexport interface RecordsSlotProps {\n readonly records: ReadonlyArray<DnsRecord.Model>;\n readonly readiness: Verify.Readiness | null;\n readonly controller: Verify.Controller;\n readonly domain: string;\n}\n\nexport interface VerificationSlotProps {\n readonly controller: Verify.Controller;\n readonly domain: string;\n}\n\nexport interface ActionsSlotProps {\n readonly connection: Connect.Controller;\n readonly provisioning: Provision.Controller;\n readonly cleanup: Cleanup.Controller;\n readonly domain: string;\n}\n\nexport interface ConnectionSlotProps {\n readonly controller: Connect.Controller;\n readonly domain: string;\n /** What the flow was told to offer when discovery names no host. */\n readonly connect: Connect.Invitation;\n}\n\n/**\n * Each slot replaces one part of the flow and keeps the rest. Every slot has a default, so\n * `<Domain.Flow domain requirements />` is complete on its own.\n */\nexport interface Slots {\n /** The requirements table. Defaults to `Records.Table` with readiness when there is any. */\n readonly records?: (props: RecordsSlotProps) => ReactNode;\n /** Defaults to `Verify.Status`. Rendered only when the transport declares `verification`. */\n readonly verification?: (props: VerificationSlotProps) => ReactNode;\n /** Defaults to Approve and Decline, plus cleanup when the transport declares it. */\n readonly actions?: (props: ActionsSlotProps) => ReactNode;\n /** Defaults to `Connect.Card` once connected and `Connect.Prompt` until then. */\n readonly connection?: (props: ConnectionSlotProps) => ReactNode;\n}\n\n/**\n * What DomainKit has to say about this domain, on the part's data attributes, in `className` and\n * `style` callbacks, and through `onState`. A host reads `connected` and `offering` to order its\n * own offers beside DomainKit's: an offer of its own competes while `offering` is true, and a\n * domain DomainKit holds needs none.\n */\nexport interface FlowState extends Record<string, unknown> {\n readonly connection: Connect.State[\"_tag\"];\n readonly provisioning: Provision.State[\"_tag\"];\n /**\n * DomainKit holds a connection for this domain, including while a command it started over that\n * connection is still running. `offering` is never true at the same time.\n */\n readonly connected: boolean;\n /** The connect surface has something to offer, so a host's own offer would compete with it. */\n readonly offering: boolean;\n /** Who holds the connection, or whose nameservers serve the zone. */\n readonly provider: string | null;\n /**\n * The apply receipt this domain's latest provisioning attempt produced, which is what cleanup\n * plans from. A host's own \"remove this domain\" surface offers cleanup only when there is one.\n */\n readonly receiptId: Receipt.ReceiptId | null;\n /** `receiptId !== null`: DomainKit applied records here and can prove which. */\n readonly applied: boolean;\n}\n\nexport interface FlowProps extends Omit<PartProps<\"div\", FlowState>, \"children\"> {\n readonly domain: string;\n readonly requirements: ReadonlyArray<DnsRecord.Model>;\n readonly slots?: Slots;\n readonly onApplied?: (receipt: Receipt.Model) => void;\n readonly onCleaned?: (receipt: Receipt.Model) => void;\n /**\n * Where an interactive provider flow returns the customer. Defaults to the page they started\n * from; pass `null` to let the server's `defaultReturnTo` decide.\n */\n readonly returnTo?: string | null;\n /** Render this domain's state without the controls that change it. Defaults to the root's. */\n readonly readOnly?: boolean;\n /**\n * Offer the connect dialog even when discovery names no host, for a host application that lets\n * a customer connect a provider the domain's nameservers do not point at, or `never` for a\n * domain the host has already settled another way. Defaults to `detected`.\n */\n readonly connect?: Connect.Invitation;\n /** Fires whenever what DomainKit has to say about this domain changes, and once on mount. */\n readonly onState?: (state: FlowState) => void;\n /**\n * `auto` plans and opens the review the moment a connection lands, so connecting and adding the\n * records is one pass rather than three. `manual` waits for the trigger.\n */\n readonly review?: Review;\n}\n\n/** Built from primitives alone, so the effect that announces it depends on exactly those. */\nconst flowState = (input: {\n readonly connected: boolean;\n readonly offering: boolean;\n readonly planning: Provision.State[\"_tag\"];\n readonly provider: string | null;\n readonly receipt: string | null;\n readonly status: Connect.State[\"_tag\"];\n}): FlowState => ({\n applied: input.receipt !== null,\n connected: input.connected,\n connection: input.status,\n offering: input.offering,\n provider: input.provider,\n provisioning: input.planning,\n receiptId: input.receipt === null ? null : Receipt.ReceiptId.make(input.receipt),\n});\n\n/** Whether the flow opens the plan itself once a connection lands, or waits to be asked. */\nexport type Review = \"auto\" | \"manual\";\n\ninterface DefaultConnectionProps extends ConnectionSlotProps {\n readonly onCleaned?: (receipt: Receipt.Model) => void;\n}\n\nfunction DefaultConnection({\n connect,\n controller,\n onCleaned,\n}: DefaultConnectionProps): ReactElement | null {\n const disconnected = controller.state._tag === \"Disconnected\";\n const host = Connect.hostProvider(controller);\n // No provider serves the zone, nothing is connected, and there is nothing to offer: DomainKit\n // has nothing to say about this domain, so it says nothing. A line here would sit above the\n // host's own offers and claim a place in an order it does not belong to. A host that wants the\n // sentence anyway renders `Connect.Status` itself.\n if (disconnected && host === null && !Connect.offering(controller, connect)) return null;\n // The prompt already names who serves the zone, so the status line is for everything else:\n // what the connection is doing, what a read-only customer sees where a trigger would be, and a\n // domain whose invitation the host turned off.\n const stated = disconnected && host !== null && Connect.offering(controller, connect);\n return Connect.holdsConnection(controller) ? (\n <Connect.Card controller={controller} {...(onCleaned === undefined ? {} : { onCleaned })} />\n ) : (\n <>\n {stated ? null : <Connect.Status controller={controller} />}\n <Connect.Prompt connect={connect} controller={controller} />\n {/* A failure the method already answers beside the field announces once, not twice. */}\n {Connect.answeredInPlace(controller) ? null : <Connect.Outcome controller={controller} />}\n </>\n );\n}\n\n/**\n * The page carries the trigger and, once an attempt ends, its outcome. What the plan will do,\n * whether to approve it, and how the apply is going all belong to the dialog the trigger opens:\n * approving beside no operations is a decision taken without the thing it is about. Removing\n * records is not here either — it is the option inside the disconnect dialog — and `Cleanup.Flow`\n * stays exported for a host that wants the standalone surface.\n */\ninterface DefaultActionsProps extends ActionsSlotProps {\n readonly open: boolean;\n readonly onOpenChange: (open: boolean) => void;\n}\n\nfunction DefaultActions({\n connection,\n onOpenChange,\n open,\n provisioning,\n}: DefaultActionsProps): ReactElement | null {\n const readOnly = useReadOnly();\n const { capabilities } = useDomainKit();\n const connected = connection.state._tag === \"Connected\";\n // Every control here starts a write; the state a read-only customer may see is rendered above.\n if (readOnly) return null;\n if (!capabilities.includes(\"provisioning\") || !connected) return null;\n return (\n <>\n <Provision.Dialog controller={provisioning} onOpenChange={onOpenChange} open={open} />\n {open ? null : <Provision.Outcome controller={provisioning} />}\n </>\n );\n}\n\n/**\n * The whole lifecycle for one domain: connect, review, apply, observe, clean up. The flow renders\n * only what the transport declares, and every part of it is a slot with a default. It adds no\n * layout containers of its own, so a host's grid can place the slot output directly.\n */\nexport function Flow({\n connect = \"detected\",\n domain,\n onApplied,\n onCleaned,\n onState,\n readOnly,\n requirements,\n returnTo,\n review = \"auto\",\n slots = {},\n ...props\n}: FlowProps): ReactElement {\n const { capabilities } = useDomainKit();\n const inherited = useReadOnly();\n const connection = Connect.useController({\n domain,\n ...(returnTo === undefined ? {} : { returnTo }),\n });\n const refresh = connection.refresh;\n const provisioning = Provision.useController({\n domain,\n onApplied: useCallback(\n (receipt: Receipt.Model) => {\n refresh();\n onApplied?.(receipt);\n },\n [onApplied, refresh],\n ),\n requirements,\n });\n const cleanup = Cleanup.useController({\n domain,\n onCleaned: useCallback(\n (receipt: Receipt.Model) => {\n refresh();\n onCleaned?.(receipt);\n },\n [onCleaned, refresh],\n ),\n ...(connection.snapshot?.lastReceiptId == null\n ? {}\n : { receiptId: Receipt.ReceiptId.make(connection.snapshot.lastReceiptId) }),\n });\n // The flow knows what it asked for, so a domain with no attachment can still be verified.\n const verification = Verify.useController({ domain, requirements });\n const readiness = verification.readiness;\n const status = connection.state._tag;\n const planning = provisioning.state._tag;\n // Connecting is the customer saying yes to the records; the plan is what those records are, so\n // it opens itself rather than waiting behind another click. `established` only ever grows, so\n // this fires once per connection that landed and never again on a re-render or a reload.\n const [reviewing, setReviewing] = useState(false);\n // A flow pointed at a new domain drops the review with everything else it was holding, while\n // rendering rather than an effect later, so no frame shows one domain's plan over another's.\n const [reviewed, setReviewed] = useState(domain);\n if (reviewed !== domain) {\n setReviewed(domain);\n setReviewing(false);\n }\n const established = connection.established;\n const answered = useRef(established);\n const buildPlan = provisioning.plan;\n useEffect(() => {\n if (answered.current === established) return;\n answered.current = established;\n if (review === \"manual\") return;\n buildPlan();\n setReviewing(true);\n }, [buildPlan, established, review]);\n // The same predicate the surface renders on, so the state a host reads and the surface a\n // customer sees never disagree, including while a disconnect is in flight.\n const connected = Connect.holdsConnection(connection);\n const offering = Connect.offering(connection, connect);\n const provider = connection.snapshot?.provider ?? Connect.hostProvider(connection)?.id ?? null;\n const receipt = connection.snapshot?.lastReceiptId ?? null;\n const state = flowState({ connected, offering, planning, provider, receipt, status });\n // The callback rides a ref so a host writing it inline does not re-announce every render.\n const announce = useRef(onState);\n useEffect(() => {\n announce.current = onState;\n });\n useEffect(() => {\n announce.current?.(flowState({ connected, offering, planning, provider, receipt, status }));\n }, [connected, offering, planning, provider, receipt, status]);\n return usePart(\"div\", props, state, {\n children: (\n <ReadOnly value={readOnly ?? inherited}>\n {!capabilities.includes(\"connection\") ? null : slots.connection === undefined ? (\n <DefaultConnection\n connect={connect}\n controller={connection}\n domain={domain}\n {...(onCleaned === undefined ? {} : { onCleaned })}\n />\n ) : (\n slots.connection({ connect, controller: connection, domain })\n )}\n {slots.records === undefined ? (\n <Records.Table readiness={readiness} records={requirements} />\n ) : (\n slots.records({ controller: verification, domain, readiness, records: requirements })\n )}\n {!capabilities.includes(\"verification\") ? null : slots.verification === undefined ? (\n <Verify.Status controller={verification} />\n ) : (\n slots.verification({ controller: verification, domain })\n )}\n {slots.actions === undefined ? (\n <DefaultActions\n cleanup={cleanup}\n connection={connection}\n domain={domain}\n onOpenChange={setReviewing}\n open={reviewing}\n provisioning={provisioning}\n />\n ) : (\n slots.actions({ cleanup, connection, domain, provisioning })\n )}\n </ReadOnly>\n ),\n \"data-domainkit-part\": \"domain-flow\",\n \"data-domain\": domain,\n });\n}\n","/**\n * The fake transport `@domainkit/react` tests render against: an in-memory `domainkit/server`\n * with memory storage and a fake provider, recording every call.\n */\nimport { Testing } from \"domainkit/testing\";\n\nexport const transport = Testing.transport;\nexport type RecordedCall = Testing.RecordedCall;\nexport type RecordingTransport = Testing.RecordingTransport;\nexport type TransportOptions = Testing.TransportOptions;\n","import type { DomainKit } from \"domainkit\";\nimport * as Data from \"effect/Data\";\n\n/**\n * The failed member every controller state shares. It carries the `DomainKit.Error` itself, so a\n * host reads `error.reason`, `error.category`, and `error.isRetryable` instead of parsing text.\n */\nexport type Failure = Data.TaggedEnum<{\n Failure: { readonly error: DomainKit.Error };\n}>;\nexport const Failure = Data.taggedEnum<Failure>();\n\n/** A defect that escaped the transport, in the shape the rest of the UI already handles. */\nexport const isFailure = (state: { readonly _tag: string }): state is Failure =>\n state._tag === \"Failure\";\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.mjs","names":["mergeMessages","State","useController","currentUrl","State","useController","useController","Connect.useController","Verify.useController","Provision.useController","Cleanup.useController","Connect.holdsConnection","offering","Connect.offering","Connect.hostProvider","Provision.pendingPlan"],"sources":["../src/messages.ts","../src/domain-kit.tsx","../src/events.ts","../src/task.ts","../src/attempt.ts","../src/cleanup.ts","../src/domain-field.ts","../src/connect.ts","../src/records.ts","../src/provision.ts","../src/verify.ts","../src/domain.ts","../src/outcome.ts","../src/testing.ts","../src/failure.ts"],"sourcesContent":["/**\n * Every string the package can put on screen. Nothing renders a `_tag`, a reason name, or a\n * status literal directly: each one arrives here first, so a host translates the whole surface by\n * passing `messages` to `DomainKit.Root`.\n */\nimport type { DnsRecord, DomainKit, Plan, Reason, Receipt, Storage } from \"domainkit\";\n\nexport interface Catalog {\n // Actions\n readonly connect: string;\n /** The token method's button, which carries the verb rather than the method's own label. */\n readonly methodToken: string;\n readonly methodOAuth: (provider: string) => string;\n readonly methodIntegration: (provider: string) => string;\n readonly disconnect: string;\n readonly detach: string;\n readonly cancel: string;\n readonly close: string;\n readonly retry: string;\n readonly approve: string;\n /** The provisioning dialog's primary action: what it adds, and how many. */\n readonly addRecords: (count: number) => string;\n readonly decline: string;\n /** Why the primary action is unavailable: every operation the plan holds is blocked. */\n readonly everyRecordConflicts: string;\n readonly reviewChanges: string;\n readonly cleanUp: string;\n readonly checkDns: string;\n readonly checkAgain: string;\n readonly moreActions: string;\n /** Reveals the fields a provider does not need, such as an account id. */\n readonly moreOptions: string;\n /** Reveals the providers the dialog narrowed away. */\n readonly useAnotherProvider: string;\n /** Opens the token form where a provider also offers a method the customer clicks through. */\n readonly useTokenInstead: string;\n /** Returns from one method's form to the provider's methods. */\n readonly back: string;\n /** The connected card's identity: who holds the connection and which account it reaches. */\n readonly connectedAccount: (provider: string, account: string) => string;\n /** How many records this domain's apply receipt proves DomainKit added. */\n readonly recordsAdded: (count: number) => string;\n readonly needsReconnect: string;\n /** The disconnect dialog's scope question, when the connection serves other domains too. */\n readonly disconnectScope: string;\n readonly disconnectThisDomain: string;\n readonly disconnectEveryDomain: (count: number) => string;\n readonly copy: string;\n readonly copied: string;\n readonly copyZone: string;\n readonly download: string;\n readonly useConnection: (label: string) => string;\n readonly chooseZone: string;\n /** The domain field's listbox, named for a customer reading it with assistive technology. */\n readonly zoneSuggestions: string;\n /** Which account a typed domain's records will go to. */\n readonly recordsGoTo: (provider: string, account: string) => string;\n /** A typed domain no connected account reaches; the customer adds the records by hand. */\n readonly notInConnectedAccount: string;\n /** A held connection whose credential the provider turned down. */\n readonly reconnectAccount: (account: string) => string;\n readonly getToken: string;\n\n // Progress\n readonly loading: string;\n readonly connecting: string;\n readonly redirecting: string;\n readonly detaching: string;\n readonly disconnecting: string;\n readonly planning: string;\n readonly approving: string;\n readonly applying: string;\n readonly rejecting: string;\n readonly planningCleanup: string;\n readonly cleaning: string;\n readonly observing: string;\n\n // Connection\n readonly connectTitle: (provider: string) => string;\n /** The dialog heading, and the trigger, when no provider is named yet. */\n readonly connectAnyTitle: string;\n /** What the disconnected prompt says about the provider whose nameservers serve the domain. */\n readonly hostDetected: (provider: string) => string;\n readonly connectDescription: (domain: string) => string;\n readonly connectedTo: (provider: string) => string;\n /** Shown where a connect control would be when the customer may not connect. */\n readonly notConnected: string;\n /**\n * What a customer who may read the domain but not write to it is told in place of the connect\n * control, so the surface explains the gap rather than leaving an empty row.\n */\n readonly administratorConnects: (provider: string) => string;\n readonly reconnectRequired: (provider: string) => string;\n readonly disconnectTitle: (provider: string) => string;\n /**\n * What disconnecting means, in the present. The default names DomainKit as what stops managing\n * the records; a host application overrides the key to name itself.\n */\n readonly disconnectConsent: (domain: string, provider: string) => string;\n /**\n * The option inside the disconnect dialog, over the records it would remove. Only this domain's\n * apply receipt proves what DomainKit created, so the words say which records go.\n */\n readonly disconnectWithCleanup: (count: number) => string;\n /** What the listed records do when that option is off. */\n readonly disconnectKeepsRecords: (provider: string) => string;\n readonly detachConsent: string;\n readonly detached: string;\n readonly reusableConnections: string;\n readonly authenticationAlternative: string;\n readonly discoveredConnection: (label: string) => string;\n readonly discoveryAmbiguous: string;\n readonly discoveryNotFound: (nameservers: ReadonlyArray<string>) => string;\n readonly noProviders: string;\n readonly fieldLabel: (name: string) => string;\n readonly optionalField: string;\n\n // Plan review\n readonly planTitle: string;\n readonly planConsent: string;\n readonly cleanupTitle: string;\n readonly cleanupConsent: string;\n readonly noChanges: string;\n readonly planExpires: (at: string) => string;\n readonly declinedBy: (actor: string) => string;\n readonly declineReason: (reason: string) => string;\n readonly operation: (operation: Plan.Operation) => string;\n readonly conflictReason: (reason: Plan.Conflict[\"reason\"]) => string;\n /** What to do about a conflict, in the row that reports it. */\n readonly conflictAdvice: (reason: Plan.Conflict[\"reason\"]) => string;\n /** What a pending plan holds for one row: a write, a record already there, or a blocker. */\n readonly planStatus: (operation: Plan.Operation) => string;\n readonly attemptStatus: (status: Storage.AttemptStatus) => string;\n\n // Records\n readonly recordsCaption: (domain: string) => string;\n readonly headingType: string;\n readonly headingName: string;\n readonly headingValue: string;\n readonly headingStatus: string;\n readonly headingPurpose: string;\n readonly priority: (priority: number) => string;\n readonly ttl: (seconds: number) => string;\n readonly recordType: (record: DnsRecord.Observed) => string;\n\n // Receipts\n readonly applied: (receipt: Receipt.Model) => string;\n readonly cleaned: (receipt: Receipt.Model) => string;\n readonly partiallyAppliedTitle: string;\n readonly partiallyApplied: string;\n readonly partiallyCleanedTitle: string;\n readonly partiallyCleaned: string;\n readonly receiptOutcome: (outcome: Receipt.Outcome) => string;\n readonly skippedReason: (reason: Receipt.Skipped[\"reason\"]) => string;\n\n // Verification\n readonly requirementStatus: (status: Storage.RequirementStatus) => string;\n readonly overall: (overall: Storage.Overall) => string;\n readonly evidenceSource: (evidence: EvidenceLike) => string;\n readonly hostEvidenceStatus: (status: \"failed\" | \"ok\" | \"pending\") => string;\n /** What the requirement asks for, shown when an observation disagrees with it. */\n readonly expectedValue: (value: string) => string;\n /** What one observer actually read back for that name. */\n readonly observedValues: (values: ReadonlyArray<string>) => string;\n readonly observedNothing: string;\n readonly checkedAt: (at: string) => string;\n readonly nextCheckAt: (at: string) => string;\n readonly hostEvidence: string;\n readonly noEvidence: string;\n\n // Failures, rendered from the error's reason: a heading and the sentence under it\n readonly invalidInput: (reason: Reason.InvalidInput, context: OutcomeContext) => Outcome;\n readonly unauthenticated: (reason: Reason.Unauthenticated, context: OutcomeContext) => Outcome;\n readonly forbidden: (reason: Reason.Forbidden, context: OutcomeContext) => Outcome;\n readonly notFound: (reason: Reason.NotFound, context: OutcomeContext) => Outcome;\n readonly conflict: (reason: Reason.Conflict, context: OutcomeContext) => Outcome;\n readonly stale: (reason: Reason.Stale, context: OutcomeContext) => Outcome;\n readonly expired: (reason: Reason.Expired, context: OutcomeContext) => Outcome;\n readonly busy: (reason: Reason.Busy, context: OutcomeContext) => Outcome;\n readonly providerRejected: (reason: Reason.ProviderRejected, context: OutcomeContext) => Outcome;\n readonly providerUnavailable: (\n reason: Reason.ProviderUnavailable,\n context: OutcomeContext,\n ) => Outcome;\n readonly providerConflict: (reason: Reason.ProviderConflict, context: OutcomeContext) => Outcome;\n readonly unsupported: (reason: Reason.Unsupported, context: OutcomeContext) => Outcome;\n readonly reconnect: (reason: Reason.Reconnect, context: OutcomeContext) => Outcome;\n readonly storageFailed: (reason: Reason.StorageFailed, context: OutcomeContext) => Outcome;\n readonly cryptoFailed: (reason: Reason.CryptoFailed, context: OutcomeContext) => Outcome;\n readonly resolverFailed: (reason: Reason.ResolverFailed, context: OutcomeContext) => Outcome;\n}\n\n/** What an outcome says: a heading the customer reads first, then what to do about it. */\nexport interface Outcome {\n readonly title: string;\n /** What to do about it. Absent where the title has already said the whole of it. */\n readonly description?: string;\n}\n\n/**\n * What the flow was doing when it failed. The reason alone cannot name the provider a customer\n * typed a token for, so the part that renders the outcome supplies it.\n */\nexport interface OutcomeContext {\n /** The provider's display name, when the flow knows which one the customer acted on. */\n readonly provider?: string;\n readonly domain?: string;\n}\n\n/** The evidence shapes `Verify` produces, structurally, so the catalog needs no service import. */\nexport type EvidenceLike =\n | { readonly _tag: \"Host\"; readonly source: string; readonly label: string }\n | { readonly _tag: \"Provider\"; readonly provider: string }\n | { readonly _tag: \"PublicDns\"; readonly resolver: string };\n\nconst entity: Readonly<Record<Reason.NotFound[\"entity\"], string>> = {\n approval: \"approval\",\n attachment: \"domain attachment\",\n authorization: \"provider authorization\",\n connection: \"provider connection\",\n continuation: \"sign-in attempt\",\n plan: \"plan\",\n provider: \"provider\",\n receipt: \"receipt\",\n record: \"DNS record\",\n zone: \"DNS zone\",\n};\n\nconst expiredEntity: Readonly<Record<Reason.Expired[\"entity\"], string>> = {\n approval: \"approval\",\n continuation: \"sign-in attempt\",\n credential: \"provider credential\",\n plan: \"plan\",\n};\n\nconst recordTypes: Readonly<Record<Exclude<DnsRecord.Observed[\"_tag\"], \"Opaque\">, string>> = {\n A: \"A\",\n AAAA: \"AAAA\",\n CAA: \"CAA\",\n CNAME: \"CNAME\",\n MX: \"MX\",\n NS: \"NS\",\n SRV: \"SRV\",\n TXT: \"TXT\",\n};\n\n/** The provider the customer acted on, or a neutral stand-in when the flow does not know it. */\nconst named = (provider: string | undefined): string => provider ?? \"The provider\";\n\n/** The domain the failure is about, or a neutral stand-in. */\nconst where = (domain: string | undefined): string => domain ?? \"this domain\";\n\n/** `accountId` reads as \"Account id\" until a host names the field itself. */\nconst humanize = (name: string): string => {\n const spaced = name\n .replaceAll(/([a-z0-9])([A-Z])/g, \"$1 $2\")\n .replaceAll(/[_-]+/g, \" \")\n .trim();\n return spaced.charAt(0).toUpperCase() + spaced.slice(1).toLowerCase();\n};\n\nexport const english: Catalog = {\n connect: \"Connect\",\n methodToken: \"Connect with an API token\",\n methodOAuth: (provider) => `Continue with ${provider}`,\n methodIntegration: (provider) => `Install the ${provider} integration`,\n disconnect: \"Disconnect\",\n detach: \"Detach domain\",\n cancel: \"Cancel\",\n close: \"Close\",\n retry: \"Try again\",\n approve: \"Approve\",\n addRecords: (count) => (count === 1 ? \"Add 1 record\" : `Add ${count} records`),\n decline: \"Decline\",\n everyRecordConflicts: \"Resolve the records above at your provider, then check again.\",\n reviewChanges: \"Review changes\",\n cleanUp: \"Remove records\",\n checkDns: \"Check DNS\",\n checkAgain: \"Check again\",\n moreActions: \"More actions\",\n moreOptions: \"Add an account id\",\n useAnotherProvider: \"Use a different provider\",\n useTokenInstead: \"Use an API token instead\",\n back: \"Back\",\n connectedAccount: (provider, account) => `${provider} · ${account}`,\n recordsAdded: (count) => (count === 1 ? \"1 added\" : `${count} added`),\n needsReconnect: \"Needs reconnecting\",\n disconnectScope: \"This connection serves other domains.\",\n disconnectThisDomain: \"Only this domain\",\n disconnectEveryDomain: (count) => `All ${count} domains`,\n copy: \"Copy\",\n copied: \"Copied\",\n copyZone: \"Copy zone file\",\n download: \"Download\",\n useConnection: (label) => `Use ${label}`,\n chooseZone: \"Choose the zone that serves this domain\",\n zoneSuggestions: \"Zones your connected accounts serve\",\n recordsGoTo: (provider, account) => `Records go to ${provider} through ${account}.`,\n notInConnectedAccount: \"Not in a connected account.\",\n reconnectAccount: (account) => `Reconnect ${account}`,\n getToken: \"Where do I find this?\",\n\n loading: \"Loading…\",\n connecting: \"Connecting…\",\n redirecting: \"Opening the provider…\",\n detaching: \"Detaching…\",\n disconnecting: \"Disconnecting…\",\n planning: \"Preparing DNS changes…\",\n approving: \"Approving…\",\n applying: \"Adding records…\",\n rejecting: \"Declining…\",\n planningCleanup: \"Preparing cleanup…\",\n cleaning: \"Removing records…\",\n observing: \"Checking DNS…\",\n\n connectTitle: (provider) => `Connect ${provider}`,\n connectAnyTitle: \"Connect a DNS provider\",\n hostDetected: (provider) => `${provider} DNS detected`,\n connectDescription: (domain) => `Authorize DNS changes for ${domain}.`,\n connectedTo: (provider) => `${provider} connected`,\n notConnected: \"No DNS provider is connected.\",\n administratorConnects: (provider) => `An administrator can connect ${provider}`,\n reconnectRequired: (provider) => `${provider} needs to be reconnected`,\n disconnectTitle: (provider) => `Disconnect ${provider}?`,\n disconnectConsent: (domain, provider) =>\n `DomainKit stops managing DNS for ${domain} through ${provider}.`,\n disconnectWithCleanup: (count) =>\n count === 1\n ? \"Remove the 1 record DomainKit added\"\n : `Remove the ${count} records DomainKit added`,\n disconnectKeepsRecords: (provider) => `Records stay in ${provider}.`,\n detachConsent: \"This domain is detached from the provider. Existing DNS records are preserved.\",\n detached: \"Domain detached. DNS records were preserved.\",\n reusableConnections: \"Connections you already have\",\n authenticationAlternative: \"or\",\n discoveredConnection: (label) => `${label} already serves this domain`,\n discoveryAmbiguous: \"More than one connection can serve this domain. Pick one.\",\n discoveryNotFound: (nameservers) =>\n nameservers.length === 0\n ? \"No connected provider serves this domain yet.\"\n : `No connected provider serves this domain. Its nameservers are ${nameservers.join(\", \")}.`,\n noProviders: \"No DNS providers are available.\",\n fieldLabel: humanize,\n optionalField: \"optional\",\n\n planTitle: \"Review DNS changes\",\n planConsent: \"Review the exact DNS operations before approving this plan.\",\n cleanupTitle: \"Review the records to remove\",\n cleanupConsent: \"Only records the apply receipt proves DomainKit created will be deleted.\",\n noChanges: \"No changes needed\",\n planExpires: (at) => `This plan expires at ${at}.`,\n declinedBy: (actor) => `Declined by ${actor}. Build a new plan to continue.`,\n declineReason: (reason) => `Reason: ${reason}`,\n operation: (operation) => {\n switch (operation._tag) {\n case \"Create\":\n return \"Add\";\n case \"Noop\":\n return \"Already in place\";\n case \"Delete\":\n return \"Remove\";\n case \"Conflict\":\n return \"Blocked\";\n }\n },\n conflictReason: (reason) => {\n switch (reason) {\n case \"exclusive-name\":\n return \"Another record already owns this name.\";\n case \"cname-collision\":\n return \"A CNAME cannot share a name with other records.\";\n case \"value-mismatch\":\n return \"A record with this name holds a different value.\";\n case \"opaque\":\n return \"A record here uses a form DomainKit will not overwrite.\";\n case \"missing\":\n return \"The record this plan expected is gone.\";\n }\n },\n conflictAdvice: (reason) => {\n switch (reason) {\n case \"exclusive-name\":\n return \"Remove the record on that name at your provider, then check again.\";\n case \"cname-collision\":\n return \"Remove the other records on that name at your provider, then check again.\";\n case \"value-mismatch\":\n return \"Point that record at this value at your provider, or remove it and check again.\";\n case \"opaque\":\n return \"Remove that record at your provider, then check again.\";\n case \"missing\":\n return \"Check again to build a plan from what is there now.\";\n }\n },\n planStatus: (operation) => {\n switch (operation._tag) {\n case \"Create\":\n return \"Will add\";\n case \"Noop\":\n return \"Already there\";\n case \"Delete\":\n return \"Will remove\";\n case \"Conflict\":\n return \"In the way\";\n }\n },\n attemptStatus: (status) => {\n switch (status) {\n case \"planned\":\n return \"Awaiting review\";\n case \"approved\":\n return \"Approved\";\n case \"applying\":\n return \"Applying\";\n case \"complete\":\n return \"Applied\";\n case \"partial\":\n return \"Partly applied\";\n case \"failed\":\n return \"Failed\";\n case \"expired\":\n return \"Expired\";\n case \"rejected\":\n return \"Declined\";\n }\n },\n\n recordsCaption: (domain) => `DNS records for ${domain}`,\n headingType: \"Type\",\n headingName: \"Name\",\n headingValue: \"Value\",\n headingStatus: \"Status\",\n headingPurpose: \"Purpose\",\n priority: (priority) => `Priority ${priority}`,\n ttl: (seconds) => `TTL ${seconds}s`,\n recordType: (record) => (record._tag === \"Opaque\" ? record.type : recordTypes[record._tag]),\n\n applied: (receipt) =>\n receipt.status === \"complete\" ? \"DNS records added.\" : \"Some DNS records were not added.\",\n cleaned: (receipt) =>\n receipt.status === \"complete\" ? \"DNS records removed.\" : \"Some DNS records were not removed.\",\n partiallyAppliedTitle: \"Some DNS changes did not land\",\n partiallyApplied: \"Review what applied, then retry. Retrying is safe.\",\n partiallyCleanedTitle: \"Some DNS records are still there\",\n partiallyCleaned: \"Review what is left, then retry. Retrying is safe.\",\n receiptOutcome: (outcome) => {\n switch (outcome._tag) {\n case \"Applied\":\n return \"Done\";\n case \"Skipped\":\n return \"Skipped\";\n case \"Failed\":\n return outcome.message;\n }\n },\n skippedReason: (reason) => {\n switch (reason) {\n case \"noop\":\n return \"The record was already in place.\";\n case \"not-approved\":\n return \"The approval left this operation out.\";\n case \"not-attempted\":\n return \"An earlier operation failed before this one ran.\";\n }\n },\n\n requirementStatus: (status) => {\n switch (status) {\n case \"satisfied\":\n return \"Found\";\n case \"missing\":\n return \"Missing\";\n case \"mismatch\":\n return \"Different value\";\n case \"unknown\":\n return \"Not checked\";\n }\n },\n overall: (overall) => {\n switch (overall) {\n case \"ready\":\n return \"Ready\";\n case \"pending\":\n return \"Pending\";\n case \"failed\":\n return \"Failed\";\n }\n },\n evidenceSource: (evidence) => {\n switch (evidence._tag) {\n case \"Host\":\n return evidence.label;\n case \"Provider\":\n return `${evidence.provider} records`;\n case \"PublicDns\":\n return `Public DNS via ${evidence.resolver}`;\n }\n },\n hostEvidenceStatus: (status) => {\n switch (status) {\n case \"ok\":\n return \"Ready\";\n case \"pending\":\n return \"Pending\";\n case \"failed\":\n return \"Failed\";\n }\n },\n expectedValue: (value) => `Expected ${value}`,\n observedValues: (values) => `Found ${values.join(\", \")}`,\n observedNothing: \"Found nothing\",\n checkedAt: (at) => `Checked ${at}`,\n nextCheckAt: (at) => `Next check ${at}`,\n hostEvidence: \"Other checks\",\n noEvidence: \"Nothing has been checked yet.\",\n\n invalidInput: (reason) => ({\n description: reason.message,\n title:\n reason.field === undefined\n ? \"Check what you entered\"\n : `Check the ${humanize(reason.field).toLowerCase()}`,\n }),\n // The dialog's heading already names the provider, so the outcome answers about the credential\n // and nothing else. A longer title wraps in the column beside the retry, and a second line under\n // it repeats what the title said.\n unauthenticated: () => ({\n title: \"Token not accepted\",\n }),\n forbidden: (_reason, context) => ({\n description: `The connection needs permission to edit DNS for ${where(context.domain)}.`,\n title: \"This connection can't change DNS here\",\n }),\n notFound: (reason) => ({\n description: \"Reload the page and start this step again.\",\n title: `That ${entity[reason.entity]} no longer exists`,\n }),\n conflict: (reason) => ({\n description: \"Review what the zone already holds, then build a new plan.\",\n title:\n reason.operations.length === 1\n ? \"A record is in the way\"\n : `${reason.operations.length} records are in the way`,\n }),\n stale: () => ({\n description: \"Review the new plan before you apply it.\",\n title: \"The zone changed since you reviewed\",\n }),\n expired: (reason) => ({\n description: \"Start this step again.\",\n title: `That ${expiredEntity[reason.entity]} expired`,\n }),\n busy: () => ({\n description: \"Wait for it to finish, then try again.\",\n title: \"Another change is running\",\n }),\n providerRejected: (reason, context) => ({\n description: reason.message,\n title: `${named(context.provider ?? reason.provider)} refused the change`,\n }),\n providerUnavailable: (reason, context) => ({\n description: \"Nothing changed. Try again in a minute.\",\n title: `${named(context.provider ?? reason.provider)} isn't responding`,\n }),\n providerConflict: (reason, context) => ({\n description: \"Remove or rename that record at the provider, then try again.\",\n title: `${named(context.provider ?? reason.provider)} already holds a conflicting record`,\n }),\n unsupported: (reason, context) => ({\n description: \"Nothing changed. This step needs a provider that can do it.\",\n title: `${named(context.provider ?? reason.provider)} cannot ${reason.operation}`,\n }),\n reconnect: (reason, context) => ({\n description: \"The stored credential no longer works. Connect again to continue.\",\n title: `Reconnect ${named(context.provider ?? reason.provider)}`,\n }),\n storageFailed: () => ({\n description: \"Nothing changed. Try again.\",\n title: \"The change could not be saved\",\n }),\n cryptoFailed: () => ({\n description: \"Connect the provider again to replace it.\",\n title: \"A stored credential could not be read\",\n }),\n resolverFailed: (reason) => ({\n description: \"The lookup failed, which says nothing about your DNS. Try again in a moment.\",\n title: `DNS lookups through ${reason.resolver} failed`,\n }),\n};\n\nexport const merge = (overrides: Partial<Catalog> = {}): Catalog => ({ ...english, ...overrides });\n\n/** The title and description for a failure, chosen by the error's reason. */\nexport const outcome = (\n error: DomainKit.Error,\n catalog: Catalog,\n context: OutcomeContext = {},\n): Outcome => {\n const reason = error.reason;\n switch (reason._tag) {\n case \"InvalidInput\":\n return catalog.invalidInput(reason, context);\n case \"Unauthenticated\":\n return catalog.unauthenticated(reason, context);\n case \"Forbidden\":\n return catalog.forbidden(reason, context);\n case \"NotFound\":\n return catalog.notFound(reason, context);\n case \"Conflict\":\n return catalog.conflict(reason, context);\n case \"Stale\":\n return catalog.stale(reason, context);\n case \"Expired\":\n return catalog.expired(reason, context);\n case \"Busy\":\n return catalog.busy(reason, context);\n case \"ProviderRejected\":\n return catalog.providerRejected(reason, context);\n case \"ProviderUnavailable\":\n return catalog.providerUnavailable(reason, context);\n case \"ProviderConflict\":\n return catalog.providerConflict(reason, context);\n case \"Unsupported\":\n return catalog.unsupported(reason, context);\n case \"Reconnect\":\n return catalog.reconnect(reason, context);\n case \"StorageFailed\":\n return catalog.storageFailed(reason, context);\n case \"CryptoFailed\":\n return catalog.cryptoFailed(reason, context);\n case \"ResolverFailed\":\n return catalog.resolverFailed(reason, context);\n }\n};\n\n/** The same failure as one sentence, for a host that renders text rather than a card. */\nexport const failure = (\n error: DomainKit.Error,\n catalog: Catalog,\n context: OutcomeContext = {},\n): string => {\n const { description, title } = outcome(error, catalog, context);\n return description === undefined ? `${title}.` : `${title}. ${description}`;\n};\n","import { Transport } from \"domainkit/client\";\nimport * as Effect from \"effect/Effect\";\nimport {\n createContext,\n useCallback,\n useContext,\n useLayoutEffect,\n useMemo,\n useRef,\n type ReactElement,\n type ReactNode,\n} from \"react\";\n\nimport type { Listener } from \"./events.ts\";\nimport type { Catalog } from \"./messages.ts\";\nimport { merge as mergeMessages } from \"./messages.ts\";\n\nexport interface RootProps {\n readonly children: ReactNode;\n readonly messages?: Partial<Catalog>;\n /** Where an interactive provider flow sends the customer. Defaults to `window.location`. */\n readonly navigate?: (url: string) => void;\n readonly onEvent?: Listener;\n /**\n * Report the domain's state without the controls that change it, for a customer who may read\n * the domain but not write to it. Capability gating already hides a group the transport does\n * not declare; this covers authorization the transport cannot express, such as a member of an\n * organisation. Every flow carries it on `FlowState.readOnly`, so a surface can explain it.\n */\n readonly readOnly?: boolean;\n /** Bump to re-inspect every mounted domain after a change the UI did not make. */\n readonly revision?: number;\n /** The transport, by value. Rebuilding it inline on every render does not restart controllers. */\n readonly transport: Transport.Interface;\n}\n\ninterface ContextValue {\n readonly capabilities: ReadonlyArray<Transport.Capability>;\n readonly emit: Listener;\n readonly messages: Catalog;\n readonly navigate: (url: string) => void;\n readonly readOnly: boolean;\n readonly revision: number;\n readonly transport: Transport.Interface;\n}\n\nconst Context = createContext<ContextValue | null>(null);\n\nconst navigateInBrowser = (url: string): void => {\n if (typeof window === \"undefined\") {\n throw new Error(\"DomainKit provider authorization requires a browser or a `navigate` prop\");\n }\n window.location.assign(url);\n};\n\nexport interface StableTransport {\n readonly transport: Transport.Interface;\n readonly capabilities: ReadonlyArray<Transport.Capability>;\n}\n\ntype Method = (...args: ReadonlyArray<never>) => Effect.Effect<unknown, unknown>;\n\n/**\n * A transport whose identity survives re-renders. Each method reads the newest transport when it\n * runs, so a host may write `<DomainKit.Root transport={Transport.fromFetch(\"/api/domainkit\")}>`\n * inline and controllers still see one transport for the whole mount. Swapping in a transport\n * that declares different capability groups rebuilds it, and every controller re-runs.\n */\nconst useStableTransport = (transport: Transport.Interface): StableTransport => {\n const latest = useRef(transport);\n useLayoutEffect(() => {\n latest.current = transport;\n });\n const signature = Transport.capabilities(transport).join(\",\");\n return useMemo(() => {\n const capabilities = Transport.capabilities(latest.current);\n const stable = Object.fromEntries(\n capabilities.map((capability) => {\n const group = latest.current[capability] as unknown as Record<string, Method>;\n return [\n capability,\n Object.fromEntries(\n Object.keys(group).map((name) => [\n name,\n (...args: ReadonlyArray<never>) =>\n Effect.suspend(() => {\n const live = latest.current[capability] as unknown as Record<string, Method>;\n const method = live[name];\n if (method === undefined) {\n throw new Error(`The transport no longer declares ${capability}.${name}`);\n }\n return method(...args);\n }),\n ]),\n ),\n ];\n }),\n ) as Transport.Interface;\n return { capabilities, transport: stable };\n }, [signature]);\n};\n\n/**\n * The transport, the catalog, and the two host callbacks every hook below reads. It renders no\n * element of its own: `@domainkit/react` supplies behaviour, state, copy, and accessibility, and\n * the host application supplies the markup.\n */\nexport function Root({\n children,\n messages,\n navigate = navigateInBrowser,\n onEvent,\n readOnly = false,\n revision = 0,\n transport,\n}: RootProps): ReactElement {\n const { capabilities, transport: stable } = useStableTransport(transport);\n const onEventRef = useRef(onEvent);\n useLayoutEffect(() => {\n onEventRef.current = onEvent;\n }, [onEvent]);\n const emit = useCallback<Listener>((event) => {\n try {\n onEventRef.current?.(event);\n } catch {\n // Host observers are best-effort and cannot change a completed operation's outcome.\n }\n }, []);\n const value: ContextValue = {\n capabilities,\n emit,\n messages: mergeMessages(messages),\n navigate,\n readOnly,\n revision,\n transport: stable,\n };\n return <Context.Provider value={value}>{children}</Context.Provider>;\n}\n\nexport function useDomainKit(): ContextValue {\n const value = useContext(Context);\n if (value === null) {\n throw new Error(\"DomainKit hooks must be called inside DomainKit.Root\");\n }\n return value;\n}\n\n/** The catalog `DomainKit.Root` holds, with the host's overrides already merged in. */\nexport function useMessages(): Catalog {\n return useDomainKit().messages;\n}\n\n/** The transport `DomainKit.Root` holds, with the identity it keeps for the whole mount. */\nexport function useTransport(): Transport.Interface {\n return useDomainKit().transport;\n}\n\nconst ReadOnlyContext = createContext<boolean | null>(null);\n\n/** Narrow one subtree to read-only without touching the rest of the page. */\nexport function ReadOnly({\n children,\n value,\n}: {\n readonly children: ReactNode;\n readonly value: boolean;\n}) {\n return <ReadOnlyContext.Provider value={value}>{children}</ReadOnlyContext.Provider>;\n}\n\n/** Whether this surface may offer controls that change the domain. */\nexport function useReadOnly(): boolean {\n const scoped = useContext(ReadOnlyContext);\n const root = useDomainKit().readOnly;\n return scoped ?? root;\n}\n\n/** Which capability groups the host's transport declares, for gating a surface of your own. */\nexport function useCapabilities(): ReadonlyArray<Transport.Capability> {\n return useDomainKit().capabilities;\n}\n","import type { DomainKit, Receipt } from \"domainkit\";\nimport type { Transport } from \"domainkit/client\";\nimport * as Data from \"effect/Data\";\n\n/** What a customer finished doing, for host notifications, analytics, and audit trails. */\nexport type Event = Data.TaggedEnum<{\n Connected: {\n readonly domain: string;\n readonly connectionId: string;\n readonly snapshot: Transport.Snapshot;\n };\n Detached: { readonly domain: string };\n Disconnected: { readonly domain: string; readonly connectionId: string };\n Applied: { readonly domain: string; readonly receipt: Receipt.Model };\n Cleaned: { readonly domain: string; readonly receipt: Receipt.Model };\n Declined: { readonly domain: string; readonly attempt: Transport.Attempt };\n Failed: { readonly domain: string; readonly error: DomainKit.Error };\n}>;\nexport const Event = Data.taggedEnum<Event>();\n\nexport type Listener = (event: Event) => void;\n","/**\n * The one place the package leaves Effect. Every controller runs its transport calls through\n * `useRunner`, which interrupts the call in flight when a newer one starts or the component\n * unmounts, and drops results that arrive after either.\n */\nimport { DomainKit, Reason } from \"domainkit\";\nimport * as Effect from \"effect/Effect\";\nimport * as Exit from \"effect/Exit\";\nimport * as Option from \"effect/Option\";\nimport { useEffect, useMemo, useRef } from \"react\";\n\nexport interface Runner {\n /**\n * Run `effect`, replacing whatever this runner had in flight. `onSuccess` and `onFailure` fire\n * only while this call is still the newest and the component is mounted.\n */\n readonly run: <A>(\n effect: Effect.Effect<A, DomainKit.Error>,\n handlers: {\n readonly onSuccess: (value: A) => void;\n readonly onFailure: (error: DomainKit.Error) => void;\n },\n ) => void;\n /** Stop the call in flight without starting another. */\n readonly cancel: () => void;\n}\n\n/** A defect is not a lifecycle failure; report it in the shape the UI already renders. */\nconst defect = (cause: unknown): DomainKit.Error =>\n new DomainKit.Error({\n reason: new Reason.ProviderUnavailable({\n provider: \"domainkit\",\n message: `The transport failed: ${String(cause)}`,\n }),\n });\n\ninterface Live {\n readonly id: number;\n interrupt: (() => void) | null;\n}\n\nexport function useRunner(): Runner {\n const state = useRef<{ mounted: boolean; next: number; live: Live | null }>({\n live: null,\n mounted: true,\n next: 0,\n });\n useEffect(() => {\n const current = state.current;\n current.mounted = true;\n return () => {\n current.mounted = false;\n current.live?.interrupt?.();\n current.live = null;\n };\n }, []);\n return useMemo<Runner>(() => {\n const stop = () => {\n state.current.live?.interrupt?.();\n state.current.live = null;\n };\n return {\n cancel: stop,\n run: (effect, handlers) => {\n stop();\n const live: Live = { id: (state.current.next += 1), interrupt: null };\n state.current.live = live;\n const interrupt = Effect.runCallback(effect, {\n onExit: (exit) => {\n if (state.current.live?.id !== live.id || !state.current.mounted) return;\n state.current.live = null;\n if (Exit.isSuccess(exit)) {\n handlers.onSuccess(exit.value);\n return;\n }\n // Read both before the interrupt guard: it narrows `exit` to the success side.\n const cause = exit.cause;\n const error = Exit.findErrorOption(exit);\n if (Exit.hasInterrupts(exit)) return;\n handlers.onFailure(Option.isSome(error) ? error.value : defect(cause));\n },\n });\n // A synchronous effect already ran `onExit` and cleared `live`; only a call still in\n // flight needs an interrupt handle.\n if (state.current.live?.id === live.id) live.interrupt = () => interrupt();\n },\n };\n }, []);\n}\n","/**\n * The plan -> approve -> apply machine both `Provision` and `Cleanup` run. They differ only in\n * which plan they build and which event they emit when the receipt lands, so the machine lives\n * here once and each namespace exports its own controller over it.\n */\nimport type { Approval, DomainKit, Plan, Receipt } from \"domainkit\";\nimport type { Transport } from \"domainkit/client\";\nimport * as Data from \"effect/Data\";\nimport * as Effect from \"effect/Effect\";\nimport { useCallback, useEffect, useRef, useState } from \"react\";\n\nimport { useDomainKit, useReadOnly } from \"./domain-kit.tsx\";\nimport { Event } from \"./events.ts\";\nimport { useRunner } from \"./task.ts\";\n\nexport type State = Data.TaggedEnum<{\n Idle: {};\n Planning: {};\n Planned: { readonly plan: Plan.Model };\n Approving: { readonly plan: Plan.Model };\n Applying: { readonly plan: Plan.Model; readonly approval: Approval.Model };\n Applied: { readonly plan: Plan.Model | null; readonly receipt: Receipt.Model };\n Rejecting: { readonly plan: Plan.Model };\n Rejected: { readonly plan: Plan.Model; readonly attempt: Transport.Attempt };\n Failure: { readonly error: DomainKit.Error };\n}>;\nexport const State = Data.taggedEnum<State>();\n\n/** The verbs `Provision` and `Cleanup` share on the wire. */\nexport interface Group {\n readonly approve: (input: {\n readonly planId: Plan.PlanId;\n readonly operationIds?: ReadonlyArray<Plan.OperationId>;\n }) => Effect.Effect<Approval.Model, DomainKit.Error>;\n readonly reject: (input: {\n readonly planId: Plan.PlanId;\n readonly reason?: string;\n }) => Effect.Effect<Transport.Attempt, DomainKit.Error>;\n readonly apply: (\n approvalId: Approval.ApprovalId,\n ) => Effect.Effect<Receipt.Model, DomainKit.Error>;\n}\n\nexport interface Controller {\n readonly state: State;\n /** Build a plan. The plan itself rides on the state, from `Planned` through `Applied`. */\n readonly plan: () => void;\n /** Authorize the digest and apply it. Pass `operationIds` to approve part of the plan. */\n readonly approve: (operationIds?: ReadonlyArray<Plan.OperationId>) => void;\n /** Decline the plan. Terminal: approving it afterwards fails `Stale`. */\n readonly reject: (reason?: string) => void;\n /** Apply the approval this controller already holds. */\n readonly apply: () => void;\n /** Re-plan when the zone moved under the plan, otherwise re-run the step that failed. */\n readonly retry: () => void;\n readonly reset: () => void;\n}\n\nexport interface Options {\n readonly domain: string;\n /**\n * Identifies the inputs this attempt is for. When it changes the attempt is abandoned, because a\n * plan, approval, and receipt only mean anything for the inputs that produced them.\n */\n readonly key: string;\n readonly group: Group | undefined;\n /** The plan call, or `null` when this flow has nothing to plan yet. */\n readonly plan: () => Effect.Effect<Plan.Model, DomainKit.Error> | null;\n readonly done: (receipt: Receipt.Model) => Event;\n readonly onDone: ((receipt: Receipt.Model) => void) | undefined;\n /** Refuse every step. Defaults to the surrounding `readOnly`. */\n readonly readOnly: boolean | undefined;\n}\n\n/** Reasons that mean the plan itself is gone: retrying the same step would fail the same way. */\nconst needsNewPlan = (error: DomainKit.Error): boolean =>\n error.reason._tag === \"Stale\" ||\n error.reason._tag === \"Expired\" ||\n error.reason._tag === \"Conflict\";\n\n/** The plan an attempt holds, whatever step it is on; `null` before there is one. */\nexport const planOf = (state: State): Plan.Model | null => {\n switch (state._tag) {\n case \"Planned\":\n case \"Approving\":\n case \"Applying\":\n case \"Rejecting\":\n case \"Rejected\":\n case \"Applied\":\n return state.plan;\n case \"Idle\":\n case \"Planning\":\n case \"Failure\":\n return null;\n }\n};\n\n/**\n * The plan still awaiting its apply, which is what a row of records reports; `null` once one has\n * landed, because from then on an observation answers instead.\n */\nexport const pendingPlan = (state: State): Plan.Model | null => {\n switch (state._tag) {\n case \"Planned\":\n case \"Approving\":\n case \"Applying\":\n return state.plan;\n case \"Idle\":\n case \"Planning\":\n case \"Applied\":\n case \"Rejecting\":\n case \"Rejected\":\n case \"Failure\":\n return null;\n }\n};\n\nexport function useAttempt(options: Options): Controller {\n const { domain, done, group, key, onDone } = options;\n const { emit } = useDomainKit();\n const inherited = useReadOnly();\n // Every step of an attempt is a write, planning included: a plan is an attempt the server\n // records. A read-only surface may render a button anyway, so the refusal lives here.\n const readOnly = options.readOnly ?? inherited;\n const runner = useRunner();\n const [state, setState] = useState<State>(State.Idle());\n // The key travels with what it produced, so a command raised before the reset commits still\n // refuses to run: a plan built for one domain must never be approved for another.\n const held = useRef<{\n key: string;\n plan: Plan.Model | null;\n approval: Approval.Model | null;\n }>({ approval: null, key, plan: null });\n const lastCommand = useRef<{ key: string; run: () => void } | null>(null);\n const build = useRef(options.plan);\n useEffect(() => {\n build.current = options.plan;\n });\n\n // Abandoning while rendering, not one effect later, is what makes the guards below sound: a\n // reply that lands in between finds the new key already recorded and drops itself.\n const [current, setCurrent] = useState(key);\n if (current !== key) {\n setCurrent(key);\n runner.cancel();\n held.current = { approval: null, key, plan: null };\n lastCommand.current = null;\n setState(State.Idle());\n }\n\n const onFailure = useCallback(\n (error: DomainKit.Error) => {\n setState(State.Failure({ error }));\n emit(Event.Failed({ domain, error }));\n },\n [domain, emit],\n );\n\n const applyWith = useCallback(\n (plan: Plan.Model, approval: Approval.Model) => {\n if (readOnly || group === undefined || held.current.key !== key) return;\n const command = () => {\n setState(State.Applying({ approval, plan }));\n runner.run(group.apply(approval.id), {\n onFailure,\n onSuccess: (receipt) => {\n setState(State.Applied({ plan, receipt }));\n emit(done(receipt));\n onDone?.(receipt);\n },\n });\n };\n lastCommand.current = { key, run: command };\n command();\n },\n [done, emit, group, key, onDone, onFailure, readOnly, runner],\n );\n\n const buildPlan = useCallback(() => {\n if (readOnly) return;\n const effect = build.current();\n if (effect === null) return;\n const command = () => {\n setState(State.Planning());\n runner.run(effect, {\n onFailure,\n onSuccess: (plan) => {\n if (held.current.key !== key) return;\n held.current = { approval: null, key, plan };\n setState(State.Planned({ plan }));\n },\n });\n };\n lastCommand.current = { key, run: command };\n command();\n }, [key, onFailure, readOnly, runner]);\n\n const approve = useCallback(\n (operationIds?: ReadonlyArray<Plan.OperationId>) => {\n const plan = held.current.plan;\n if (readOnly || group === undefined || plan === null || held.current.key !== key) return;\n const command = () => {\n setState(State.Approving({ plan }));\n runner.run(\n group.approve({\n planId: plan.id,\n ...(operationIds === undefined ? {} : { operationIds }),\n }),\n {\n onFailure,\n onSuccess: (approval) => {\n if (held.current.key !== key) return;\n held.current = { approval, key, plan };\n applyWith(plan, approval);\n },\n },\n );\n };\n lastCommand.current = { key, run: command };\n command();\n },\n [applyWith, group, key, onFailure, readOnly, runner],\n );\n\n const reject = useCallback(\n (reason?: string) => {\n const plan = held.current.plan;\n if (readOnly || group === undefined || plan === null || held.current.key !== key) return;\n const command = () => {\n setState(State.Rejecting({ plan }));\n runner.run(group.reject({ planId: plan.id, ...(reason === undefined ? {} : { reason }) }), {\n onFailure,\n onSuccess: (attempt) => {\n setState(State.Rejected({ attempt, plan }));\n emit(Event.Declined({ attempt, domain }));\n },\n });\n };\n lastCommand.current = { key, run: command };\n command();\n },\n [domain, emit, group, key, onFailure, readOnly, runner],\n );\n\n const apply = useCallback(() => {\n const { approval, plan } = held.current;\n if (readOnly || approval === null || plan === null) return;\n applyWith(plan, approval);\n }, [applyWith]);\n\n const retry = useCallback(() => {\n // Every step of an attempt is a write, so read-only has nothing to retry.\n if (readOnly) return;\n if (state._tag === \"Failure\" && needsNewPlan(state.error)) {\n held.current = { approval: null, key, plan: null };\n buildPlan();\n return;\n }\n const command = lastCommand.current;\n if (command === null || command.key !== key) buildPlan();\n else command.run();\n }, [buildPlan, key, readOnly, state]);\n\n const reset = useCallback(() => {\n runner.cancel();\n held.current = { approval: null, key, plan: null };\n lastCommand.current = null;\n setState(State.Idle());\n }, [key, runner]);\n\n return { apply, approve, plan: buildPlan, reject, reset, retry, state };\n}\n","import { DomainKit, Reason, Receipt } from \"domainkit\";\nimport * as Effect from \"effect/Effect\";\nimport { useCallback } from \"react\";\n\nimport { pendingPlan, planOf, State, useAttempt, type Controller } from \"./attempt.ts\";\nimport { useDomainKit } from \"./domain-kit.tsx\";\nimport { Event } from \"./events.ts\";\n\nexport { pendingPlan, planOf, State };\nexport type { Controller };\n\nexport interface Options {\n readonly domain: string;\n /** Which apply to undo. Without it, the domain's latest provisioning receipt. */\n readonly receiptId?: Receipt.ReceiptId;\n readonly onCleaned?: (receipt: Receipt.Model) => void;\n /** Refuse every step. Defaults to the surrounding `readOnly`. */\n readonly readOnly?: boolean;\n}\n\n/**\n * Cleanup is bound to a receipt: it removes only what an apply proved DomainKit created. When the\n * host does not name one, the controller reads the domain's latest from the snapshot.\n */\nexport function useController({ domain, onCleaned, readOnly, receiptId }: Options): Controller {\n const { transport } = useDomainKit();\n const group = transport.cleanup;\n const connection = transport.connection;\n return useAttempt({\n domain,\n key: [domain, receiptId ?? \"\"].join(\"|\"),\n done: (receipt) => Event.Cleaned({ domain, receipt }),\n group,\n onDone: onCleaned,\n readOnly,\n plan: useCallback(() => {\n if (group === undefined) return null;\n if (receiptId !== undefined) return group.plan(receiptId);\n if (connection === undefined) return null;\n return Effect.flatMap(connection.inspect(domain), (snapshot) =>\n snapshot.lastReceiptId === null\n ? Effect.fail(\n new DomainKit.Error({\n reason: new Reason.NotFound({ entity: \"receipt\", id: snapshot.domain }),\n }),\n )\n : group.plan(Receipt.ReceiptId.make(snapshot.lastReceiptId)),\n );\n }, [connection, domain, group, receiptId]),\n });\n}\n","/**\n * Adding a domain is one input. The zones every connected account reaches load when the field\n * mounts, typing filters them, Tab completes the highlighted one while keeping whatever subdomain\n * was typed in front of it, and the surface names the account the records will go to.\n *\n * The listbox is built here rather than on a combobox primitive because the completion rule is not\n * a selection model: a suggestion never replaces what the customer typed, it finishes it, and a\n * domain outside every zone leaves the input a plain text field.\n */\nimport type { DomainKit } from \"domainkit\";\nimport { Transport } from \"domainkit/client\";\nimport * as Data from \"effect/Data\";\nimport {\n useCallback,\n useEffect,\n useId,\n useRef,\n useState,\n type AriaAttributes,\n type FocusEventHandler,\n type FormEventHandler,\n type KeyboardEventHandler,\n type MouseEventHandler,\n} from \"react\";\n\nimport type { Descriptor } from \"./connect.ts\";\nimport { useDomainKit, useMessages, useReadOnly } from \"./domain-kit.tsx\";\nimport { useRunner } from \"./task.ts\";\n\nexport type Zone = Transport.Zone;\nexport type Account = Transport.Zones[\"connections\"][number];\nexport type AuthMethod = Descriptor[\"methods\"][number];\n\n/** Where a domain's records would go: the connection that serves it, and in which zone. */\nexport interface Placement {\n readonly connectionId: string;\n readonly zone: string;\n}\n\n// ---------------------------------------------------------------------------------------------\n// useZones\n// ---------------------------------------------------------------------------------------------\n\nexport type ZonesState = Data.TaggedEnum<{\n Loading: {};\n Ready: {\n readonly zones: ReadonlyArray<Zone>;\n readonly connections: ReadonlyArray<Account>;\n readonly providers: ReadonlyArray<Descriptor>;\n };\n Failure: { readonly error: DomainKit.Error };\n}>;\nexport const ZonesState = Data.taggedEnum<ZonesState>();\n\nexport interface ZonesController {\n readonly state: ZonesState;\n readonly zones: ReadonlyArray<Zone>;\n readonly connections: ReadonlyArray<Account>;\n readonly providers: ReadonlyArray<Descriptor>;\n readonly refresh: () => void;\n}\n\nexport interface ZonesOptions {\n /** Only this provider's connections. Omit for every connection this owner holds. */\n readonly provider?: string;\n}\n\nconst nothing = {\n connections: [] as ReadonlyArray<Account>,\n providers: [] as ReadonlyArray<Descriptor>,\n zones: [] as ReadonlyArray<Zone>,\n};\n\n/**\n * Every zone this owner's connections reach. A connection whose credential the provider turned\n * down is listed in `connections` as `reconnect` and contributes no zones, so one dead account\n * never costs the customer the others.\n */\nexport function useZones({ provider }: ZonesOptions = {}): ZonesController {\n const { revision, transport } = useDomainKit();\n const connection = transport.connection;\n const runner = useRunner();\n const [state, setState] = useState<ZonesState>(ZonesState.Loading());\n\n const load = useCallback(() => {\n if (connection === undefined) return;\n setState(ZonesState.Loading());\n runner.run(connection.zones(provider === undefined ? {} : { provider }), {\n onFailure: (error) => setState(ZonesState.Failure({ error })),\n onSuccess: (listing) =>\n setState(\n ZonesState.Ready({\n connections: listing.connections,\n providers: listing.providers,\n zones: listing.zones,\n }),\n ),\n });\n }, [connection, provider, runner]);\n\n useEffect(load, [load, revision]);\n\n const held = state._tag === \"Ready\" ? state : nothing;\n return {\n connections: held.connections,\n providers: held.providers,\n refresh: load,\n state,\n zones: held.zones,\n };\n}\n\n// ---------------------------------------------------------------------------------------------\n// useAccounts\n// ---------------------------------------------------------------------------------------------\n\nexport interface ConnectAccountInput {\n readonly provider: string;\n readonly method: AuthMethod[\"kind\"];\n /** Keyed by the descriptor's field names. Ignored by the interactive methods. */\n readonly values?: Readonly<Record<string, string>>;\n}\n\nexport type AccountsState = Data.TaggedEnum<{\n Loading: {};\n Ready: {};\n Submitting: { readonly provider: string };\n Redirecting: { readonly url: string };\n Failure: { readonly error: DomainKit.Error };\n}>;\nexport const AccountsState = Data.taggedEnum<AccountsState>();\n\nexport interface AccountsController {\n readonly state: AccountsState;\n readonly zones: ReadonlyArray<Zone>;\n readonly connections: ReadonlyArray<Account>;\n readonly providers: ReadonlyArray<Descriptor>;\n /** Connect a provider with no domain attached. The account is what the customer is granting. */\n readonly connect: (input: ConnectAccountInput) => void;\n /**\n * Prove an account again for a connection the owner already holds. The connection and its\n * domains stay; only the credential behind it is replaced.\n */\n readonly reconnect: (input: ConnectAccountInput & { readonly connectionId: string }) => void;\n readonly refresh: () => void;\n}\n\nexport interface AccountsOptions {\n /** Where an interactive method returns the customer. Defaults to the page they started from. */\n readonly returnTo?: string | null;\n /** Refuse the commands that grant an account. Defaults to the surrounding `readOnly`. */\n readonly readOnly?: boolean;\n}\n\nconst currentUrl = (): string | null =>\n typeof window === \"undefined\" ? null : window.location.href;\n\n/**\n * The accounts this owner holds, and the one way to add another: connect a provider without naming\n * a domain. A token method finishes in place; an interactive one redirects and comes back through\n * the library's own callback, which lands on `returnTo`.\n */\nexport function useAccounts({\n readOnly: refused,\n returnTo,\n}: AccountsOptions = {}): AccountsController {\n const { navigate, transport } = useDomainKit();\n const inherited = useReadOnly();\n // Granting an account is a write like any other, so the refusal lives here rather than in the\n // markup a host wrote.\n const readOnly = refused ?? inherited;\n const connection = transport.connection;\n const runner = useRunner();\n const listing = useZones();\n const [command, setCommand] = useState<AccountsState | null>(null);\n\n const refresh = listing.refresh;\n const submit = useCallback(\n (input: ConnectAccountInput & { readonly connectionId?: string }) => {\n if (connection === undefined || readOnly) return;\n const destination = returnTo === undefined ? currentUrl() : returnTo;\n const interactive = destination === null ? {} : { returnTo: destination };\n const method =\n input.method === \"token\"\n ? Transport.Method.token(input.values ?? {})\n : input.method === \"oauth\"\n ? Transport.Method.oauth(interactive)\n : Transport.Method.integration(interactive);\n setCommand(AccountsState.Submitting({ provider: input.provider }));\n const granting =\n input.connectionId === undefined\n ? connection.start({ method, provider: input.provider })\n : connection.reconnect({ connectionId: input.connectionId, method });\n runner.run(granting, {\n onFailure: (error) => setCommand(AccountsState.Failure({ error })),\n onSuccess: (started) => {\n if (started._tag === \"Redirect\") {\n setCommand(AccountsState.Redirecting({ url: started.authorizationUrl }));\n navigate(started.authorizationUrl);\n return;\n }\n // A selection is about a domain and this flow names none, so the account is connected.\n setCommand(null);\n refresh();\n },\n });\n },\n [connection, navigate, readOnly, refresh, returnTo, runner],\n );\n const connect = useCallback((input: ConnectAccountInput) => submit(input), [submit]);\n const reconnect = useCallback(\n (input: ConnectAccountInput & { readonly connectionId: string }) => submit(input),\n [submit],\n );\n\n const state =\n command ??\n (listing.state._tag === \"Loading\"\n ? AccountsState.Loading()\n : listing.state._tag === \"Failure\"\n ? AccountsState.Failure({ error: listing.state.error })\n : AccountsState.Ready());\n\n return {\n connect,\n reconnect,\n connections: listing.connections,\n providers: listing.providers,\n refresh,\n state,\n zones: listing.zones,\n };\n}\n\n// ---------------------------------------------------------------------------------------------\n// Matching\n// ---------------------------------------------------------------------------------------------\n\nconst normalize = (value: string): string => value.trim().toLowerCase().replace(/\\.$/, \"\");\n\n/**\n * The zone a value already sits in: the longest listed zone the value is at or under. Two accounts\n * can serve the same zone, so `preferred` names the one the customer picked and wins among equals;\n * without it the first listed account answers.\n */\nexport const placementOf = (\n value: string,\n zones: ReadonlyArray<Zone>,\n preferred?: Placement | null,\n): { readonly zone: Zone; readonly placement: Placement } | null => {\n const domain = normalize(value);\n if (domain === \"\") return null;\n const matching = zones.filter((candidate) => {\n const zone = normalize(candidate.zone);\n return domain === zone || domain.endsWith(`.${zone}`);\n });\n const longest = matching.reduce(\n (best, candidate) =>\n best === null || normalize(candidate.zone).length > normalize(best.zone).length\n ? candidate\n : best,\n null as Zone | null,\n );\n if (longest === null) return null;\n const closest = matching.filter(\n (candidate) => normalize(candidate.zone) === normalize(longest.zone),\n );\n const best =\n closest.find(\n (candidate) =>\n preferred != null &&\n candidate.connectionId === preferred.connectionId &&\n normalize(candidate.zone) === normalize(preferred.zone),\n ) ??\n closest[0] ??\n longest;\n return { placement: { connectionId: best.connectionId, zone: best.zone }, zone: best };\n};\n\n/**\n * What the customer typed in front of the zone they are reaching for. \"mail.ex\" against\n * `example.com` is the subdomain \"mail\"; \"ex\" on its own is none.\n */\nconst subdomainOf = (value: string, zone: string): string => {\n const typed = normalize(value);\n const target = normalize(zone);\n if (typed === \"\" || target.startsWith(typed)) return \"\";\n const cut = typed.lastIndexOf(\".\");\n if (cut < 0) return \"\";\n const head = typed.slice(0, cut);\n const tail = typed.slice(cut + 1);\n return target.startsWith(tail) ? head : \"\";\n};\n\n/** Zones the typed value is reaching for: a prefix of the zone, or a subdomain of one. */\nexport const suggestionsFor = (value: string, zones: ReadonlyArray<Zone>): ReadonlyArray<Zone> => {\n const typed = normalize(value);\n if (typed === \"\") return zones;\n return zones.filter((candidate) => {\n const zone = normalize(candidate.zone);\n if (zone.startsWith(typed)) return true;\n const cut = typed.lastIndexOf(\".\");\n if (cut < 0) return false;\n const tail = typed.slice(cut + 1);\n return tail !== \"\" && zone.startsWith(tail);\n });\n};\n\n/** The value a suggestion completes to: whatever subdomain was typed, then the zone. */\nexport const completionOf = (value: string, zone: Zone): string => {\n const subdomain = subdomainOf(value, zone.zone);\n return subdomain === \"\" ? zone.zone : `${subdomain}.${zone.zone}`;\n};\n\n// ---------------------------------------------------------------------------------------------\n// useDomainField\n// ---------------------------------------------------------------------------------------------\n\nconst optionId = (listId: string, zone: Zone): string =>\n `${listId}-${zone.connectionId}-${zone.zone}`;\n\nexport interface DomainFieldOptions {\n /** Every zone the surface offers, which `useZones` or `useAccounts` already holds. */\n readonly zones: ReadonlyArray<Zone>;\n readonly value: string;\n readonly onChange: (value: string) => void;\n /**\n * Fires when the value or the account it resolves to changes, so a host holds the two together\n * and submits them together. It reports the value as typed, not only the placement, because a\n * form needs the name the customer is on as well as where its records would go.\n */\n readonly onResolve?: (input: {\n readonly domain: string;\n readonly connection: Placement | null;\n }) => void;\n /** The input's id. The listbox and its options are named from it; one is generated otherwise. */\n readonly id?: string;\n}\n\n/** The props one suggestion carries, so the option is a listbox option to a screen reader. */\nexport interface OptionProps {\n readonly \"aria-selected\": boolean;\n readonly id: string;\n readonly onMouseDown: MouseEventHandler<Element>;\n readonly role: \"option\";\n}\n\nexport interface DomainFieldController {\n /** Whether the listbox is showing: the customer opened it and there is something in it. */\n readonly open: boolean;\n /** The zones the typed value is reaching for, in the order they were listed. */\n readonly suggestions: ReadonlyArray<Zone>;\n /** The suggestion Tab and Enter would complete, or `null` when the list is empty. */\n readonly highlighted: Zone | null;\n /** The zone the value already sits in, with the account its records would go to. */\n readonly found: { readonly zone: Zone; readonly placement: Placement } | null;\n /** Finish the name from one suggestion, keeping whatever subdomain was typed in front of it. */\n readonly complete: (zone: Zone) => void;\n readonly close: () => void;\n readonly inputProps: {\n readonly \"aria-activedescendant\": AriaAttributes[\"aria-activedescendant\"];\n readonly \"aria-autocomplete\": \"list\";\n readonly \"aria-controls\": string;\n readonly \"aria-expanded\": boolean;\n readonly autoComplete: \"off\";\n readonly id: string;\n readonly onChange: FormEventHandler<HTMLInputElement>;\n readonly onFocus: FocusEventHandler<HTMLInputElement>;\n readonly onKeyDown: KeyboardEventHandler<HTMLInputElement>;\n readonly role: \"combobox\";\n readonly type: \"text\";\n readonly value: string;\n };\n readonly listboxProps: {\n readonly \"aria-label\": string;\n readonly hidden: boolean;\n readonly id: string;\n readonly role: \"listbox\";\n };\n readonly optionProps: (zone: Zone) => OptionProps;\n}\n\n/**\n * One input over every zone the workspace's accounts reach, as props rather than markup. Arrow\n * keys move the highlight, Tab or Enter completes it, Escape closes the list, and `found` says\n * where the records will go.\n */\nexport function useDomainField({\n id,\n onChange,\n onResolve,\n value,\n zones,\n}: DomainFieldOptions): DomainFieldController {\n const messages = useMessages();\n const generated = useId();\n const inputId = id ?? generated;\n const listId = `${inputId}-suggestions`;\n const [open, setOpen] = useState(false);\n const [active, setActive] = useState(0);\n // Which account the customer completed from, so a zone two accounts both serve stays the one\n // they picked rather than whichever the listing happens to hold first. `placementOf` honours it\n // only while the value still sits in that zone, so a value that moves — whether the customer\n // typed it or the host set it — loses the preference by the same rule.\n const [chosen, setChosen] = useState<Placement | null>(null);\n const suggestions = suggestionsFor(value, zones);\n const highlighted = suggestions[Math.min(active, Math.max(suggestions.length - 1, 0))] ?? null;\n const found = placementOf(value, zones, chosen);\n const showing = open && suggestions.length > 0;\n\n // One report per value and placement: a re-render that changes neither says nothing.\n const placement = found?.placement ?? null;\n const connectionId = placement?.connectionId ?? null;\n const placedIn = placement?.zone ?? null;\n const announced = useRef<string | null>(null);\n useEffect(() => {\n const signature = `${value}|${connectionId ?? \"\"}|${placedIn ?? \"\"}`;\n if (announced.current === signature) return;\n announced.current = signature;\n onResolve?.({\n connection:\n connectionId === null || placedIn === null ? null : { connectionId, zone: placedIn },\n domain: value,\n });\n }, [connectionId, onResolve, placedIn, value]);\n\n const complete = (zone: Zone) => {\n onChange(completionOf(value, zone));\n setChosen({ connectionId: zone.connectionId, zone: zone.zone });\n setOpen(false);\n setActive(0);\n };\n\n return {\n close: () => setOpen(false),\n complete,\n found,\n highlighted,\n inputProps: {\n \"aria-activedescendant\":\n showing && highlighted !== null ? optionId(listId, highlighted) : undefined,\n \"aria-autocomplete\": \"list\",\n \"aria-controls\": listId,\n \"aria-expanded\": showing,\n autoComplete: \"off\",\n id: inputId,\n onChange: (event) => {\n onChange((event.target as HTMLInputElement).value);\n setActive(0);\n setOpen(true);\n },\n onFocus: () => setOpen(true),\n onKeyDown: (event) => {\n if (event.key === \"Escape\") {\n setOpen(false);\n return;\n }\n if (suggestions.length === 0) return;\n if (event.key === \"ArrowDown\") {\n event.preventDefault();\n setOpen(true);\n setActive((index) => (index + 1) % suggestions.length);\n return;\n }\n if (event.key === \"ArrowUp\") {\n event.preventDefault();\n setOpen(true);\n setActive((index) => (index + suggestions.length - 1) % suggestions.length);\n return;\n }\n // Tab and Enter finish the name rather than choosing one: what the customer typed in\n // front of the zone stays in front of it.\n if ((event.key === \"Tab\" || event.key === \"Enter\") && showing && highlighted !== null) {\n event.preventDefault();\n complete(highlighted);\n }\n },\n role: \"combobox\",\n type: \"text\",\n value,\n },\n listboxProps: {\n \"aria-label\": messages.zoneSuggestions,\n hidden: !showing,\n id: listId,\n role: \"listbox\",\n },\n open: showing,\n optionProps: (zone) => ({\n \"aria-selected\": zone === highlighted,\n id: optionId(listId, zone),\n // The press must not take focus off the input before the completion lands.\n onMouseDown: (event) => {\n event.preventDefault();\n complete(zone);\n },\n role: \"option\",\n }),\n suggestions,\n };\n}\n","import { Receipt, type DomainKit, type Storage } from \"domainkit\";\nimport { Transport } from \"domainkit/client\";\nimport * as Data from \"effect/Data\";\nimport * as Effect from \"effect/Effect\";\nimport { useCallback, useEffect, useRef, useState } from \"react\";\n\nimport { useDomainKit, useReadOnly } from \"./domain-kit.tsx\";\nimport { Event } from \"./events.ts\";\nimport { useRunner } from \"./task.ts\";\n\nexport {\n AccountsState,\n completionOf,\n placementOf,\n suggestionsFor,\n useAccounts,\n useDomainField,\n useZones,\n ZonesState,\n type Account,\n type AccountsController,\n type AccountsOptions,\n type ConnectAccountInput,\n type DomainFieldController,\n type DomainFieldOptions,\n type Placement,\n type Zone,\n type ZonesController,\n type ZonesOptions,\n} from \"./domain-field.ts\";\n\nexport type Snapshot = Transport.Snapshot;\nexport type Discovery = Transport.Discovery;\nexport type Candidate = Transport.Candidate;\n/** A provider as the snapshot describes it: an id, a display name, and its auth methods. */\nexport type Descriptor = Transport.Snapshot[\"providers\"][number];\nexport type MethodDescriptor = Descriptor[\"methods\"][number];\nexport type Field = NonNullable<MethodDescriptor[\"fields\"]>[number];\n\n/**\n * Where a domain stands with its DNS provider. `Disconnected` carries whatever\n * `connection.discover` found, so the UI can offer a connection the customer already has before\n * asking for another one.\n */\nexport type State = Data.TaggedEnum<{\n Loading: { readonly snapshot: Snapshot | null };\n Disconnected: { readonly snapshot: Snapshot; readonly discovery: Discovery | null };\n Connected: { readonly snapshot: Snapshot };\n Reconnect: { readonly snapshot: Snapshot };\n Submitting: { readonly snapshot: Snapshot | null; readonly discovery: Discovery | null };\n Redirecting: { readonly url: string };\n SelectionRequired: {\n readonly snapshot: Snapshot | null;\n readonly connectionId: string;\n readonly candidates: ReadonlyArray<Candidate>;\n };\n Failure: {\n readonly error: DomainKit.Error;\n readonly snapshot: Snapshot | null;\n readonly discovery: Discovery | null;\n /** The provider and method the customer was using, when a command failed rather than a read. */\n readonly attempt: Attempt | null;\n };\n}>;\nexport const State = Data.taggedEnum<State>();\n\n/** Which provider and method the failed command was for, so the form can answer beside it. */\nexport interface Attempt {\n readonly provider: string;\n readonly method: Storage.AuthMethod;\n}\n\nexport interface ConnectInput {\n readonly provider: string;\n readonly method: Storage.AuthMethod;\n /** Keyed by the descriptor's field names. Ignored by the interactive methods. */\n readonly values?: Readonly<Record<string, string>>;\n /** Where an interactive method returns the customer. */\n readonly returnTo?: string;\n}\n\nexport interface Controller {\n readonly domain: string;\n /**\n * What this domain's last apply landed, read once per receipt id and held here. `null` until\n * the snapshot names a receipt, or when the transport carries no provisioning group.\n */\n readonly receipt: Receipt.Model | null;\n /**\n * How many times a connection has been established for this domain on this surface: a token\n * connect that landed, or a load that followed this library's own redirect back. It only ever\n * grows, so a flow acts on a change rather than on a state that would fire again every render.\n */\n readonly established: number;\n readonly state: State;\n readonly snapshot: Snapshot | null;\n readonly discovery: Discovery | null;\n readonly providers: ReadonlyArray<Descriptor>;\n readonly connect: (input: ConnectInput) => void;\n /** Attach the domain to a connection this owner already has. */\n readonly reuse: (input: { readonly connectionId: string; readonly zone?: string }) => void;\n /** Answer `SelectionRequired` by naming the zone that serves the domain. */\n readonly select: (zone: string) => void;\n readonly detach: () => void;\n readonly disconnect: () => void;\n /** Re-inspect the domain, discarding any failure. */\n readonly refresh: () => void;\n /** Re-run the step that failed; without one, re-inspect. */\n readonly retry: () => void;\n}\n\nexport interface Options {\n readonly domain: string;\n /**\n * Where an interactive method returns the customer. Defaults to the page they started from;\n * pass `null` to send none and let the server's `defaultReturnTo` decide.\n */\n readonly returnTo?: string | null;\n /**\n * Refuse every command that changes the connection. Defaults to the surrounding `readOnly`,\n * which is `DomainKit.Root`'s unless a `DomainKit.ReadOnly` narrows it.\n */\n readonly readOnly?: boolean;\n}\n\n/**\n * An interactive method leaves the page and comes back, so what the library knew is gone with it.\n * It writes down the domain it sent the customer away for, and the load that follows reads it once:\n * that, not a query parameter a host would have to keep, is how a return is told from a reload.\n */\nconst RETURNING = \"domainkit.returning\";\n\nconst markReturn = (domain: string): void => {\n try {\n sessionStorage.setItem(RETURNING, domain);\n } catch {\n // A browser with storage turned off simply loses the one-click return.\n }\n};\n\nconst tookReturn = (domain: string): boolean => {\n try {\n if (sessionStorage.getItem(RETURNING) !== domain) return false;\n sessionStorage.removeItem(RETURNING);\n return true;\n } catch {\n return false;\n }\n};\n\n/** Read at connect time, not at render, so it is the page the customer is actually on. */\nconst currentUrl = (): string | null =>\n typeof window === \"undefined\" ? null : window.location.href;\n\nconst snapshotOf = (state: State): Snapshot | null => {\n switch (state._tag) {\n case \"Connected\":\n case \"Reconnect\":\n case \"Disconnected\":\n return state.snapshot;\n case \"Loading\":\n case \"Submitting\":\n case \"SelectionRequired\":\n case \"Failure\":\n return state.snapshot;\n case \"Redirecting\":\n return null;\n }\n};\n\nconst settled = (snapshot: Snapshot, discovery: Discovery | null): State => {\n switch (snapshot.status) {\n case \"connected\":\n return State.Connected({ snapshot });\n case \"reconnect\":\n return State.Reconnect({ snapshot });\n case \"disconnected\":\n return State.Disconnected({ discovery, snapshot });\n }\n};\n\n/**\n * The domain's connection, and the four ways to change it. Discovery runs on mount whenever the\n * transport declares it and the domain has no connection yet; a discovery failure is not the\n * customer's problem, so the provider list still renders.\n */\nexport function useController({ domain, readOnly: refused, returnTo }: Options): Controller {\n const { emit, navigate, revision, transport } = useDomainKit();\n const inherited = useReadOnly();\n // The surface is the host's now, so a control it renders anyway must not reach the transport:\n // every command that changes the connection is refused here rather than hidden up there.\n const readOnly = refused ?? inherited;\n const connection = transport.connection;\n const provisioning = transport.provisioning;\n const runner = useRunner();\n const [state, setState] = useState<State>(State.Loading({ snapshot: null }));\n\n // The snapshot and the discovery belong to the domain they were read for, so a controller\n // pointed at a new domain drops both while rendering rather than one effect later.\n // What was read travels with the domain it was read for, so a command or a reply that arrives\n // after the controller moved refuses to act: one domain's attachment must never be detached for\n // another.\n const held = useRef<{\n domain: string;\n snapshot: Snapshot | null;\n discovery: Discovery | null;\n }>({ discovery: null, domain, snapshot: null });\n const lastCommand = useRef<{ domain: string; run: () => void } | null>(null);\n // What the customer was doing when it failed, so the dialog can answer beside that method.\n const attempted = useRef<Attempt | null>(null);\n\n const [established, setEstablished] = useState(0);\n const [inspected, setInspected] = useState(domain);\n if (inspected !== domain) {\n setInspected(domain);\n runner.cancel();\n held.current = { discovery: null, domain, snapshot: null };\n lastCommand.current = null;\n setState(State.Loading({ snapshot: null }));\n }\n\n // A failure keeps what was already read: the customer's provider list, the domain in the\n // dialog's description, and the discovery that offered a connection they already have.\n const onFailure = useCallback(\n (error: DomainKit.Error) => {\n setState(\n State.Failure({\n attempt: attempted.current,\n discovery: held.current.discovery,\n error,\n snapshot: held.current.snapshot,\n }),\n );\n emit(Event.Failed({ domain, error }));\n },\n [domain, emit],\n );\n\n const load = useCallback(() => {\n if (connection === undefined) return;\n lastCommand.current = null;\n attempted.current = null;\n held.current = { discovery: null, domain, snapshot: null };\n // A refresh keeps the snapshot on screen; a domain change already cleared it.\n setState((previous) => State.Loading({ snapshot: snapshotOf(previous) }));\n runner.run(\n Effect.flatMap(connection.inspect(domain), (snapshot) =>\n snapshot.status === \"disconnected\"\n ? Effect.map(\n connection.discover(domain).pipe(Effect.catch(() => Effect.succeed(null))),\n (discovery) => ({ discovery, snapshot }),\n )\n : Effect.succeed({ discovery: null, snapshot }),\n ),\n {\n onFailure,\n onSuccess: ({ discovery, snapshot }) => {\n if (held.current.domain !== domain) return;\n held.current = { discovery, domain, snapshot };\n // The marker answers exactly one load: the one that came back. It is spent whatever\n // that load found, so an authorization the customer abandoned cannot leave it lying\n // there for an ordinary page view to read as a return weeks later.\n const returned = tookReturn(domain);\n if (returned && snapshot.status === \"connected\") {\n setEstablished((count) => count + 1);\n }\n setState(settled(snapshot, discovery));\n },\n },\n );\n }, [connection, domain, onFailure, runner]);\n\n useEffect(load, [load, revision]);\n\n const started = useCallback(\n (result: Transport.Started) => {\n if (held.current.domain !== domain) return;\n switch (result._tag) {\n case \"Connected\": {\n const snapshot = result.snapshot;\n setEstablished((count) => count + 1);\n // This controller is one domain's, so every command it sends carries that domain and\n // comes back with its snapshot. A reply without one connected an account alone, which\n // only a host calling the transport directly can do, so read the domain again.\n if (snapshot === null) {\n load();\n return;\n }\n held.current = { discovery: null, domain, snapshot };\n setState(settled(snapshot, null));\n if (snapshot.connectionId !== null) {\n emit(Event.Connected({ connectionId: snapshot.connectionId, domain, snapshot }));\n }\n return;\n }\n case \"Redirect\":\n markReturn(domain);\n setState(State.Redirecting({ url: result.authorizationUrl }));\n navigate(result.authorizationUrl);\n return;\n case \"SelectionRequired\":\n setState(\n State.SelectionRequired({\n candidates: result.candidates,\n connectionId: result.connectionId,\n snapshot: held.current.snapshot,\n }),\n );\n return;\n }\n },\n [domain, emit, load, navigate],\n );\n\n const submit = useCallback(\n (effect: Effect.Effect<Transport.Started, DomainKit.Error>, attempt: Attempt | null) => {\n if (held.current.domain !== domain) return;\n attempted.current = attempt;\n const command = () => {\n setState(\n State.Submitting({\n discovery: held.current.discovery,\n snapshot: held.current.snapshot,\n }),\n );\n runner.run(effect, { onFailure, onSuccess: started });\n };\n lastCommand.current = { domain, run: command };\n command();\n },\n [domain, onFailure, runner, started],\n );\n\n const connect = useCallback(\n (input: ConnectInput) => {\n if (connection === undefined || readOnly) return;\n const destination = input.returnTo ?? (returnTo === undefined ? currentUrl() : returnTo);\n const interactive = destination === null ? {} : { returnTo: destination };\n const method =\n input.method === \"token\"\n ? Transport.Method.token(input.values ?? {})\n : input.method === \"oauth\"\n ? Transport.Method.oauth(interactive)\n : Transport.Method.integration(interactive);\n // A domain whose connection the provider turned down is not asking for a second account:\n // proving the same provider again re-credits the connection it already has, and the domains\n // on it stay where they are. Starting instead would fail, because the domain is attached.\n const snapshot = held.current.snapshot;\n const stale =\n snapshot?.status === \"reconnect\" &&\n snapshot.provider === input.provider &&\n snapshot.connectionId !== null;\n submit(\n stale && snapshot?.connectionId != null\n ? connection.reconnect({ connectionId: snapshot.connectionId, method })\n : connection.start({ domain, method, provider: input.provider }),\n { method: input.method, provider: input.provider },\n );\n },\n [connection, domain, readOnly, returnTo, submit],\n );\n\n const reuse = useCallback(\n (input: { readonly connectionId: string; readonly zone?: string }) => {\n if (connection === undefined || readOnly) return;\n submit(\n connection.attach({\n connectionId: input.connectionId,\n domain,\n ...(input.zone === undefined ? {} : { zone: input.zone }),\n }),\n null,\n );\n },\n [connection, domain, readOnly, submit],\n );\n\n const select = useCallback(\n (zone: string) => {\n if (state._tag !== \"SelectionRequired\") return;\n reuse({ connectionId: state.connectionId, zone });\n },\n [reuse, state],\n );\n\n const release = useCallback(\n (effect: Effect.Effect<void, DomainKit.Error>, event: Event) => {\n if (held.current.domain !== domain) return;\n attempted.current = null;\n const command = () => {\n setState(\n State.Submitting({\n discovery: held.current.discovery,\n snapshot: held.current.snapshot,\n }),\n );\n runner.run(effect, {\n onFailure,\n onSuccess: () => {\n emit(event);\n load();\n },\n });\n };\n lastCommand.current = { domain, run: command };\n command();\n },\n [domain, emit, load, onFailure, runner],\n );\n\n const detach = useCallback(() => {\n const attachmentId = held.current.snapshot?.attachment?.id;\n if (readOnly || connection === undefined || attachmentId == null) return;\n if (held.current.domain !== domain) return;\n release(connection.detach(attachmentId), Event.Detached({ domain }));\n }, [connection, domain, readOnly, release]);\n\n const disconnect = useCallback(() => {\n const connectionId = held.current.snapshot?.connectionId;\n if (readOnly || connection === undefined || connectionId == null) return;\n if (held.current.domain !== domain) return;\n release(connection.disconnect(connectionId), Event.Disconnected({ connectionId, domain }));\n }, [connection, domain, readOnly, release]);\n\n const retry = useCallback(() => {\n const command = lastCommand.current;\n // Re-inspecting is a read, so it stays; rerunning the last write does not.\n if (readOnly || command === null || command.domain !== domain) load();\n else command.run();\n }, [domain, load, readOnly]);\n\n // One connection of this owner already serves the zone, so the customer has nothing left to\n // decide: the account they granted covers this domain too. Attaching here is what keeps a second\n // domain from meeting the connect dialog again. Each (domain, connection, zone) is tried once,\n // so an attach that failed, or one the customer undid with a detach, is not started over.\n const sighted = useRef<string | null>(null);\n useEffect(() => {\n if (readOnly || state._tag !== \"Disconnected\") return;\n const discovery = state.discovery;\n if (discovery === null || discovery._tag !== \"Resolved\") return;\n const sight = `${domain}|${discovery.connectionId}|${discovery.zone}`;\n if (sighted.current === sight) return;\n sighted.current = sight;\n reuse({ connectionId: discovery.connectionId, zone: discovery.zone });\n }, [domain, readOnly, reuse, state]);\n\n // The card names how many records this domain holds, which only the receipt knows. One read per\n // receipt id: the id changes when an apply lands, and nothing else moves it.\n const [receipt, setReceipt] = useState<Receipt.Model | null>(null);\n const receiptId = snapshotOf(state)?.lastReceiptId ?? null;\n const readReceipt = useRef<string | null>(null);\n useEffect(() => {\n if (receiptId === null) {\n readReceipt.current = null;\n setReceipt(null);\n return;\n }\n if (provisioning === undefined || readReceipt.current === receiptId) return;\n readReceipt.current = receiptId;\n runner.run(provisioning.receipt(Receipt.ReceiptId.make(receiptId)), {\n // A receipt the surface cannot read is one line of copy missing, not a failure the\n // customer has to answer, so the card renders without it.\n onFailure: () => setReceipt(null),\n onSuccess: (value) => setReceipt(value.id === receiptId ? value : null),\n });\n }, [provisioning, receiptId, runner]);\n\n return {\n connect,\n detach,\n disconnect,\n domain,\n established,\n discovery:\n state._tag === \"Disconnected\" || state._tag === \"Failure\" || state._tag === \"Submitting\"\n ? state.discovery\n : null,\n providers: snapshotOf(state)?.providers ?? [],\n receipt: receipt?.id === receiptId ? receipt : null,\n refresh: load,\n retry,\n reuse,\n select,\n snapshot: snapshotOf(state),\n state,\n };\n}\n\n// ---------------------------------------------------------------------------------------------\n// Reading a connection\n// ---------------------------------------------------------------------------------------------\n\n/**\n * Whether a failure is already answered where it was raised: beside the method the customer used.\n * A surface rendering one outcome for the whole flow skips it, so the failure announces once.\n */\nexport const answeredInPlace = (controller: Controller): boolean =>\n controller.state._tag === \"Failure\" && controller.state.attempt !== null;\n\n/**\n * Whether the surface should read as connected: it is, or a command it started is in flight over a\n * connection that was. The provider row and the dialog it opened stay on screen for the length of\n * the command rather than vanishing under the customer half way through it.\n */\nexport const holdsConnection = (controller: Controller): boolean =>\n controller.state._tag === \"Connected\" ||\n (controller.state._tag === \"Submitting\" && controller.snapshot?.status === \"connected\");\n\n/**\n * Whether the provider turned the credential down, so the customer must prove the account again.\n * Proving it re-credits the connection the workspace already holds and leaves its domains where\n * they are, which is why the surface offers a reconnect rather than a second account.\n */\nexport const reconnect = (controller: Controller): boolean =>\n controller.state._tag === \"Reconnect\" ||\n (controller.state._tag === \"Submitting\" && controller.snapshot?.status === \"reconnect\");\n\n/**\n * The provider whose nameservers serve this domain, as the snapshot describes it. Discovery names\n * it by id; without a descriptor there is nothing to draw, so there is no host.\n */\nexport const hostProvider = (controller: Controller): Descriptor | null => {\n const discovery = controller.discovery;\n if (discovery === null || discovery._tag !== \"NotFound\" || discovery.host === null) return null;\n const named = discovery.host.provider;\n return controller.providers.find((entry) => entry.id === named) ?? null;\n};\n\n/** The descriptor for one provider id, or `null` when the snapshot describes no such provider. */\nexport const providerOf = (\n controller: Controller,\n providerId: string | null | undefined,\n): Descriptor | null =>\n providerId == null\n ? null\n : (controller.providers.find((entry) => entry.id === providerId) ?? null);\n\n/** The provider as the customer knows it, falling back to the id when the snapshot has no name. */\nexport const displayName = (controller: Controller, providerId: string): string =>\n providerOf(controller, providerId)?.name ?? providerId;\n\n/**\n * Whether the flow offers a connect surface: only when discovery names a host, always, or never.\n * `never` is a host that decides for itself, such as a domain already ready without DomainKit; a\n * connected domain keeps its status and its disconnect either way.\n */\nexport type Invitation = \"always\" | \"detected\" | \"never\";\n\n/**\n * Whether the connect surface has anything to offer for this domain: a provider that serves the\n * zone, a connection discovery already found, one the owner already holds, or a command already\n * running. Never while a connection is held, which is what `holdsConnection` answers. A host reads\n * it to order its own offers beside DomainKit's rather than competing with them.\n */\nexport const offering = (controller: Controller, connect: Invitation = \"detected\"): boolean => {\n // A surface that holds a connection is not offering one: the connected row is what renders, and\n // a host reading both must never see them claim different things about the same domain.\n if (holdsConnection(controller)) return false;\n const state = controller.state;\n // A command in flight owns the surface whatever discovery found: it is how the customer answers\n // a zone choice, a reconnect, or a redirect that came back.\n if (\n state._tag === \"Submitting\" ||\n state._tag === \"Redirecting\" ||\n state._tag === \"SelectionRequired\" ||\n state._tag === \"Reconnect\"\n ) {\n return true;\n }\n if (connect !== \"detected\") return connect === \"always\";\n const discovery = controller.discovery;\n return (\n hostProvider(controller) !== null ||\n (discovery !== null && discovery._tag !== \"NotFound\") ||\n (controller.snapshot?.reusable.length ?? 0) > 0\n );\n};\n\n/** A connection this owner already holds that would serve the domain, as one list to offer. */\nexport interface Reusable {\n readonly connectionId: string;\n /** The zone the connection would attach, when discovery named one. */\n readonly zone: string | undefined;\n readonly label: string;\n}\n\n/**\n * Every connection the customer can attach without proving anything: the one discovery resolved,\n * the candidates a zone choice is between, and the connections the snapshot lists as reusable.\n */\nexport const reusableConnections = (controller: Controller): ReadonlyArray<Reusable> => {\n const state = controller.state;\n const discovery = controller.discovery;\n const candidates =\n state._tag === \"SelectionRequired\"\n ? state.candidates.map((candidate) => ({ ...candidate, connectionId: state.connectionId }))\n : discovery !== null && discovery._tag === \"SelectionRequired\"\n ? discovery.candidates\n : [];\n const resolved = discovery !== null && discovery._tag === \"Resolved\" ? [discovery] : [];\n return [\n ...resolved.map((entry) => ({\n connectionId: entry.connectionId,\n label: entry.label,\n zone: entry.zone,\n })),\n ...candidates.map((entry) => ({\n connectionId: entry.connectionId,\n label: entry.label,\n zone: entry.zone,\n })),\n ...(controller.snapshot?.reusable ?? []).map((entry) => ({\n connectionId: entry.connectionId,\n label: entry.provider,\n zone: undefined,\n })),\n ];\n};\n\n// ---------------------------------------------------------------------------------------------\n// Reading a provider's methods\n// ---------------------------------------------------------------------------------------------\n\n/** The fields one token method declares, split into what the surface asks for and what it hides. */\nexport interface MethodFields {\n readonly required: ReadonlyArray<Field>;\n /** The fields a provider does not need, which the surface keeps behind a disclosure. */\n readonly optional: ReadonlyArray<Field>;\n /** The field the provider's documentation link explains: the first secret, else the first field. */\n readonly explains: string | null;\n}\n\n/** One declared auth method, with the fields it asks for already arranged. */\nexport interface DescribedMethod {\n readonly kind: Storage.AuthMethod;\n readonly descriptor: MethodDescriptor;\n /** `null` for a method the customer clicks through, which asks for nothing on the page. */\n readonly fields: MethodFields | null;\n}\n\n/** What one provider offers, in the order the descriptor declares it. */\nexport interface DescribedMethods {\n /** The methods the customer clicks through: OAuth and the provider's own integration. */\n readonly interactive: ReadonlyArray<DescribedMethod>;\n /** The methods that ask for credentials on the page. */\n readonly typed: ReadonlyArray<DescribedMethod>;\n /**\n * Both kinds are on offer, so the surface shows the interactive one and a control that opens the\n * token form in its place: one decision at a time rather than a wall of alternatives.\n */\n readonly alternate: boolean;\n}\n\nconst fieldsOf = (method: MethodDescriptor): MethodFields | null => {\n const fields = method.fields;\n if (fields === null) return null;\n const required = fields.filter((field) => field.required);\n const optional = fields.filter((field) => !field.required);\n return {\n explains: (required.find((field) => field.secret) ?? required[0] ?? optional[0])?.name ?? null,\n optional,\n required,\n };\n};\n\n/** One provider's auth methods, arranged for a surface that asks for one decision at a time. */\nexport const describeMethods = (provider: Descriptor): DescribedMethods => {\n const described = provider.methods.map<DescribedMethod>((method) => ({\n descriptor: method,\n fields: fieldsOf(method),\n kind: method.kind,\n }));\n const interactive = described.filter((method) => method.fields === null);\n const typed = described.filter((method) => method.fields !== null);\n return { alternate: interactive.length > 0 && typed.length > 0, interactive, typed };\n};\n\n/**\n * The one field a rejected command was about, if any. A provider that turns down credentials is\n * answering the secret it was given, and it names no field, so the first secret carries the\n * answer; anything else is about the request rather than one input.\n */\nexport const rejectedField = (\n error: DomainKit.Error | null,\n fields: ReadonlyArray<Field>,\n): string | null => {\n if (error === null) return null;\n const reason = error.reason;\n if (reason._tag === \"InvalidInput\") {\n return fields.find((field) => field.name === reason.field)?.name ?? null;\n }\n if (reason._tag !== \"Unauthenticated\" && reason._tag !== \"Forbidden\") return null;\n return fields.find((field) => field.secret)?.name ?? null;\n};\n\n/** Whether a failure was raised by this provider's method, so the form answers beside it. */\nexport const attempted = (\n controller: Controller,\n provider: string,\n method: Storage.AuthMethod,\n): DomainKit.Error | null => {\n const state = controller.state;\n if (state._tag !== \"Failure\" || state.attempt === null) return null;\n return state.attempt.provider === provider && state.attempt.method === method\n ? state.error\n : null;\n};\n","/**\n * What a domain's requirements are, as data: the zone file they spell, the clipboard control a\n * value needs, and the standing one row reports. The table itself is the host's.\n */\nimport { DnsRecord, type Plan } from \"domainkit\";\nimport type { Transport } from \"domainkit/client\";\nimport { useEffect, useRef, useState } from \"react\";\n\nexport type Readiness = Transport.Readiness;\nexport type RequirementStatus = Readiness[\"requirements\"][number][\"status\"];\n\n// ---------------------------------------------------------------------------------------------\n// Zone file\n// ---------------------------------------------------------------------------------------------\n\nconst absolute = (value: string): string => (value.endsWith(\".\") ? value : `${value}.`);\n\nconst textEncoder = new TextEncoder();\n\nconst escapeTxtCharacter = (character: string): string => {\n if (character === '\"' || character === \"\\\\\") return `\\\\${character}`;\n const codePoint = character.codePointAt(0);\n if (codePoint !== undefined && (codePoint < 32 || codePoint === 127)) {\n return `\\\\${codePoint.toString().padStart(3, \"0\")}`;\n }\n return character;\n};\n\n/** TXT strings are capped at 255 bytes each, so long values are split and quoted per chunk. */\nconst txtValue = (value: string): string => {\n const chunks: Array<string> = [];\n let chunk = \"\";\n let byteLength = 0;\n for (const character of value) {\n const characterByteLength = textEncoder.encode(character).byteLength;\n if (byteLength + characterByteLength > 255) {\n chunks.push(chunk);\n chunk = \"\";\n byteLength = 0;\n }\n chunk += escapeTxtCharacter(character);\n byteLength += characterByteLength;\n }\n chunks.push(chunk);\n return chunks.map((part) => `\"${part}\"`).join(\" \");\n};\n\n/** The RR type as a zone file spells it. The tag and the type name are the same string. */\nconst rrType = (record: DnsRecord.Model): string => record._tag;\n\nconst zoneData = (record: DnsRecord.Model): string => {\n switch (record._tag) {\n case \"A\":\n case \"AAAA\":\n return record.address;\n case \"CNAME\":\n return absolute(record.target);\n case \"NS\":\n return absolute(record.nameserver);\n case \"TXT\":\n return txtValue(record.value);\n case \"MX\":\n return `${record.priority} ${absolute(record.exchange)}`;\n case \"CAA\":\n return `${record.flags} ${record.tag} \"${record.value}\"`;\n case \"SRV\":\n return `${record.priority} ${record.weight} ${record.port} ${absolute(record.target)}`;\n }\n};\n\nexport const toZoneFile = (records: ReadonlyArray<DnsRecord.Model>): string =>\n `${records\n .map(\n (record) =>\n `${absolute(record.name)}${record.ttl === null ? \"\" : ` ${record.ttl}`} IN ${rrType(record)} ${zoneData(record)}`,\n )\n .join(\"\\n\")}\\n`;\n\nconst downloadText = (filename: string, contents: string): void => {\n if (typeof document === \"undefined\") return;\n const blob = new Blob([contents], { type: \"text/plain;charset=utf-8\" });\n const url = URL.createObjectURL(blob);\n const anchor = document.createElement(\"a\");\n anchor.download = filename;\n anchor.href = url;\n document.body.append(anchor);\n anchor.click();\n anchor.remove();\n URL.revokeObjectURL(url);\n};\n\nexport const downloadZoneFile = (domain: string, records: ReadonlyArray<DnsRecord.Model>): void =>\n downloadText(`${domain}.txt`, toZoneFile(records));\n\n// ---------------------------------------------------------------------------------------------\n// Copy\n// ---------------------------------------------------------------------------------------------\n\nexport const copyText = (value: string): Promise<boolean> => {\n if (typeof navigator === \"undefined\" || navigator.clipboard === undefined) {\n return Promise.resolve(false);\n }\n return navigator.clipboard.writeText(value).then(\n () => true,\n () => false,\n );\n};\n\nexport interface CopyController {\n readonly copied: boolean;\n readonly copy: () => void;\n}\n\nexport function useCopy(value: string, resetAfter = 2000): CopyController {\n const [copied, setCopied] = useState(false);\n const reset = useRef<ReturnType<typeof setTimeout>>(undefined);\n useEffect(() => () => clearTimeout(reset.current), []);\n return {\n copied,\n copy: () => {\n void copyText(value).then((ok) => {\n if (!ok) return;\n setCopied(true);\n clearTimeout(reset.current);\n reset.current = setTimeout(() => setCopied(false), resetAfter);\n });\n },\n };\n}\n\n/**\n * What a row has to say about one record: while a plan is pending it is what the plan will do to\n * it, and otherwise what the last observation read back.\n */\nexport type Standing =\n | { readonly _tag: \"Operation\"; readonly operation: Plan.Operation }\n | { readonly _tag: \"Readiness\"; readonly status: RequirementStatus };\n\nexport interface Sources {\n /** A plan still awaiting its apply. Pass `null` once one has landed; readiness answers then. */\n readonly plan?: Plan.Model | null | undefined;\n readonly readiness?: Readiness | null | undefined;\n}\n\n/** The row's standing, or `null` when neither a plan nor an observation covers the record. */\nexport const statusOf = (record: DnsRecord.Model, sources: Sources): Standing | null => {\n const operation = sources.plan?.operations.find((entry) =>\n DnsRecord.equals(entry.record, record),\n );\n if (operation !== undefined) return { _tag: \"Operation\", operation };\n const status = sources.readiness?.requirements.find((requirement) =>\n DnsRecord.equals(requirement.record, record),\n )?.status;\n return status === undefined ? null : { _tag: \"Readiness\", status };\n};\n\n/** A stable React key for a requirement: type, name, and data identify a record. */\nexport const identity = (record: DnsRecord.Model): string =>\n [rrType(record), record.name, DnsRecord.data(record)].join(\":\");\n\n/**\n * A requirement set keyed by everything it carries, for memos that decide whether to re-send it.\n * `identity` is deliberately narrower: it answers \"is this the same record\" for a React key, while\n * a plan and an observation are built from `ttl`, `policy`, and `purpose` as well. `policy` in\n * particular decides whether a name may hold anything else, so readiness turns on it.\n */\nexport const requirementsKey = (records: ReadonlyArray<DnsRecord.Model>): string =>\n JSON.stringify(records);\n","import { DnsRecord, type Receipt } from \"domainkit\";\nimport { useCallback } from \"react\";\n\nimport { pendingPlan, planOf, State, useAttempt, type Controller } from \"./attempt.ts\";\nimport { useDomainKit } from \"./domain-kit.tsx\";\nimport { Event } from \"./events.ts\";\nimport { requirementsKey } from \"./records.ts\";\n\nexport { pendingPlan, planOf, State };\nexport type { Controller };\n\nexport interface Options {\n readonly domain: string;\n readonly requirements: ReadonlyArray<DnsRecord.Model>;\n readonly onApplied?: (receipt: Receipt.Model) => void;\n /** Refuse every step. Defaults to the surrounding `readOnly`. */\n readonly readOnly?: boolean;\n}\n\n/**\n * Plan, approve, apply; `approve` authorizes the digest and applies it in the same action.\n * Requirements identify themselves by content, so an inline array does not abandon the attempt.\n * Every field counts: a plan turns on `policy`, and `ttl` and `purpose` ride the wire with it.\n */\nconst keyOf = (domain: string, requirements: ReadonlyArray<DnsRecord.Model>): string =>\n [domain, requirementsKey(requirements)].join(\"|\");\n\nexport function useController({ domain, onApplied, readOnly, requirements }: Options): Controller {\n const { transport } = useDomainKit();\n const group = transport.provisioning;\n return useAttempt({\n domain,\n key: keyOf(domain, requirements),\n done: (receipt) => Event.Applied({ domain, receipt }),\n group,\n onDone: onApplied,\n readOnly,\n plan: useCallback(\n () => (group === undefined ? null : group.plan({ domain, requirements })),\n [domain, group, requirements],\n ),\n });\n}\n","import { DnsRecord, type DomainKit } from \"domainkit\";\nimport type { Transport } from \"domainkit/client\";\nimport * as Data from \"effect/Data\";\nimport * as DateTime from \"effect/DateTime\";\nimport { useCallback, useEffect, useMemo, useRef, useState } from \"react\";\n\nimport { useDomainKit } from \"./domain-kit.tsx\";\nimport { Event } from \"./events.ts\";\nimport { requirementsKey } from \"./records.ts\";\nimport { useRunner } from \"./task.ts\";\n\nexport type Readiness = Transport.Readiness;\nexport type HostEvidence = Readiness[\"host\"][number];\nexport type Requirement = Readiness[\"requirements\"][number];\nexport type Evidence = Requirement[\"evidence\"][number];\n\n/**\n * What the observer read back for the requirement's name, or `null` when it read nothing back at\n * all. Host evidence reports a status the host reached rather than values read off a name, and an\n * `unknown` observation is a lookup that never answered, which is not the same as finding nothing.\n */\nexport const valuesOf = (evidence: Evidence): ReadonlyArray<string> | null =>\n evidence._tag === \"Host\" || evidence.status === \"unknown\" ? null : evidence.values;\n\n/**\n * Readiness rides on the state rather than a ref, so it can never outlive the render that\n * produced it: a controller pointed at a new domain has no readiness in the very first frame.\n */\nexport type State = Data.TaggedEnum<{\n Idle: {};\n Observing: { readonly readiness: Readiness | null };\n Observed: { readonly readiness: Readiness };\n Failure: { readonly error: DomainKit.Error; readonly readiness: Readiness | null };\n}>;\nexport const State = Data.taggedEnum<State>();\n\nconst readinessOf = (state: State): Readiness | null =>\n state._tag === \"Idle\" ? null : state.readiness;\n\nexport interface Controller {\n readonly state: State;\n /** The latest readiness, kept while a new observation runs. */\n readonly readiness: Readiness | null;\n readonly observe: () => void;\n /** Observe again after a failure. */\n readonly retry: () => void;\n /** Whether this controller re-observes at `nextCheckAt` while mounted. */\n readonly polling: boolean;\n}\n\nexport interface Options {\n readonly domain: string;\n /**\n * What to look for. Supplied requirements win over the attachment's latest provisioning receipt,\n * which is what lets a domain with no attachment be verified at all.\n */\n readonly requirements?: ReadonlyArray<DnsRecord.Model>;\n /** Re-observe at each `nextCheckAt` while mounted. Default true. */\n readonly polling?: boolean;\n}\n\n/** Observe once on mount, then follow the readiness's own `nextCheckAt` while polling is on. */\nexport function useController({ domain, polling = true, requirements }: Options): Controller {\n const { emit, revision, transport } = useDomainKit();\n const verification = transport.verification;\n const runner = useRunner();\n const [state, setState] = useState<State>(State.Idle());\n const timer = useRef<ReturnType<typeof setTimeout>>(undefined);\n\n // Requirements identify themselves by content, so a host writing the array inline does not\n // rebuild `observe` on every render and set the mount effect observing in a loop. The key covers\n // every field, because `policy` and `ttl` ride the wire and `policy` decides readiness.\n const signature = requirements === undefined ? null : requirementsKey(requirements);\n const requested = useMemo(\n () => (requirements === undefined ? undefined : { requirements }),\n [signature],\n );\n\n // Readiness belongs to the domain that was observed. Dropping it while rendering, rather than\n // in an effect, keeps the first frame for a new domain free of the previous one's evidence.\n // The domain travels with it, so an answer that arrives after the controller moved refuses\n // itself rather than hanging one domain's evidence under another's name.\n const held = useRef(domain);\n const [observed, setObserved] = useState(domain);\n if (observed !== domain) {\n setObserved(domain);\n held.current = domain;\n setState(State.Idle());\n }\n\n const observe = useCallback(() => {\n if (verification === undefined) return;\n clearTimeout(timer.current);\n setState((previous) => State.Observing({ readiness: readinessOf(previous) }));\n runner.run(\n requested === undefined\n ? verification.observe(domain)\n : verification.observe(domain, requested),\n {\n onFailure: (error) => {\n if (held.current !== domain) return;\n setState((previous) => State.Failure({ error, readiness: readinessOf(previous) }));\n emit(Event.Failed({ domain, error }));\n },\n onSuccess: (readiness) => {\n if (held.current !== domain) return;\n setState(State.Observed({ readiness }));\n },\n },\n );\n }, [domain, emit, requested, runner, verification]);\n\n useEffect(() => {\n observe();\n }, [observe, revision]);\n\n useEffect(() => {\n if (!polling || state._tag !== \"Observed\") return;\n const next = state.readiness.nextCheckAt;\n if (next === null) return;\n const delay = Math.max(0, DateTime.toEpochMillis(next) - Date.now());\n timer.current = setTimeout(observe, delay);\n return () => clearTimeout(timer.current);\n }, [observe, polling, state]);\n\n useEffect(() => () => clearTimeout(timer.current), []);\n\n return {\n observe,\n polling,\n readiness: readinessOf(state),\n retry: observe,\n state,\n };\n}\n","/**\n * The whole lifecycle for one domain in one hook: connect, add the records, observe, clean up.\n * `useFlow` runs the four controllers together and plans as soon as the domain is attached with\n * nothing applied, and again when an observation reads an applied record back missing or wrong, so\n * the styled surface is only markup.\n */\nimport { Receipt, type DnsRecord, type Plan } from \"domainkit\";\nimport type { Transport } from \"domainkit/client\";\nimport * as DateTime from \"effect/DateTime\";\nimport { useCallback, useEffect, useRef } from \"react\";\n\nimport * as Cleanup from \"./cleanup.ts\";\nimport * as Connect from \"./connect.ts\";\nimport { useDomainKit, useReadOnly } from \"./domain-kit.tsx\";\nimport * as Provision from \"./provision.ts\";\nimport { identity, requirementsKey } from \"./records.ts\";\nimport * as Verify from \"./verify.ts\";\n\n/**\n * What DomainKit has to say about this domain. A host reads `connected` and `offering` to order\n * its own offers beside DomainKit's: an offer of its own competes while `offering` is true, and a\n * domain DomainKit holds needs none.\n */\nexport interface FlowState {\n readonly connection: Connect.State[\"_tag\"];\n readonly provisioning: Provision.State[\"_tag\"];\n /**\n * DomainKit holds a connection for this domain, including while a command it started over that\n * connection is still running. `offering` is never true at the same time.\n */\n readonly connected: boolean;\n /** The connect surface has something to offer, so a host's own offer would compete with it. */\n readonly offering: boolean;\n /** Who holds the connection, or whose nameservers serve the zone. */\n readonly provider: string | null;\n /**\n * The account the records go to, as the provider labelled the zone when the domain was attached.\n * `null` until there is an attachment.\n */\n readonly label: string | null;\n /**\n * The apply receipt this domain's latest provisioning attempt produced, which is what cleanup\n * plans from. A host's own \"remove this domain\" surface offers cleanup only when there is one.\n */\n readonly receiptId: Receipt.ReceiptId | null;\n /** `receiptId !== null`: DomainKit applied records here and can prove which. */\n readonly applied: boolean;\n /**\n * The surface may read this domain but not write to it, so a host can say why rather than\n * leaving a customer in front of a page with nothing on it.\n */\n readonly readOnly: boolean;\n}\n\nexport interface FlowOptions {\n readonly domain: string;\n readonly requirements: ReadonlyArray<DnsRecord.Model>;\n /**\n * Offer the connect surface even when discovery names no host, for a host application that lets\n * a customer connect a provider the domain's nameservers do not point at, or `never` for a\n * domain the host has already settled another way. Defaults to `detected`.\n */\n readonly connect?: Connect.Invitation;\n readonly onApplied?: (receipt: Receipt.Model) => void;\n readonly onCleaned?: (receipt: Receipt.Model) => void;\n /**\n * Where an interactive provider flow returns the customer. Defaults to the page they started\n * from; pass `null` to let the server's `defaultReturnTo` decide.\n */\n readonly returnTo?: string | null;\n /** Report this domain's state without the controls that change it. Defaults to the root's. */\n readonly readOnly?: boolean;\n}\n\nexport interface Flow {\n readonly domain: string;\n /** What the host asked for, as the surface renders it row by row. */\n readonly requirements: ReadonlyArray<DnsRecord.Model>;\n readonly state: FlowState;\n readonly connection: Connect.Controller;\n readonly provisioning: Provision.Controller;\n /** Bound to the domain's latest apply receipt, which is the only thing cleanup may undo. */\n readonly cleanup: Cleanup.Controller;\n readonly verification: Verify.Controller;\n /** The plan the rows report, which is one still awaiting its apply. */\n readonly plan: Plan.Model | null;\n readonly readiness: Verify.Readiness | null;\n /** Which capability groups the transport declares, so a surface renders only what it can run. */\n readonly capabilities: ReadonlyArray<Transport.Capability>;\n /** What the flow was told to offer when discovery names no host. */\n readonly invitation: Connect.Invitation;\n}\n\n/** Built from primitives alone, so the memo that reports it depends on exactly those. */\nconst flowState = (input: {\n readonly connected: boolean;\n readonly label: string | null;\n readonly offering: boolean;\n readonly planning: Provision.State[\"_tag\"];\n readonly provider: string | null;\n readonly readOnly: boolean;\n readonly receipt: string | null;\n readonly status: Connect.State[\"_tag\"];\n}): FlowState => ({\n applied: input.receipt !== null,\n connected: input.connected,\n connection: input.status,\n label: input.label,\n offering: input.offering,\n provider: input.provider,\n provisioning: input.planning,\n readOnly: input.readOnly,\n receiptId: input.receipt === null ? null : Receipt.ReceiptId.make(input.receipt),\n});\n\n/**\n * A removal this flow is carrying out, at whatever step it reached. A cleanup that failed halfway\n * has taken records away, and offering them back would contradict what the customer asked for, so\n * the intent stands until the plan is declined or the flow is mounted again.\n */\nconst removing = (cleanup: Cleanup.State): boolean =>\n cleanup._tag !== \"Idle\" && cleanup._tag !== \"Rejecting\" && cleanup._tag !== \"Rejected\";\n\n/**\n * Which records an applied domain lost, keyed by the records themselves rather than by when they\n * were read, so every observation that reports the same drift is one reason to plan. `null` when\n * there is nothing to add back:\n *\n * - the observation was stored before the apply, so it is evidence about a zone from before the\n * records were written rather than about records that went missing since. An observation that\n * read the zone before the apply and stored after it is interrupted instead: the apply starts a\n * new one, and the runner drops whatever it replaced;\n * - this flow is the one taking the records away;\n * - every requirement was found.\n */\nconst driftKey = (\n readiness: Verify.Readiness | null,\n receipt: Receipt.Model | null,\n cleanup: Cleanup.State,\n): string | null => {\n if (readiness === null || receipt === null) return null;\n if (DateTime.isLessThan(readiness.checkedAt, receipt.appliedAt)) return null;\n if (removing(cleanup)) return null;\n const drifted = readiness.requirements\n .filter(({ status }) => status === \"missing\" || status === \"mismatch\")\n .map(({ record, status }) => `${identity(record)} ${status}`)\n .sort();\n return drifted.length === 0 ? null : drifted.join(\"\\n\");\n};\n\nexport function useFlow({\n connect = \"detected\",\n domain,\n onApplied,\n onCleaned,\n readOnly,\n requirements,\n returnTo,\n}: FlowOptions): Flow {\n const { capabilities } = useDomainKit();\n const inherited = useReadOnly();\n const surfaceReadOnly = readOnly ?? inherited;\n // The flow's own flag reaches its controllers, so a read-only domain among writable ones\n // refuses commands rather than only reporting that it should.\n const connection = Connect.useController({\n domain,\n readOnly: surfaceReadOnly,\n ...(returnTo === undefined ? {} : { returnTo }),\n });\n const refresh = connection.refresh;\n // The flow knows what it asked for, so a domain with no attachment can still be verified.\n const verification = Verify.useController({ domain, requirements });\n const observe = verification.observe;\n const provisioning = Provision.useController({\n domain,\n readOnly: surfaceReadOnly,\n onApplied: useCallback(\n (receipt: Receipt.Model) => {\n refresh();\n // The zone holds records it did not a moment ago, so the flow reads it again rather than\n // waiting for the next poll. Observing also interrupts an observation that overlapped the\n // apply, whose evidence is about the zone as it was before the writes landed.\n observe();\n onApplied?.(receipt);\n },\n [observe, onApplied, refresh],\n ),\n requirements,\n });\n const receiptId = connection.snapshot?.lastReceiptId ?? null;\n const cleanup = Cleanup.useController({\n domain,\n readOnly: surfaceReadOnly,\n ...(onCleaned === undefined ? {} : { onCleaned }),\n ...(receiptId === null ? {} : { receiptId: Receipt.ReceiptId.make(receiptId) }),\n });\n\n // The plan is what the table is: an attached domain with nothing applied to it yet has records\n // that are still a proposal, and the rows say so. An applied domain plans again once an\n // observation reads a record back missing or wrong, so a customer whose records were deleted at\n // the provider is offered them again instead of a count of what once landed. The signature is\n // what makes that one call per reason to make it — the domain, the connection that landed, what\n // the host asked for, the receipt, and which records drifted — rather than one per render or one\n // per poll.\n const attached = connection.snapshot?.attachment != null;\n const drift = driftKey(verification.readiness, connection.receipt, cleanup.state);\n const signature =\n surfaceReadOnly ||\n !capabilities.includes(\"provisioning\") ||\n !attached ||\n (receiptId !== null && drift === null)\n ? null\n : [\n domain,\n connection.established,\n requirementsKey(requirements),\n receiptId ?? \"\",\n drift ?? \"\",\n ].join(\"|\");\n const planned = useRef<string | null>(null);\n const buildPlan = provisioning.plan;\n useEffect(() => {\n // A flow that cannot plan forgets what it planned, so pointing it back at a domain it once\n // planned for builds a plan again rather than leaving that domain with none.\n if (signature === null) {\n planned.current = null;\n return;\n }\n if (planned.current === signature) return;\n planned.current = signature;\n buildPlan();\n }, [buildPlan, signature]);\n\n // The same predicates the surface renders on, so the state a host reads and the surface a\n // customer sees never disagree, including while a disconnect is in flight.\n const connected = Connect.holdsConnection(connection);\n const offering = Connect.offering(connection, connect);\n const provider = connection.snapshot?.provider ?? Connect.hostProvider(connection)?.id ?? null;\n return {\n capabilities,\n cleanup,\n connection,\n domain,\n invitation: connect,\n plan: Provision.pendingPlan(provisioning.state),\n provisioning,\n readiness: verification.readiness,\n requirements,\n state: flowState({\n connected,\n label: connection.snapshot?.attachment?.label ?? null,\n offering,\n planning: provisioning.state._tag,\n provider,\n readOnly: surfaceReadOnly,\n receipt: receiptId,\n status: connection.state._tag,\n }),\n verification,\n };\n}\n","/**\n * What a flow says when a step ends badly: a heading the customer reads first, then what to do\n * about it. Both come from the catalog, chosen by the error's reason, so nothing renders a tag,\n * a status literal, or a reason name.\n *\n * const describe = Outcome.useDescribe();\n * const words = describe(error, { provider: \"Cloudflare\" });\n */\nimport type { DomainKit } from \"domainkit\";\n\nimport { useMessages } from \"./domain-kit.tsx\";\nimport type { Catalog, Outcome, OutcomeContext } from \"./messages.ts\";\nimport { outcome } from \"./messages.ts\";\n\nexport type { Outcome, OutcomeContext };\n\n/** The catalog's title and description for one failure. */\nexport const describe = (\n error: DomainKit.Error,\n catalog: Catalog,\n context: OutcomeContext = {},\n): Outcome => outcome(error, catalog, context);\n\n/**\n * `describe` bound to the catalog `DomainKit.Root` holds. The reason alone cannot name the\n * provider a customer typed a token for, so the surface supplies it in the context.\n */\nexport function useDescribe(): (error: DomainKit.Error, context?: OutcomeContext) => Outcome {\n const messages = useMessages();\n return (error, context = {}) => outcome(error, messages, context);\n}\n","/**\n * The fake transport `@domainkit/react` tests render against: an in-memory `domainkit/server`\n * with memory storage and a fake provider, recording every call.\n */\nimport { Testing } from \"domainkit/testing\";\n\nexport const transport = Testing.transport;\nexport type RecordedCall = Testing.RecordedCall;\nexport type RecordingTransport = Testing.RecordingTransport;\nexport type TransportOptions = Testing.TransportOptions;\n","import type { DomainKit } from \"domainkit\";\nimport * as Data from \"effect/Data\";\n\n/**\n * The failed member every controller state shares. It carries the `DomainKit.Error` itself, so a\n * host reads `error.reason`, `error.category`, and `error.isRetryable` instead of parsing text.\n */\nexport type Failure = Data.TaggedEnum<{\n Failure: { readonly error: DomainKit.Error };\n}>;\nexport const Failure = Data.taggedEnum<Failure>();\n\n/** A defect that escaped the transport, in the shape the rest of the UI already handles. */\nexport const isFailure = (state: { readonly _tag: string }): state is Failure =>\n state._tag === \"Failure\";\n"],"mappings":"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"}