@knkcs/contenthub-ui 0.2.0 → 0.3.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.
@@ -0,0 +1 @@
1
+ {"version":3,"file":"heads-dBmqNcOB.js","names":["CHECK_NOTE_MAX","CONTENT_SEARCH_MAX","CHANGE_SET_NAME_MAX","SOURCE_REFERENCE_MAX","BLOCK_REASON_NAME_MAX","ContentBlockedError","contentId","blockReasonId","ContentArchivedError","StatusTransitionRefusedError","input","StaleStatusError","currentStatus","ServiceUnavailableError","message","WithheldWorkError","ChangeSetClosedError","state","BlockReasonNameTakenError","takenName","ContentRefusedError","reasons","PublishRefusedError","blockers","StaleHeadError","CheckResultDeniedError","NameTakenError","RestrictionUnavailableError","GuardianModeRequiredError","feature","AccessDeniedError","CoversReleaseError","coveredReleaseIds","COLLECTION_NAME_MAX","REQUIRED_CHECK_NAME_MAX","MAX_BLUEPRINT_IDS","BLUEPRINT_ACCESSOR_MAX","InvalidInputError","DAY","localToday","pad","n","now","dated","entries","releaseInForceOn","day","last","inForceOnOrAfter","headsOf","out","chain","cs","b","sameHeads","keys","a","k"],"sources":["../src/client/contenthub-client.ts","../src/common/in-force.ts","../src/common/heads.ts"],"sourcesContent":["import type {\n\tBlockReason,\n\tBlueprintInfo,\n\tBlueprintPage,\n\tBlueprintReleaseInfo,\n\tChainPreview,\n\tChangeSet,\n\tChangeSetList,\n\tChangeSetSource,\n\tChangeSetState,\n\tCheckOutcome,\n\tCheckResult,\n\tCheckStanding,\n\tCollection,\n\tCollectionGrant,\n\tCompareBase,\n\tContent,\n\tContentAttributes,\n\tContentDetail,\n\tContentList,\n\tContentTimeline,\n\tContentView,\n\tCopyFrom,\n\tEdge,\n\tFieldResolution,\n\tOutdatedPin,\n\tPendingMerge,\n\tPlannedEnd,\n\tPlannedRelease,\n\tPreviewedContent,\n\tPublishBlocker,\n\tPublishOutcome,\n\tPublishReview,\n\tRecorderGrant,\n\tReferrerList,\n\tRequiredCheck,\n\tRequiredCheckInput,\n\tRequiredCheckRecorders,\n\tRevisionComparison,\n\tRevisionList,\n\tUpdateFromMainOutcome,\n\tValidityPeriod,\n} from \"../types\";\n\n/** The longest note on a Check Result, in characters (internal/changesets.MaxCheckNote). */\nexport const CHECK_NOTE_MAX = 2000;\n\n/** The longest Editor Search, in characters (ContentFilter.search). */\nexport const CONTENT_SEARCH_MAX = 200;\n\n/** The longest Change Set name, in characters (internal/changesets.MaxNameLength). */\nexport const CHANGE_SET_NAME_MAX = 200;\n\n/** The longest Source reference, in characters (internal/changesets.MaxReferenceLength). */\nexport const SOURCE_REFERENCE_MAX = 500;\n\n/**\n * The longest Block Reason name, in characters: the service's limit\n * (internal/workspaceconfig.MaxBlockReasonName), checked here too so a form\n * says so before it asks.\n */\nexport const BLOCK_REASON_NAME_MAX = 200;\n\n/** What `updateChangeSet` changes of a Change Set. */\nexport type ChangeSetUpdateField = \"name\" | \"source\";\n\n/**\n * Everything contenthub-ui's screens ask contenthub, and nothing else: the\n * port a host fills (ADR 0020). `createConnectContenthubClient` is the\n * production implementation; `@knkcs/contenthub-ui/testing` has a stub over\n * an in-memory workspace.\n *\n * Errors the screens act on arrive as the typed errors below, never as a\n * ConnectError the screen would have to pick details out of. Anything else\n * (no permission, the service down) arrives as it came.\n *\n * The workspace is never an argument: contenthub reads it from the caller's\n * token (contenthub ADR 0017), so a host cannot ask about another workspace by\n * mistake.\n */\nexport interface ContenthubClient {\n\t/** The workspace's Block Reasons, by name. */\n\tlistBlockReasons(): Promise<BlockReason[]>;\n\t/**\n\t * Adds a Block Reason. Rejects with `BlockReasonNameTakenError` when the\n\t * workspace already has one of that name, and `InvalidInputError` for a\n\t * name the service refuses (blank, too long, more than one line).\n\t */\n\tcreateBlockReason(input: { name: string }): Promise<BlockReason>;\n\t/** Renames a Block Reason; its id stays. Rejects as `createBlockReason` does. */\n\trenameBlockReason(input: { id: string; name: string }): Promise<BlockReason>;\n\t/** Removes a Block Reason. */\n\tdeleteBlockReason(input: { id: string }): Promise<void>;\n\n\t/**\n\t * Change Sets, newest first, without their Chains, dependencies or\n\t * Planned Releases. Each filter given must hold.\n\t */\n\tlistChangeSets(input?: {\n\t\tstate?: ChangeSetState;\n\t\t/** Only those this odon user is assigned to. */\n\t\tassigneeId?: string;\n\t\t/** Only those with a Chain on this Content. */\n\t\tcontentId?: string;\n\t\t/** At most 200; 50 when absent. */\n\t\tpageSize?: number;\n\t\tpageToken?: string;\n\t}): Promise<ChangeSetList>;\n\t/**\n\t * Opens a Change Set. Rejects with `InvalidInputError` for a name or\n\t * Source the service refuses.\n\t */\n\tcreateChangeSet(input: { name: string; source?: ChangeSetSource }): Promise<ChangeSet>;\n\t/** A Change Set with its Chains, their Branches' heads and its dependencies. */\n\tgetChangeSet(id: string): Promise<ChangeSet>;\n\t/**\n\t * Renames an open Change Set and corrects its Source, as `updateMask`\n\t * says: a field it doesn't name is left as it is, and a masked `source`\n\t * that is absent clears the Source. Rejects with `InvalidInputError` for\n\t * a name or Source the service refuses, and `ChangeSetClosedError` once\n\t * it is published or discarded: the Source freezes at Publish.\n\t */\n\tupdateChangeSet(input: {\n\t\tid: string;\n\t\tupdateMask: ChangeSetUpdateField[];\n\t\tname?: string;\n\t\tsource?: ChangeSetSource;\n\t\t/** Makes a retry safe (CONTEXT.md, Idempotency Key). */\n\t\tidempotencyKey?: string;\n\t}): Promise<ChangeSet>;\n\t/**\n\t * Moves the status label from `expectedStatus` (the status the caller\n\t * saw, \"\" for none) to `status`. Rejects with\n\t * `StatusTransitionRefusedError` when statushub refuses the move,\n\t * `StaleStatusError` when the status moved meanwhile,\n\t * `ChangeSetClosedError` when the Change Set is published or discarded,\n\t * and `ServiceUnavailableError` while statushub can't be reached.\n\t */\n\tsetChangeSetStatus(input: {\n\t\tid: string;\n\t\texpectedStatus: string;\n\t\tstatus: string;\n\t}): Promise<ChangeSet>;\n\t/** Replaces who is working on it: the whole new set of odon user ids. */\n\tsetChangeSetAssignees(input: { id: string; assigneeIds: string[] }): Promise<ChangeSet>;\n\t/**\n\t * Makes the Change Set depend on another open one. Rejects with\n\t * `InvalidInputError` for one that would close a cycle or is closed, and\n\t * `ChangeSetClosedError` when this Change Set itself is closed.\n\t */\n\taddDependency(input: { id: string; dependsOnId: string }): Promise<ChangeSet>;\n\t/** Undoes `addDependency` while the Change Set is open. */\n\tremoveDependency(input: { id: string; dependsOnId: string }): Promise<ChangeSet>;\n\t/**\n\t * Publish's dry run with `reviewedHeads` (Branch id to head Revision id):\n\t * every blocker a Publish with them would be refused with now, and the\n\t * Releases it would cut. Writes nothing. Rejects with `WithheldWorkError`\n\t * when Publish would, for a caller who can't see all of the Change Set.\n\t */\n\tvalidatePublish(input: {\n\t\tid: string;\n\t\treviewedHeads: Record<string, string>;\n\t}): Promise<PublishReview>;\n\t/**\n\t * Publishes the Change Set with exactly `reviewedHeads`: every Branch at\n\t * the head the caller reviewed. Rejects with `PublishRefusedError`\n\t * carrying every blocker when it is refused, `ChangeSetClosedError`\n\t * when it is closed (published with other heads, or discarded), and\n\t * `WithheldWorkError` when it holds work the caller can't see.\n\t */\n\tpublish(input: { id: string; reviewedHeads: Record<string, string> }): Promise<PublishOutcome>;\n\t/**\n\t * Merges what Main (and each dependency) gained since into every Chain\n\t * of the Change Set. A Branch whose merge has Conflicts, or fails its\n\t * Blueprint Release, is left with a Pending Merge, which the Branch\n\t * editor resolves. Rejects with `ChangeSetClosedError` when it is closed,\n\t * and, without `chainId`, `WithheldWorkError` when it holds work the\n\t * caller can't see.\n\t */\n\tupdateFromMain(input: {\n\t\tid: string;\n\t\t/** One of its Chains to update alone; every Chain when absent. */\n\t\tchainId?: string;\n\t\t/** Makes a retry safe (CONTEXT.md, Idempotency Key). */\n\t\tidempotencyKey?: string;\n\t}): Promise<UpdateFromMainOutcome>;\n\t/**\n\t * Closes the Change Set for good without publishing it. Rejects with\n\t * `ChangeSetClosedError` when it is closed already, and\n\t * `WithheldWorkError` when it holds work the caller can't see.\n\t */\n\tdiscardChangeSet(id: string): Promise<ChangeSet>;\n\t/**\n\t * Where every Required Check that applies to the Change Set stands: the\n\t * heads a result recorded now names, its results newest first, and\n\t * whether the latest is stale or clears it.\n\t */\n\tlistCheckResults(changeSetId: string): Promise<CheckStanding[]>;\n\t/**\n\t * Records a Check Result against `heads`, the heads the recorder saw.\n\t * Rejects with `StaleHeadError` when one of them moved,\n\t * `CheckResultDeniedError` when the caller may not record it (an\n\t * independent check's passed or waived from an author of what it\n\t * covers), `InvalidInputError` for what\n\t * the service refuses (a waiver without a note), and\n\t * `ChangeSetClosedError` when the Change Set is closed.\n\t */\n\trecordCheckResult(input: {\n\t\tchangeSetId: string;\n\t\trequiredCheckId: string;\n\t\theads: Record<string, string>;\n\t\toutcome: CheckOutcome;\n\t\tnote: string;\n\t}): Promise<CheckResult>;\n\n\t/** The workspace's Required Checks, by name. */\n\tlistRequiredChecks(): Promise<RequiredCheck[]>;\n\t/**\n\t * Declares a Required Check; it gates every open Change Set at once.\n\t * Rejects with `NameTakenError` when another check has the name, and\n\t * `InvalidInputError` for anything else the service refuses.\n\t */\n\tcreateRequiredCheck(input: RequiredCheckInput): Promise<RequiredCheck>;\n\t/** Replaces every field of a Required Check; its id stays. Rejects as create does. */\n\tupdateRequiredCheck(input: RequiredCheckInput & { id: string }): Promise<RequiredCheck>;\n\t/**\n\t * Removes a Required Check: it stops gating. Its results are kept and\n\t * count for nothing; its recorders' grants go with it. Rejects with\n\t * `ServiceUnavailableError` while Guardian doesn't take that, and nothing\n\t * is removed.\n\t */\n\tdeleteRequiredCheck(input: { id: string }): Promise<void>;\n\t/**\n\t * Who records a Required Check: every member until an admin narrows it\n\t * (ADR 0017's 2026-10-03 amendment). Admin only: rejects with\n\t * `AccessDeniedError` otherwise, and with `GuardianModeRequiredError` in\n\t * `authz.mode: workspace`, where every member records every check and\n\t * nothing narrows it.\n\t */\n\tlistRequiredCheckRecorders(requiredCheckId: string): Promise<RequiredCheckRecorders>;\n\t/**\n\t * Makes a member, or every member, a recorder of a Required Check. The\n\t * caller may grant themselves: an admin records a check only when\n\t * granted (break-glass, announced like any grant). Rejects as\n\t * `listRequiredCheckRecorders` does, with `InvalidInputError` for a\n\t * grantee who is not a member, and `ServiceUnavailableError` while\n\t * Guardian doesn't take the grant.\n\t */\n\tgrantRequiredCheckRecorder(input: {\n\t\trequiredCheckId: string;\n\t\trecorder: RecorderGrant;\n\t}): Promise<void>;\n\t/**\n\t * Takes recorder from a person, or from every member, which narrows the\n\t * check to the people granted by name. Rejects as grant does.\n\t */\n\trevokeRequiredCheckRecorder(input: {\n\t\trequiredCheckId: string;\n\t\trecorder: RecorderGrant;\n\t}): Promise<void>;\n\n\t/** Every Collection of the workspace, by name, then id: a tree by `parentId`. */\n\tlistCollections(): Promise<Collection[]>;\n\t/**\n\t * Creates a Collection at the root or under `parentId`. Rejects with\n\t * `NameTakenError` for a sibling of the same name, `InvalidInputError` for\n\t * a name the service refuses, and `RestrictionUnavailableError` for a\n\t * restricted one in workspace mode.\n\t */\n\tcreateCollection(input: {\n\t\tname: string;\n\t\tparentId?: string;\n\t\trestricted?: boolean;\n\t}): Promise<Collection>;\n\t/** Renames a Collection, keeping its place and filing. Rejects as create does. */\n\trenameCollection(input: { id: string; name: string }): Promise<Collection>;\n\t/**\n\t * Moves a Collection, with everything under it, under `parentId` (\"\" for\n\t * the root). Rejects with `InvalidInputError` for a move under itself, and\n\t * `NameTakenError` for a sibling of the same name there, whose\n\t * `takenName` is \"\": the request carries no name.\n\t */\n\tmoveCollection(input: { id: string; parentId: string }): Promise<Collection>;\n\t/**\n\t * Removes a Collection and unfiles its Content, answering the Content it\n\t * unfiled. Rejects with `InvalidInputError` while Collections sit under it.\n\t */\n\tremoveCollection(input: { id: string }): Promise<string[]>;\n\t/**\n\t * Restricts a Collection (the caller becomes its owner), or opens it\n\t * again, which discloses its Content to every viewer and so needs\n\t * `acknowledgeDisclosure`; opening it clears its grants. Rejects with\n\t * `RestrictionUnavailableError` in workspace mode, and\n\t * `InvalidInputError` for an unacknowledged disclosure.\n\t */\n\tsetCollectionRestricted(input: {\n\t\tid: string;\n\t\trestricted: boolean;\n\t\tacknowledgeDisclosure?: boolean;\n\t}): Promise<Collection>;\n\t/**\n\t * Who is granted on a Restricted Collection, its owner included. Rejects\n\t * with `AccessDeniedError` unless the caller is its owner or an admin, and\n\t * `RestrictionUnavailableError` in workspace mode.\n\t */\n\tlistCollectionGrants(collectionId: string): Promise<CollectionGrant[]>;\n\t/**\n\t * Grants a member viewer or editor on a Restricted Collection, replacing\n\t * what they held. The caller may grant themselves (break-glass, announced\n\t * like any grant). Rejects as `listCollectionGrants` does, and with\n\t * `InvalidInputError` for a grantee who is not a member or an open\n\t * Collection.\n\t */\n\tgrantCollectionAccess(input: {\n\t\tcollectionId: string;\n\t\tuserId: string;\n\t\tlevel: \"viewer\" | \"editor\";\n\t}): Promise<void>;\n\t/** Takes a person's grant on a Restricted Collection. Rejects as grant does. */\n\trevokeCollectionAccess(input: { collectionId: string; userId: string }): Promise<void>;\n\t/**\n\t * Content in one view, ordered by id (then Branch, for a search), each\n\t * filter given holding. Rejects with `InvalidInputError` for a search in\n\t * the In Force view, which Editor Search never covers (ADR 0019), and for\n\t * a search the service refuses.\n\t */\n\tlistContents(input?: {\n\t\t/** Main when absent. */\n\t\tview?: ContentView;\n\t\t/**\n\t\t * Only Content filed directly in this Collection, not in Collections\n\t\t * under it.\n\t\t */\n\t\tcollectionId?: string;\n\t\t/** Editor Search: a name, number or phrase, letter for letter but ignoring case. */\n\t\tsearch?: string;\n\t\t/**\n\t\t * Only Content of one of these Blueprints, filtered by the service so\n\t\t * that every page but the last is full; empty or absent for every\n\t\t * Blueprint. At most 100.\n\t\t */\n\t\tblueprintIds?: string[];\n\t\t/** Only Content this user maintains: one of its assignees. */\n\t\tassigneeId?: string;\n\t\t/** At most 200; 50 when absent. */\n\t\tpageSize?: number;\n\t\tpageToken?: string;\n\t}): Promise<ContentList>;\n\t/**\n\t * A page of the workspace's content Blueprints Content can be made from:\n\t * not archived, with at least one Release, whose accessor or name holds\n\t * `query`. contenthub asks blueprinthub as the caller (#238). Rejects\n\t * with `ServiceUnavailableError` while blueprinthub gives no answer.\n\t */\n\tsearchBlueprints(input: {\n\t\tquery: string;\n\t\tpageToken?: string;\n\t\tsignal?: AbortSignal;\n\t}): Promise<BlueprintPage>;\n\t/**\n\t * Every Release of a Blueprint, newest first, each with contenthub's\n\t * answer: `refusals` is empty when Content can pin it. Empty for a\n\t * Blueprint the workspace doesn't have. Rejects with\n\t * `ServiceUnavailableError` while blueprinthub gives no answer.\n\t */\n\tlistBlueprintReleases(blueprintId: string): Promise<BlueprintReleaseInfo[]>;\n\t/**\n\t * Names the Blueprints of these ids, archived ones and ones without a\n\t * Release included, so existing Content stays readable after its\n\t * Blueprint is retired (#241). An unknown id, or one of another\n\t * workspace, is left out. At most `MAX_BLUEPRINT_IDS`. Rejects with\n\t * `ServiceUnavailableError` while blueprinthub gives no answer.\n\t */\n\tgetBlueprints(ids: string[]): Promise<BlueprintInfo[]>;\n\t/**\n\t * Creates a Content in an open Change Set, pinning a Blueprint Release,\n\t * with empty data: its one Chain has one Branch, opened in the Branch\n\t * editor. Rejects with `ChangeSetClosedError` for a closed Change Set,\n\t * `ContentRefusedError` for a Release contenthub can't load or empty data\n\t * the Release refuses (a required field), and `InvalidInputError` for\n\t * anything else the service refuses.\n\t */\n\tcreateContent(input: {\n\t\tchangeSetId: string;\n\t\t/** May be \"\" with `copyFrom`, to pin what the source pins. */\n\t\tblueprintReleaseId: string;\n\t\t/** Duplicate: the new Content's first Revision takes this source's data. */\n\t\tcopyFrom?: CopyFrom;\n\t}): Promise<Content>;\n\t/**\n\t * Saves a new Revision on a Branch of an open Change Set, on top of\n\t * `expectedHeadId`, the head the editor loaded (ADR 0003). With\n\t * `fieldMask` the save is partial: each top-level field it names takes\n\t * its value in `data`, or is removed when `data` doesn't hold it, and\n\t * every other field is carried over from the head. Answers the Content\n\t * as read in the Change Set afterwards.\n\t *\n\t * Rejects with `StaleHeadError` when the head moved (nothing is written,\n\t * and nothing is merged: ADR 0020), `ContentRefusedError` with one reason\n\t * per Violation the data breaks, `ContentBlockedError` or\n\t * `ContentArchivedError` for Content closed to the caller,\n\t * `ChangeSetClosedError` for a closed Change Set, and `InvalidInputError`\n\t * for anything else the service refuses.\n\t */\n\tsaveRevision(input: {\n\t\t/** The Branch's Change Set, which a closed refusal names. */\n\t\tchangeSetId: string;\n\t\tbranchId: string;\n\t\texpectedHeadId: string;\n\t\tdata: Record<string, unknown>;\n\t\t/** Top-level field accessors; absent saves `data` as the whole Revision. */\n\t\tfieldMask?: string[];\n\t\t/**\n\t\t * Makes a retry safe (CONTEXT.md, Idempotency Key): sent again with\n\t\t * the same request, it answers the first save and writes nothing.\n\t\t */\n\t\tidempotencyKey?: string;\n\t}): Promise<Content>;\n\n\t/**\n\t * One Content with its Blueprint Release and attributes: on Main, or\n\t * inside `changeSetId`, at the head of its Chain's last Branch, or of\n\t * `branchId`, a Branch of that Chain, when given (#252). Content born in\n\t * an open Change Set exists only there, so read anywhere else it is a\n\t * NotFound ConnectError, as is a Branch outside the Chain.\n\t */\n\tgetContent(input: {\n\t\tid: string;\n\t\tchangeSetId?: string;\n\t\tbranchId?: string;\n\t}): Promise<ContentDetail>;\n\t/** Its Timeline, with the Planned Releases of open Change Sets beside it. */\n\tgetTimeline(contentId: string): Promise<ContentTimeline>;\n\t/**\n\t * Revisions, newest first: every one of a published Content, or those of\n\t * one Branch (the only way to list those of Content born in an open\n\t * Change Set).\n\t */\n\tlistRevisions(input: {\n\t\ttarget: { contentId: string } | { branchId: string };\n\t\tpageSize?: number;\n\t\tpageToken?: string;\n\t}): Promise<RevisionList>;\n\t/** How `revisionId` differs from a base, field by field. */\n\tcompare(input: { revisionId: string; base: CompareBase }): Promise<RevisionComparison>;\n\t/** The outgoing edges of one Revision, its own only. */\n\tlistReferences(input: { contentId: string; revisionId: string }): Promise<Edge[]>;\n\t/**\n\t * One page of the edges pointing at a Content from Releases In Force\n\t * today and, asked, open Branch heads: Releases first, then Change Sets.\n\t */\n\tlistReferrers(input: {\n\t\tcontentId: string;\n\t\tincludeOpenChangeSets?: boolean;\n\t\t/** 100 when absent; above 1000 reads as 1000. */\n\t\tpageSize?: number;\n\t\tpageToken?: string;\n\t}): Promise<ReferrerList>;\n\t/** The pinned edges of a Branch head or a Revision that are outdated today. */\n\tlistOutdatedPins(input: { branchId: string } | { revisionId: string }): Promise<OutdatedPin[]>;\n\n\t/** Files a Content in exactly these Collections: no save, no Revision (ADR 0015). Answers its Collections. */\n\tsetContentCollections(input: { contentId: string; collectionIds: string[] }): Promise<string[]>;\n\t/** Replaces who maintains a Content: no save, no Revision. */\n\tsetContentAssignees(input: {\n\t\tcontentId: string;\n\t\tassigneeIds: string[];\n\t}): Promise<ContentAttributes>;\n\t/** Blocks a Content, replacing any Block it has. */\n\tblockContent(input: {\n\t\tcontentId: string;\n\t\tblockReasonId: string;\n\t\tallowedUserIds: string[];\n\t}): Promise<ContentAttributes>;\n\tunblockContent(contentId: string): Promise<ContentAttributes>;\n\t/**\n\t * Archives a published Content with no Release In Force today or later.\n\t * Rejects with `InvalidInputError` for any other, with the service's reason.\n\t */\n\tarchiveContent(contentId: string): Promise<ContentAttributes>;\n\tunarchiveContent(contentId: string): Promise<ContentAttributes>;\n\n\t/**\n\t * Starts a Chain on a published Content, in `changeSetId` or in a new\n\t * Change Set named `changeSetName` (after the Content when empty).\n\t * Answers the Change Set and the Content as read on the Branch to edit.\n\t * Rejects with `ContentBlockedError`, `ContentArchivedError`,\n\t * `ChangeSetClosedError`, and `InvalidInputError` for anything else the\n\t * service refuses (a missing or needless effective date).\n\t */\n\tstartEditing(input: {\n\t\tcontentId: string;\n\t\tchangeSetId?: string;\n\t\t/** YYYY-MM-DD: required for Dated Content, refused for undated. */\n\t\teffectiveOn?: string;\n\t\tchangeSetName?: string;\n\t}): Promise<{ changeSet: ChangeSet; content: Content }>;\n\t/** What a Chain on Dated Content, effective on a date, would fork from and meet. */\n\tpreviewChain(input: {\n\t\tchangeSetId: string;\n\t\tcontentId: string;\n\t\teffectiveOn: string;\n\t\t/** The period to meet the Content's Releases with; from `effectiveOn`, open, when absent. */\n\t\tvalidityPeriod?: ValidityPeriod;\n\t}): Promise<ChainPreview>;\n\t/**\n\t * Plans the Release Publish will cut of an editorial Branch's head, with\n\t * its Validity Period (required for Dated Content, refused for undated)\n\t * and Release Spec values. Rejects with `ContentRefusedError` for Release\n\t * Spec values the Blueprint Release refuses, `CoversReleaseError` when\n\t * the period would cover a Release entirely, and as any edit does.\n\t */\n\tplanRelease(input: {\n\t\tchangeSetId: string;\n\t\tbranchId: string;\n\t\tvalidityPeriod?: ValidityPeriod;\n\t\treleaseSpec?: Record<string, unknown>;\n\t\tsupersedesReleaseIds?: string[];\n\t\tidempotencyKey?: string;\n\t}): Promise<PlannedRelease>;\n\t/**\n\t * Changes a Planned Release: each part given replaces what it had, each\n\t * absent keeps it. The Change Set's proposals are derived again. Rejects\n\t * as `planRelease` does, and with `InvalidInputError` for a proposal.\n\t */\n\tupdatePlannedRelease(input: {\n\t\tchangeSetId: string;\n\t\tplannedReleaseId: string;\n\t\tvalidityPeriod?: ValidityPeriod;\n\t\treleaseSpec?: Record<string, unknown>;\n\t\tsupersedesReleaseIds?: string[];\n\t\tidempotencyKey?: string;\n\t}): Promise<PlannedRelease>;\n\t/**\n\t * Adds an editorial Branch to a Chain on Dated Content, for a later\n\t * date. Answers the Change Set and the new Branch's id. Rejects with\n\t * `InvalidInputError` for a date not after the Chain's last editorial\n\t * Branch's, or a Chain without dates.\n\t */\n\tappendBranch(input: {\n\t\tchangeSetId: string;\n\t\tchainId: string;\n\t\teffectiveOn: string;\n\t\tidempotencyKey?: string;\n\t}): Promise<{ changeSet: ChangeSet; branchId: string }>;\n\t/**\n\t * Removes a Chain from an open Change Set with its Planned Releases; its\n\t * Revisions stay in history. Rejects with `InvalidInputError` for the\n\t * Chain of Content born in the Change Set.\n\t */\n\tdropChain(input: {\n\t\tchangeSetId: string;\n\t\tchainId: string;\n\t\tidempotencyKey?: string;\n\t}): Promise<ChangeSet>;\n\t/** The Pending Merge on a Branch, with what its resolution decides; null for none. */\n\tgetPendingMerge(branchId: string): Promise<PendingMerge | null>;\n\t/**\n\t * Resolves the Pending Merge on a Branch field by field, as a merge\n\t * Revision that becomes its head. Rejects with `StaleHeadError` when the\n\t * head moved, `ContentRefusedError` when the result fails the Blueprint\n\t * Release, and `InvalidInputError` for a field undecided or a Branch\n\t * without a Pending Merge.\n\t */\n\tresolveMerge(input: {\n\t\tchangeSetId: string;\n\t\tbranchId: string;\n\t\texpectedHeadId: string;\n\t\tresolutions: FieldResolution[];\n\t\tidempotencyKey?: string;\n\t}): Promise<Content>;\n\t/** Drops the Pending Merge on a Branch, which stays behind its base. */\n\tabortMerge(input: {\n\t\tchangeSetId: string;\n\t\tbranchId: string;\n\t\tidempotencyKey?: string;\n\t}): Promise<void>;\n\t/**\n\t * Preview: the Content as In Force on `validOn` (today when absent) if\n\t * the open Change Set were published now (ReleaseService's\n\t * preview_change_set); null when nothing is In Force then.\n\t */\n\tpreviewInForce(input: {\n\t\tcontentId: string;\n\t\tchangeSetId: string;\n\t\tvalidOn?: string;\n\t}): Promise<PreviewedContent | null>;\n\t/** Plans a Repeal of Dated Content ending on `lastDay`. */\n\tplanRepeal(input: {\n\t\tchangeSetId: string;\n\t\tcontentId: string;\n\t\tlastDay: string;\n\t}): Promise<PlannedEnd>;\n\t/** Plans a Withdrawal of undated Content. */\n\tplanWithdrawal(input: { changeSetId: string; contentId: string }): Promise<PlannedEnd>;\n}\n\n/** The Content is blocked, and its Block doesn't allow the caller. */\nexport class ContentBlockedError extends Error {\n\treadonly contentId: string;\n\treadonly blockReasonId: string;\n\tconstructor(contentId: string, blockReasonId: string) {\n\t\tsuper(`Content ${contentId} is blocked`);\n\t\tthis.name = \"ContentBlockedError\";\n\t\tthis.contentId = contentId;\n\t\tthis.blockReasonId = blockReasonId;\n\t}\n}\n\n/** The Content is Archived: unarchive it before editing it. */\nexport class ContentArchivedError extends Error {\n\treadonly contentId: string;\n\tconstructor(contentId: string) {\n\t\tsuper(`Content ${contentId} is archived`);\n\t\tthis.name = \"ContentArchivedError\";\n\t\tthis.contentId = contentId;\n\t}\n}\n\n/** statushub refused a status move: its reason is fit to show. */\nexport class StatusTransitionRefusedError extends Error {\n\treadonly fromStatus: string;\n\treadonly toStatus: string;\n\t/** statushub's reason, as it gave it. */\n\treadonly reason: string;\n\t/** A guarded move, which this caller may not make. */\n\treadonly requiresPermission: boolean;\n\tconstructor(input: {\n\t\tfromStatus: string;\n\t\ttoStatus: string;\n\t\treason: string;\n\t\trequiresPermission: boolean;\n\t}) {\n\t\tsuper(input.reason || `the move from \"${input.fromStatus}\" to \"${input.toStatus}\" was refused`);\n\t\tthis.name = \"StatusTransitionRefusedError\";\n\t\tthis.fromStatus = input.fromStatus;\n\t\tthis.toStatus = input.toStatus;\n\t\tthis.reason = input.reason;\n\t\tthis.requiresPermission = input.requiresPermission;\n\t}\n}\n\n/** The status moved since the caller saw it: choose again from `currentStatus`. */\nexport class StaleStatusError extends Error {\n\t/** \"\" for an unknown status. */\n\treadonly currentStatus: string;\n\tconstructor(currentStatus: string) {\n\t\tsuper(`the status is now \"${currentStatus}\"`);\n\t\tthis.name = \"StaleStatusError\";\n\t\tthis.currentStatus = currentStatus;\n\t}\n}\n\n/** A service the call needs can't be reached now: retry it unchanged. */\nexport class ServiceUnavailableError extends Error {\n\tconstructor(message: string) {\n\t\tsuper(message);\n\t\tthis.name = \"ServiceUnavailableError\";\n\t}\n}\n\n/**\n * The Change Set holds work the caller can't see: Content filed in a\n * Restricted Collection they aren't granted on (ADR 0017). Publishing,\n * discarding or updating all of it is refused, naming no Content. Read from\n * the refusal's typed WithheldWork detail, not its text.\n */\nexport class WithheldWorkError extends Error {\n\tconstructor(message: string) {\n\t\tsuper(message);\n\t\tthis.name = \"WithheldWorkError\";\n\t}\n}\n\n/** The Change Set is published or discarded, and closed for good. */\nexport class ChangeSetClosedError extends Error {\n\treadonly state: ChangeSetState;\n\tconstructor(state: ChangeSetState) {\n\t\tsuper(`the Change Set is ${state}`);\n\t\tthis.name = \"ChangeSetClosedError\";\n\t\tthis.state = state;\n\t}\n}\n\n/** Another Block Reason of the workspace already has this name. */\nexport class BlockReasonNameTakenError extends Error {\n\t/** The name asked for, which another Block Reason has. */\n\treadonly takenName: string;\n\tconstructor(takenName: string) {\n\t\tsuper(`a Block Reason named \"${takenName}\" already exists`);\n\t\tthis.name = \"BlockReasonNameTakenError\";\n\t\tthis.takenName = takenName;\n\t}\n}\n\n/** One reason contenthub refused a write, as the rule's owner gave it. */\nexport interface RefusalReason {\n\t/** Whose rule: \"fieldkit\", \"knkeditor\", \"format\" or \"contenthub\". */\n\tsource: string;\n\t/** The rule's own code, such as fieldkit's \"required\". */\n\tcode: string;\n\t/** A /-separated location, such as \"/title\"; \"\" for the whole. */\n\tpath: string;\n}\n\n/**\n * contenthub refused a Revision's data, a new Content's first or a save's:\n * it breaks the Blueprint Release's rules, or the Release can't be loaded.\n * `reasons` names each, as its owner gave it.\n */\nexport class ContentRefusedError extends Error {\n\treadonly reasons: RefusalReason[];\n\tconstructor(message: string, reasons: RefusalReason[]) {\n\t\tsuper(message);\n\t\tthis.name = \"ContentRefusedError\";\n\t\tthis.reasons = reasons;\n\t}\n}\n\n/**\n * Publish was refused: nothing was written. `blockers` names every reason\n * at once, so the editor fixes them in one pass (ADR 0015).\n */\nexport class PublishRefusedError extends Error {\n\treadonly blockers: PublishBlocker[];\n\tconstructor(blockers: PublishBlocker[]) {\n\t\tsuper(`Publish was refused for ${blockers.length} reason(s)`);\n\t\tthis.name = \"PublishRefusedError\";\n\t\tthis.blockers = blockers;\n\t}\n}\n\n/** A head the call named has moved since: read again and retry on `currentHeadId`. */\nexport class StaleHeadError extends Error {\n\treadonly contentId: string;\n\t/** \"\" for a Branch-less Planned Release's Revision. */\n\treadonly branchId: string;\n\treadonly expectedHeadId: string;\n\treadonly currentHeadId: string;\n\tconstructor(input: {\n\t\tcontentId: string;\n\t\tbranchId: string;\n\t\texpectedHeadId: string;\n\t\tcurrentHeadId: string;\n\t}) {\n\t\tsuper(`the head moved from ${input.expectedHeadId} to ${input.currentHeadId}`);\n\t\tthis.name = \"StaleHeadError\";\n\t\tthis.contentId = input.contentId;\n\t\tthis.branchId = input.branchId;\n\t\tthis.expectedHeadId = input.expectedHeadId;\n\t\tthis.currentHeadId = input.currentHeadId;\n\t}\n}\n\n/**\n * The caller may not record this result; `message` is the service's reason.\n * Mostly an independent Required Check's passed or waived from someone who\n * authored what it covers (ADR 0014), who may record failed only; also a\n * caller without the right to record the check at all.\n */\nexport class CheckResultDeniedError extends Error {\n\tconstructor(message: string) {\n\t\tsuper(message);\n\t\tthis.name = \"CheckResultDeniedError\";\n\t}\n}\n\n/**\n * Another Required Check, or a sibling Collection, already has this name.\n * The service's refusal carries no detail; the client knows what it sent.\n */\nexport class NameTakenError extends Error {\n\t/** The name asked for, trimmed. */\n\treadonly takenName: string;\n\tconstructor(takenName: string) {\n\t\tsuper(`\"${takenName}\" is taken`);\n\t\tthis.name = \"NameTakenError\";\n\t\tthis.takenName = takenName;\n\t}\n}\n\n/**\n * Restricted Collections need `authz.mode: guardian`: in workspace mode\n * nothing could enforce a restriction, so contenthub refuses every\n * restriction and grant (ADR 0017). No RPC says which mode runs, so the\n * screens learn it from this refusal, read from its GuardianModeRequired\n * detail (feature \"collection_restriction\"), not its text.\n */\nexport class RestrictionUnavailableError extends Error {\n\tconstructor(message: string) {\n\t\tsuper(message);\n\t\tthis.name = \"RestrictionUnavailableError\";\n\t}\n}\n\n/**\n * What was asked needs `authz.mode: guardian`; this contenthub runs in\n * workspace mode (ADR 0017). Read from the refusal's typed\n * GuardianModeRequired detail, not its text. `feature` names what was\n * refused: \"required_check_recorders\" for narrowing who records a check,\n * where every member records every check. Collection restriction's feature\n * comes as `RestrictionUnavailableError` instead.\n */\nexport class GuardianModeRequiredError extends Error {\n\treadonly feature: string;\n\tconstructor(feature: string, message: string) {\n\t\tsuper(message);\n\t\tthis.name = \"GuardianModeRequiredError\";\n\t\tthis.feature = feature;\n\t}\n}\n\n/** The caller may not do this; `message` is the service's reason. */\nexport class AccessDeniedError extends Error {\n\tconstructor(message: string) {\n\t\tsuper(message);\n\t\tthis.name = \"AccessDeniedError\";\n\t}\n}\n\n/**\n * A plan's Validity Period would cover these Releases of its Content\n * entirely: nothing was planned. Supersede them, or change the dates.\n */\nexport class CoversReleaseError extends Error {\n\treadonly contentId: string;\n\treadonly coveredReleaseIds: string[];\n\tconstructor(contentId: string, coveredReleaseIds: string[]) {\n\t\tsuper(`the Validity Period covers ${coveredReleaseIds.join(\", \")} entirely`);\n\t\tthis.name = \"CoversReleaseError\";\n\t\tthis.contentId = contentId;\n\t\tthis.coveredReleaseIds = coveredReleaseIds;\n\t}\n}\n\n/** The longest Collection name, in characters (internal/collections.MaxNameLength). */\nexport const COLLECTION_NAME_MAX = 200;\n\n/** The longest Required Check name, in characters (internal/workspaceconfig.MaxRequiredCheckName). */\nexport const REQUIRED_CHECK_NAME_MAX = 200;\n\n/** The most ids one `getBlueprints` takes (internal/blueprintcatalog.MaxBlueprintIDs). */\nexport const MAX_BLUEPRINT_IDS = 1000;\n\n/** The longest Blueprint accessor a check names (internal/workspaceconfig.MaxBlueprintAccessor). */\nexport const BLUEPRINT_ACCESSOR_MAX = 200;\n\n/** The service refused a value; `message` is its guidance, fit to show. */\nexport class InvalidInputError extends Error {\n\tconstructor(message: string) {\n\t\tsuper(message);\n\t\tthis.name = \"InvalidInputError\";\n\t}\n}\n","import type { TimelineEntry } from \"../types\";\n\n/** A day as the service spells it: YYYY-MM-DD. */\nexport const DAY = /^\\d{4}-\\d{2}-\\d{2}$/;\n\n/**\n * Today as YYYY-MM-DD in the browser's time zone. The workspace's own time\n * zone decides In Force on the service; the page only uses this to choose\n * what to offer, and the service has the last word.\n */\nexport function localToday(now: Date = new Date()): string {\n\tconst pad = (n: number) => String(n).padStart(2, \"0\");\n\treturn `${now.getFullYear()}-${pad(now.getMonth() + 1)}-${pad(now.getDate())}`;\n}\n\n/** Whether the Timeline is a Dated Content's: its Releases carry Validity Periods. */\nfunction dated(entries: TimelineEntry[]): boolean {\n\treturn entries.some((e) => e.validityPeriod);\n}\n\n/**\n * The Release In Force on `day`, as the Timeline known now gives it: for\n * Dated Content the one whose Validity Period covers the day, for undated\n * Content the latest one, unless a Withdrawal ended its force. Undefined in\n * a gap, before the first Release, or for Content never published.\n */\nexport function releaseInForceOn(entries: TimelineEntry[], day: string): TimelineEntry | undefined {\n\tif (dated(entries)) {\n\t\treturn entries.find(\n\t\t\t(e) =>\n\t\t\t\te.validityPeriod &&\n\t\t\t\te.validityPeriod.firstDay <= day &&\n\t\t\t\t(e.validityPeriod.lastDay === \"\" || day <= e.validityPeriod.lastDay),\n\t\t);\n\t}\n\tconst last = entries.at(-1);\n\treturn last && last.kind !== \"withdrawal\" ? last : undefined;\n}\n\n/**\n * Whether any Release is In Force on `day` or later: what ArchiveContent\n * refuses (ADR 0015), since archiving a live law would hide it from the\n * editors who maintain it. A Repeal is In Force up to its last day.\n */\nexport function inForceOnOrAfter(entries: TimelineEntry[], day: string): boolean {\n\tif (dated(entries)) {\n\t\treturn entries.some(\n\t\t\t(e) =>\n\t\t\t\te.validityPeriod && (e.validityPeriod.lastDay === \"\" || e.validityPeriod.lastDay >= day),\n\t\t);\n\t}\n\treturn releaseInForceOn(entries, day) !== undefined;\n}\n","import type { ChangeSet } from \"../types\";\n\n/**\n * Every Branch of a Change Set at its head, Branch id to Revision id: the\n * heads a Publish reviews, and that `reviewed_heads` must name exactly.\n */\nexport function headsOf(cs: ChangeSet): Record<string, string> {\n\tconst out: Record<string, string> = {};\n\tfor (const chain of cs.chains) {\n\t\tfor (const b of chain.branches) out[b.id] = b.headRevisionId;\n\t}\n\treturn out;\n}\n\n/** The same heads, Branch for Branch. */\nexport function sameHeads(a: Record<string, string>, b: Record<string, string>): boolean {\n\tconst keys = Object.keys(a);\n\treturn keys.length === Object.keys(b).length && keys.every((k) => b[k] === a[k]);\n}\n"],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -330,6 +330,11 @@ export declare interface ChangeSetStatusInfo {
330
330
  name: string;
331
331
  /** Its colour as statushub holds it (a CSS colour); absent for none. */
332
332
  color?: string;
333
+ /**
334
+ * statushub's default for the catalogue: what a Change Set without a
335
+ * status reads as (ADR 0014 D9). At most one status has it.
336
+ */
337
+ isDefault?: boolean;
333
338
  }
334
339
 
335
340
  /** What `updateChangeSet` changes of a Change Set. */
@@ -852,6 +857,14 @@ export declare interface ContenthubClient {
852
857
  * `ServiceUnavailableError` while blueprinthub gives no answer.
853
858
  */
854
859
  listBlueprintReleases(blueprintId: string): Promise<BlueprintReleaseInfo[]>;
860
+ /**
861
+ * Names the Blueprints of these ids, archived ones and ones without a
862
+ * Release included, so existing Content stays readable after its
863
+ * Blueprint is retired (#241). An unknown id, or one of another
864
+ * workspace, is left out. At most `MAX_BLUEPRINT_IDS`. Rejects with
865
+ * `ServiceUnavailableError` while blueprinthub gives no answer.
866
+ */
867
+ getBlueprints(ids: string[]): Promise<BlueprintInfo[]>;
855
868
  /**
856
869
  * Creates a Content in an open Change Set, pinning a Blueprint Release,
857
870
  * with empty data: its one Chain has one Branch, opened in the Branch
@@ -898,12 +911,15 @@ export declare interface ContenthubClient {
898
911
  }): Promise<Content>;
899
912
  /**
900
913
  * One Content with its Blueprint Release and attributes: on Main, or
901
- * inside `changeSetId`. Content born in an open Change Set exists only
902
- * there, so read anywhere else it is a NotFound ConnectError.
914
+ * inside `changeSetId`, at the head of its Chain's last Branch, or of
915
+ * `branchId`, a Branch of that Chain, when given (#252). Content born in
916
+ * an open Change Set exists only there, so read anywhere else it is a
917
+ * NotFound ConnectError, as is a Branch outside the Chain.
903
918
  */
904
919
  getContent(input: {
905
920
  id: string;
906
921
  changeSetId?: string;
922
+ branchId?: string;
907
923
  }): Promise<ContentDetail>;
908
924
  /** Its Timeline, with the Planned Releases of open Change Sets beside it. */
909
925
  getTimeline(contentId: string): Promise<ContentTimeline>;
@@ -1122,6 +1138,7 @@ export declare const contenthubKeys: {
1122
1138
  contentList: (filter: object) => readonly ["contenthub", "contents", "list", object];
1123
1139
  content: (id: string) => readonly ["contenthub", "contents", "detail", string];
1124
1140
  contentRead: (id: string, changeSetId: string) => readonly ["contenthub", "contents", "detail", string, "read", string];
1141
+ contentBranchRead: (id: string, changeSetId: string, branchId: string) => readonly ["contenthub", "contents", "detail", string, "read", string, "branch", string];
1125
1142
  contentTimeline: (id: string) => readonly ["contenthub", "contents", "detail", string, "timeline"];
1126
1143
  contentRevisions: (id: string, target: object) => readonly ["contenthub", "contents", "detail", string, "revisions", object];
1127
1144
  contentCompare: (id: string, revisionId: string, base: object) => readonly ["contenthub", "contents", "detail", string, "compare", string, object];
@@ -1844,6 +1861,9 @@ export declare const contenthubTranslations: {
1844
1861
  merged_one: string;
1845
1862
  merged_other: string;
1846
1863
  nothingMerged: string;
1864
+ stopped_one: string;
1865
+ stopped_other: string;
1866
+ noneMerged: string;
1847
1867
  pendingTitle: string;
1848
1868
  pendingLine: string;
1849
1869
  closed: string;
@@ -2804,6 +2824,9 @@ export declare const contenthubTranslations: {
2804
2824
  merged_one: string;
2805
2825
  merged_other: string;
2806
2826
  nothingMerged: string;
2827
+ stopped_one: string;
2828
+ stopped_other: string;
2829
+ noneMerged: string;
2807
2830
  pendingTitle: string;
2808
2831
  pendingLine: string;
2809
2832
  closed: string;
@@ -3973,6 +3996,9 @@ export declare const i18nResources: {
3973
3996
  merged_one: string;
3974
3997
  merged_other: string;
3975
3998
  nothingMerged: string;
3999
+ stopped_one: string;
4000
+ stopped_other: string;
4001
+ noneMerged: string;
3976
4002
  pendingTitle: string;
3977
4003
  pendingLine: string;
3978
4004
  closed: string;
@@ -4933,6 +4959,9 @@ export declare const i18nResources: {
4933
4959
  merged_one: string;
4934
4960
  merged_other: string;
4935
4961
  nothingMerged: string;
4962
+ stopped_one: string;
4963
+ stopped_other: string;
4964
+ noneMerged: string;
4936
4965
  pendingTitle: string;
4937
4966
  pendingLine: string;
4938
4967
  closed: string;
@@ -5701,7 +5730,8 @@ export declare const STANDALONE_CONTENTHUB_PATHS: ContenthubPaths;
5701
5730
  * The port a host fills with statushub (ADR 0020): the workspace's Change Set
5702
5731
  * statuses, for their display names and colours. contenthub-ui depends on no
5703
5732
  * statushub package. A host without statushub leaves the port empty, and the
5704
- * screens then show the bare slug and offer no status picker.
5733
+ * screens then show the bare slug and offer no status picker. The status
5734
+ * marked `isDefault` names a Change Set that has none yet (ADR 0014 D9).
5705
5735
  */
5706
5736
  export declare interface StatusSource {
5707
5737
  /** Every status of the workspace's `contenthub/change_set` catalogue, in its order. */