From a7c2a8d5548064d58083eb42fd047cefa7308a26 Mon Sep 17 00:00:00 2001 From: "@permadeath.com" Date: Sat, 15 Aug 2026 07:58:35 -0400 Subject: [PATCH] feat(lexicon): vendor the three sh.tangled.repo.issue schemas MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Regenerated from tangled.org/core, which moves the pin from 74ce1a0 to 7ccb643. The six lexicons atgc already writes are byte-identical across that range, checked file by file, so nothing it sends changes — a pin bump riding inside a feature is worth having looked at rather than assumed. sh.tangled.repo.issue.comment is vendored with neither a reader nor a writer, and lexicons/README.md says why: an issue comment is written as sh.tangled.feed.comment, and the two schemas side by side are what makes that checkable instead of a claim. IssueState is PullState without `merged` — the same log-of-records shape, two tokens rather than three, and so no terminal state to refuse to overwrite. Co-Authored-By: Claude Opus 5 (1M context) Change-Id: I362d279e82b6bf7b8152f9e43e94af211e81c210 --- lexicons.json | 13 +- lexicons/README.md | 20 +- lexicons/sh/tangled/repo/issue.json | 54 +++ lexicons/sh/tangled/repo/issue/comment.json | 51 ++ lexicons/sh/tangled/repo/issue/state.json | 39 ++ scripts/vendor-tangled-lexicons.sh | 12 +- src/lexicon/tangled.rs | 130 +++++ vendor/tangled-lexicon/src/sh_tangled/repo.rs | 1 + .../src/sh_tangled/repo/issue.rs | 454 ++++++++++++++++++ .../src/sh_tangled/repo/issue/comment.rs | 426 ++++++++++++++++ .../src/sh_tangled/repo/issue/state.rs | 425 ++++++++++++++++ 11 files changed, 1616 insertions(+), 9 deletions(-) create mode 100644 lexicons/sh/tangled/repo/issue.json create mode 100644 lexicons/sh/tangled/repo/issue/comment.json create mode 100644 lexicons/sh/tangled/repo/issue/state.json create mode 100644 vendor/tangled-lexicon/src/sh_tangled/repo/issue.rs create mode 100644 vendor/tangled-lexicon/src/sh_tangled/repo/issue/comment.rs create mode 100644 vendor/tangled-lexicon/src/sh_tangled/repo/issue/state.rs diff --git a/lexicons.json b/lexicons.json index c1868e7..b9867c8 100644 --- a/lexicons.json +++ b/lexicons.json @@ -5,8 +5,8 @@ "type": "git", "repo": "https://tangled.org/tangled.org/core", "path": "lexicons", - "commit": "74ce1a0f0c21749bdf15198a4bc7dc457696bf97", - "fetchedAt": "2026-08-11T11:28:19Z" + "commit": "7ccb643019f40022b48296c202091be23af90fcc", + "fetchedAt": "2026-08-14T15:33:09+01:00" }, "userinput": { "type": "atproto-records", @@ -29,6 +29,15 @@ "sh.tangled.repo": { "source": "tangled" }, + "sh.tangled.repo.issue": { + "source": "tangled" + }, + "sh.tangled.repo.issue.comment": { + "source": "tangled" + }, + "sh.tangled.repo.issue.state": { + "source": "tangled" + }, "sh.tangled.repo.pull": { "source": "tangled" }, diff --git a/lexicons/README.md b/lexicons/README.md index 5035112..2f8d9ce 100644 --- a/lexicons/README.md +++ b/lexicons/README.md @@ -23,11 +23,21 @@ lexicons directory at its current tip, rewrites both the JSON here and the generated Rust in `../vendor/tangled-lexicon/`, and updates the pinned commit. -Scoped to exactly the seven lexicons the `tangled` source covers — not -Tangled's full surface (issues, CI, knot management, and every XRPC -endpoint atgc never calls). Widen -`scripts/vendor-tangled-lexicons.sh`'s codegen input if a future command -needs another one typed. +Scoped to exactly the ten lexicons the `tangled` source covers — not +Tangled's full surface (CI, knot management, and every XRPC endpoint atgc +never calls). Widen `scripts/vendor-tangled-lexicons.sh`'s codegen input if +a future command needs another one typed. + +`sh.tangled.repo.issue.comment` is the one here with neither a reader nor a +writer, and it is vendored on purpose. An issue comment is written as +`sh.tangled.feed.comment` — Tangled unified issue, pull and string comments +into that collection, and the appview's ingester handles this one as deletes +only. That claim is worth being able to check rather than take on trust, and +the two schemas side by side are the check: this one names its subject as a +bare at-uri and has no room for a CID, which is the shape from before the +unification. The pull twin, `sh.tangled.repo.pull.comment`, is *not* +vendored — it predates this reasoning, and adding it now would be a lexicon +bump inside an unrelated change. ## `app.userinput.*` diff --git a/lexicons/sh/tangled/repo/issue.json b/lexicons/sh/tangled/repo/issue.json new file mode 100644 index 0000000..e180064 --- /dev/null +++ b/lexicons/sh/tangled/repo/issue.json @@ -0,0 +1,54 @@ +{ + "lexicon": 1, + "id": "sh.tangled.repo.issue", + "needsCbor": true, + "needsType": true, + "defs": { + "main": { + "type": "record", + "key": "tid", + "record": { + "type": "object", + "required": ["repo", "title", "createdAt"], + "properties": { + "repo": { + "type": "string", + "format": "did" + }, + "title": { + "type": "string" + }, + "body": { + "type": "string" + }, + "createdAt": { + "type": "string", + "format": "datetime" + }, + "mentions": { + "type": "array", + "items": { + "type": "string", + "format": "did" + } + }, + "references": { + "type": "array", + "items": { + "type": "string", + "format": "at-uri" + } + }, + "blobs": { + "type": "array", + "items": { + "type": "blob", + "accept": ["image/*"], + "maxSize": 1000000 + } + } + } + } + } + } +} diff --git a/lexicons/sh/tangled/repo/issue/comment.json b/lexicons/sh/tangled/repo/issue/comment.json new file mode 100644 index 0000000..1bccebb --- /dev/null +++ b/lexicons/sh/tangled/repo/issue/comment.json @@ -0,0 +1,51 @@ +{ + "lexicon": 1, + "id": "sh.tangled.repo.issue.comment", + "needsCbor": true, + "needsType": true, + "defs": { + "main": { + "type": "record", + "key": "tid", + "record": { + "type": "object", + "required": [ + "issue", + "body", + "createdAt" + ], + "properties": { + "issue": { + "type": "string", + "format": "at-uri" + }, + "body": { + "type": "string" + }, + "createdAt": { + "type": "string", + "format": "datetime" + }, + "replyTo": { + "type": "string", + "format": "at-uri" + }, + "mentions": { + "type": "array", + "items": { + "type": "string", + "format": "did" + } + }, + "references": { + "type": "array", + "items": { + "type": "string", + "format": "at-uri" + } + } + } + } + } + } +} diff --git a/lexicons/sh/tangled/repo/issue/state.json b/lexicons/sh/tangled/repo/issue/state.json new file mode 100644 index 0000000..ebd9107 --- /dev/null +++ b/lexicons/sh/tangled/repo/issue/state.json @@ -0,0 +1,39 @@ +{ + "lexicon": 1, + "id": "sh.tangled.repo.issue.state", + "needsCbor": true, + "needsType": true, + "defs": { + "main": { + "type": "record", + "key": "tid", + "record": { + "type": "object", + "required": [ + "issue", + "state", + "createdAt" + ], + "properties": { + "issue": { + "type": "string", + "format": "at-uri" + }, + "createdAt": { + "type": "string", + "format": "datetime" + }, + "state": { + "type": "string", + "description": "state of the issue", + "knownValues": [ + "sh.tangled.repo.issue.state.open", + "sh.tangled.repo.issue.state.closed" + ], + "default": "sh.tangled.repo.issue.state.open" + } + } + } + } + } +} diff --git a/scripts/vendor-tangled-lexicons.sh b/scripts/vendor-tangled-lexicons.sh index 9fa0e13..d455e53 100755 --- a/scripts/vendor-tangled-lexicons.sh +++ b/scripts/vendor-tangled-lexicons.sh @@ -27,9 +27,14 @@ git clone --filter=blob:none --no-checkout --depth 1 \ commit=$(cd "$clone_dir" && git rev-parse HEAD) fetched_at=$(cd "$clone_dir" && git log -1 --format=%cI) -mkdir -p lexicons/sh/tangled/repo/pull lexicons/sh/tangled/feed lexicons/sh/tangled/markup lexicons/com/atproto/repo +mkdir -p lexicons/sh/tangled/repo/pull lexicons/sh/tangled/repo/issue lexicons/sh/tangled/feed lexicons/sh/tangled/markup lexicons/com/atproto/repo cp "$clone_dir/lexicons/pulls/pull.json" lexicons/sh/tangled/repo/pull.json cp "$clone_dir/lexicons/pulls/state.json" lexicons/sh/tangled/repo/pull/status.json +cp "$clone_dir/lexicons/issue/issue.json" lexicons/sh/tangled/repo/issue.json +cp "$clone_dir/lexicons/issue/state.json" lexicons/sh/tangled/repo/issue/state.json +# Deprecated upstream and never written by atgc — see lexicons/README.md for +# why a schema with no writer is still vendored. +cp "$clone_dir/lexicons/issue/comment.json" lexicons/sh/tangled/repo/issue/comment.json cp "$clone_dir/lexicons/repo/repo.json" lexicons/sh/tangled/repo.json cp "$clone_dir/lexicons/publicKey.json" lexicons/sh/tangled/publicKey.json cp "$clone_dir/lexicons/feed/comment.json" lexicons/sh/tangled/feed/comment.json @@ -49,6 +54,9 @@ with open('lexicons.json', 'w') as f: cp lexicons/sh/tangled/repo/pull.json "$codegen_in/sh.tangled.repo.pull.json" cp lexicons/sh/tangled/repo/pull/status.json "$codegen_in/sh.tangled.repo.pull.status.json" +cp lexicons/sh/tangled/repo/issue.json "$codegen_in/sh.tangled.repo.issue.json" +cp lexicons/sh/tangled/repo/issue/state.json "$codegen_in/sh.tangled.repo.issue.state.json" +cp lexicons/sh/tangled/repo/issue/comment.json "$codegen_in/sh.tangled.repo.issue.comment.json" cp lexicons/sh/tangled/repo.json "$codegen_in/sh.tangled.repo.json" cp lexicons/sh/tangled/publicKey.json "$codegen_in/sh.tangled.publicKey.json" cp lexicons/sh/tangled/feed/comment.json "$codegen_in/sh.tangled.feed.comment.json" @@ -69,5 +77,5 @@ cp "$codegen_out/builder_types.rs" vendor/tangled-lexicon/src/builder_types.rs # plain path dependency rather than a [patch] one. cargo fmt --all -echo "vendored 7 lexicons at commit $commit; regenerated vendor/tangled-lexicon/src/{sh_tangled,com_atproto}/" +echo "vendored 10 lexicons at commit $commit; regenerated vendor/tangled-lexicon/src/{sh_tangled,com_atproto}/" echo "lib.rs was not touched — it carries hand-added allow attributes and a LexiconSchema re-export" diff --git a/src/lexicon/tangled.rs b/src/lexicon/tangled.rs index 0f324b9..f4d030f 100644 --- a/src/lexicon/tangled.rs +++ b/src/lexicon/tangled.rs @@ -128,6 +128,83 @@ impl PullState { } } +/// sh.tangled.repo.issue — lives in the *reporter's* PDS, not the repo +/// owner's, and names its repo by that repo's own DID. The struct is +/// generated (`tangled_lexicon::sh_tangled::repo::issue`, used by +/// `crate::cmd::issue::write`); this constant stays here because several +/// commands need the bare NSID without constructing the record. +/// +/// The same asymmetry a pull record has, and for the same reason: an issue +/// on your repo filed by somebody else is a record in *their* repository, +/// which nothing enumerates. So an account's own issues are one public +/// `listRecords` away and everybody else's need an index — which is why +/// `crate::cmd::issue::read` reads the first and says plainly that it has +/// not looked at the second. +pub const ISSUE_NSID: &str = "sh.tangled.repo.issue"; + +/// sh.tangled.repo.issue.state — a state *event*, exactly as +/// [`PULL_STATUS_NSID`] is, down to the TID key and the newest-wins rule. +/// The struct is generated (`tangled_lexicon::sh_tangled::repo::issue::state`, +/// aliased `IssueStateRecord` in `crate::cmd::issue::write`). +/// +/// The record goes in the *acting* account's PDS, so a repo owner can close +/// an issue filed on their repo by somebody they cannot write to. Which +/// writers Tangled then honours is narrower than who may write one: the +/// appview's `authorizeStateRecord` accepts the issue's author, the repo's +/// owner and a collaborator, and drops everything else after an ACL check +/// against the knot. +pub const ISSUE_STATE_NSID: &str = "sh.tangled.repo.issue.state"; + +/// Whether an issue is open or closed. +/// +/// [`PullState`] without `merged`, which is the whole of the difference: an +/// issue is never landed, so the lexicon's `knownValues` are two rather than +/// three and there is no terminal state to refuse to overwrite. Everything +/// else is the same shape — not a field on the issue record, a log of +/// separate [`ISSUE_STATE_NSID`] records with the newest one winning, so +/// reopening appends an `open` record rather than deleting the `closed` one. +/// +/// Kept hand-written beside the generated `StateState` for the reason +/// [`PullState`] is: `token`/`label` are domain convenience the lexicon has +/// no reason to generate, and `--state` filters spell a state without its +/// NSID prefix. +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum IssueState { + Open, + Closed, +} + +impl IssueState { + /// The lexicon token written into a state record's `state` field. + pub fn token(self) -> &'static str { + match self { + IssueState::Open => "sh.tangled.repo.issue.state.open", + IssueState::Closed => "sh.tangled.repo.issue.state.closed", + } + } + + /// The bare word, for output and for `--state` filters. + pub fn label(self) -> &'static str { + match self { + IssueState::Open => "open", + IssueState::Closed => "closed", + } + } + + /// A token back to a state, or `None` for one this version has never + /// heard of — same permissiveness [`PullState::from_token`] argues for, + /// and for the same reason: the record was written by somebody else and + /// refusing to read the rest of a listing over it would break `issue + /// close` on unrelated issues. + pub fn from_token(token: &str) -> Option { + match token { + "sh.tangled.repo.issue.state.open" => Some(IssueState::Open), + "sh.tangled.repo.issue.state.closed" => Some(IssueState::Closed), + _ => None, + } + } +} + /// `sh.tangled.markup.markdown` — Tangled Flavored Markdown, as a comment or /// description body. The struct itself is generated /// (`tangled_lexicon::sh_tangled::markup::markdown`); see @@ -174,6 +251,31 @@ pub const FEED_COMMENT_NSID: &str = "sh.tangled.feed.comment"; /// from the pull page entirely. Writing one is a silent no-op with extra steps. pub const LEGACY_PULL_COMMENT_NSID: &str = "sh.tangled.repo.pull.comment"; +/// The collection `sh.tangled.repo.issue.comment`, which is *not* what an +/// issue comment is any more either. +/// +/// The same story as [`LEGACY_PULL_COMMENT_NSID`], one collection over, and +/// worth naming separately because the schema is vendored +/// (`lexicons/sh/tangled/repo/issue/comment.json`) and so looks even more +/// current than the pull one does. It is not. The unification that moved pull +/// comments moved these, and the appview's ingester says so in the same +/// words: +/// +/// ```text +/// // ingestIssueComment ingests legacy sh.tangled.repo.issue.comment deletions +/// case jmodels.CommitOperationCreate, jmodels.CommitOperationUpdate: +/// // no-op. sh.tangled.repo.issue.comment is deprecated +/// ``` +/// +/// The record's own shape is the corroboration: it names its `issue` as a +/// bare at-uri, where [`FEED_COMMENT_NSID`] takes a `subject` strongRef whose +/// CID the appview refuses a comment without. A CID is not something the old +/// shape had anywhere to put, so this is a schema from before the change +/// rather than an alternative to it. The scope stays requested — deleting a +/// legacy comment still needs it, which is the one operation the appview +/// still ingests here. +pub const LEGACY_ISSUE_COMMENT_NSID: &str = "sh.tangled.repo.issue.comment"; + /// sh.tangled.repo — the repo record in the owner's PDS. The struct itself /// is generated (`tangled_lexicon::sh_tangled::repo`, used by /// [`crate::cmd::repo`]); this constant stays here because several commands need @@ -217,4 +319,32 @@ mod tests { assert_eq!(PullState::from_token("closed"), None); assert_eq!(PullState::from_token(""), None); } + + /// The same round trip for issues, and the one difference that matters: + /// `merged` is a pull's token and not an issue's. A `from_token` that + /// accepted it would let a status record about a *pull* decide an issue's + /// state, which is reachable — both collections are read out of the same + /// PDS by the same walk, and only the token tells them apart. + #[test] + fn every_issue_state_maps_to_its_token_and_back() { + use super::IssueState; + + for state in [IssueState::Open, IssueState::Closed] { + assert_eq!(IssueState::from_token(state.token()), Some(state)); + assert_eq!( + state.token(), + format!("sh.tangled.repo.issue.state.{}", state.label()) + ); + } + assert_eq!( + IssueState::from_token("sh.tangled.repo.issue.state.merged"), + None + ); + assert_eq!( + IssueState::from_token(super::PullState::Closed.token()), + None + ); + assert_eq!(IssueState::from_token("closed"), None); + assert_eq!(IssueState::from_token(""), None); + } } diff --git a/vendor/tangled-lexicon/src/sh_tangled/repo.rs b/vendor/tangled-lexicon/src/sh_tangled/repo.rs index 9e2e7ac..6609295 100644 --- a/vendor/tangled-lexicon/src/sh_tangled/repo.rs +++ b/vendor/tangled-lexicon/src/sh_tangled/repo.rs @@ -6,6 +6,7 @@ // Any manual changes will be overwritten on the next regeneration. //! Generated bindings for the `sh.tangled.repo` Lexicon namespace/module. +pub mod issue; pub mod pull; #[allow(unused_imports)] diff --git a/vendor/tangled-lexicon/src/sh_tangled/repo/issue.rs b/vendor/tangled-lexicon/src/sh_tangled/repo/issue.rs new file mode 100644 index 0000000..07390a5 --- /dev/null +++ b/vendor/tangled-lexicon/src/sh_tangled/repo/issue.rs @@ -0,0 +1,454 @@ +// @generated by jacquard-lexicon. DO NOT EDIT. +// +// Lexicon: sh.tangled.repo.issue +// +// This file was automatically generated from Lexicon schemas. +// Any manual changes will be overwritten on the next regeneration. + +//! Generated bindings for the `sh.tangled.repo.issue` Lexicon namespace/module. +pub mod comment; +pub mod state; + +#[allow(unused_imports)] +use alloc::collections::BTreeMap; + +#[allow(unused_imports)] +use core::marker::PhantomData; +use jacquard_common::{BosStr, CowStr, DefaultStr, FromStaticStr}; + +#[allow(unused_imports)] +use jacquard_common::deps::codegen::unicode_segmentation::UnicodeSegmentation; +use jacquard_common::deps::smol_str::SmolStr; +use jacquard_common::types::blob::BlobRef; +use jacquard_common::types::collection::{Collection, RecordError}; +use jacquard_common::types::string::{AtUri, Cid, Datetime, Did}; +use jacquard_common::types::uri::{RecordUri, UriError}; +use jacquard_common::types::value::Data; +use jacquard_common::xrpc::XrpcResp; +use jacquard_derive::{IntoStatic, lexicon}; +use jacquard_lexicon::lexicon::LexiconDoc; +use jacquard_lexicon::schema::LexiconSchema; + +#[allow(unused_imports)] +use jacquard_lexicon::validation::{ConstraintError, ValidationPath}; +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + rename = "sh.tangled.repo.issue", + tag = "$type", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct Issue { + #[serde(skip_serializing_if = "Option::is_none")] + pub blobs: Option>>, + #[serde(skip_serializing_if = "Option::is_none")] + pub body: Option, + pub created_at: Datetime, + #[serde(skip_serializing_if = "Option::is_none")] + pub mentions: Option>>, + #[serde(skip_serializing_if = "Option::is_none")] + pub references: Option>>, + pub repo: Did, + pub title: S, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +/// Typed wrapper for GetRecord response with this collection's record type. + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde(rename_all = "camelCase")] +pub struct IssueGetRecordOutput { + #[serde(skip_serializing_if = "Option::is_none")] + pub cid: Option>, + pub uri: AtUri, + pub value: Issue, +} + +impl Issue { + pub fn uri(uri: S) -> Result, UriError> { + RecordUri::try_from_uri(AtUri::new(uri)?) + } +} + +/// Marker type for deserializing records from this collection. + +#[derive(Debug, Serialize, Deserialize)] +pub struct IssueRecord; +impl XrpcResp for IssueRecord { + const NSID: &'static str = "sh.tangled.repo.issue"; + const ENCODING: &'static str = "application/json"; + type Output = IssueGetRecordOutput; + type Err = RecordError; +} + +impl From> for Issue { + fn from(output: IssueGetRecordOutput) -> Self { + output.value + } +} + +impl Collection for Issue { + const NSID: &'static str = "sh.tangled.repo.issue"; + type Record = IssueRecord; +} + +impl Collection for IssueRecord { + const NSID: &'static str = "sh.tangled.repo.issue"; + type Record = IssueRecord; +} + +impl LexiconSchema for Issue { + fn nsid() -> &'static str { + "sh.tangled.repo.issue" + } + fn def_name() -> &'static str { + "main" + } + fn lexicon_doc() -> LexiconDoc<'static> { + lexicon_doc_sh_tangled_repo_issue() + } + fn validate(&self) -> Result<(), ConstraintError> { + Ok(()) + } +} + +pub mod issue_state { + + pub use crate::builder_types::{IsSet, IsUnset, Set, Unset}; + #[allow(unused)] + use ::core::marker::PhantomData; + mod sealed { + pub trait Sealed {} + } + /// State trait tracking which required fields have been set + pub trait State: sealed::Sealed { + type CreatedAt; + type Repo; + type Title; + } + /// Empty state - all required fields are unset + pub struct Empty(()); + impl sealed::Sealed for Empty {} + impl State for Empty { + type CreatedAt = Unset; + type Repo = Unset; + type Title = Unset; + } + ///State transition - sets the `created_at` field to Set + pub struct SetCreatedAt(PhantomData St>); + impl sealed::Sealed for SetCreatedAt {} + impl State for SetCreatedAt { + type CreatedAt = Set; + type Repo = St::Repo; + type Title = St::Title; + } + ///State transition - sets the `repo` field to Set + pub struct SetRepo(PhantomData St>); + impl sealed::Sealed for SetRepo {} + impl State for SetRepo { + type CreatedAt = St::CreatedAt; + type Repo = Set; + type Title = St::Title; + } + ///State transition - sets the `title` field to Set + pub struct SetTitle(PhantomData St>); + impl sealed::Sealed for SetTitle {} + impl State for SetTitle { + type CreatedAt = St::CreatedAt; + type Repo = St::Repo; + type Title = Set; + } + /// Marker types for field names + #[allow(non_camel_case_types)] + pub mod members { + ///Marker type for the `created_at` field + pub struct created_at(()); + ///Marker type for the `repo` field + pub struct repo(()); + ///Marker type for the `title` field + pub struct title(()); + } +} + +/// Builder for constructing an instance of this type. +pub struct IssueBuilder { + _state: PhantomData St>, + _fields: ( + Option>>, + Option, + Option, + Option>>, + Option>>, + Option>, + Option, + ), + _type: PhantomData S>, +} + +impl Issue { + /// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed + pub fn new() -> IssueBuilder { + IssueBuilder::new() + } +} + +impl Issue { + /// Create a new builder for this type + pub fn builder() -> IssueBuilder { + IssueBuilder::builder() + } +} + +impl IssueBuilder { + /// Create a new builder with all fields unset, using the default string type, if needed + pub fn new() -> Self { + IssueBuilder { + _state: PhantomData, + _fields: (None, None, None, None, None, None, None), + _type: PhantomData, + } + } +} + +impl IssueBuilder { + /// Create a new builder with all fields unset + pub fn builder() -> Self { + IssueBuilder { + _state: PhantomData, + _fields: (None, None, None, None, None, None, None), + _type: PhantomData, + } + } +} + +impl IssueBuilder { + /// Set the `blobs` field (optional) + pub fn blobs(mut self, value: impl Into>>>) -> Self { + self._fields.0 = value.into(); + self + } + /// Set the `blobs` field to an Option value (optional) + pub fn maybe_blobs(mut self, value: Option>>) -> Self { + self._fields.0 = value; + self + } +} + +impl IssueBuilder { + /// Set the `body` field (optional) + pub fn body(mut self, value: impl Into>) -> Self { + self._fields.1 = value.into(); + self + } + /// Set the `body` field to an Option value (optional) + pub fn maybe_body(mut self, value: Option) -> Self { + self._fields.1 = value; + self + } +} + +impl IssueBuilder +where + St: issue_state::State, + St::CreatedAt: issue_state::IsUnset, +{ + /// Set the `createdAt` field (required) + pub fn created_at( + mut self, + value: impl Into, + ) -> IssueBuilder, S> { + self._fields.2 = Option::Some(value.into()); + IssueBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl IssueBuilder { + /// Set the `mentions` field (optional) + pub fn mentions(mut self, value: impl Into>>>) -> Self { + self._fields.3 = value.into(); + self + } + /// Set the `mentions` field to an Option value (optional) + pub fn maybe_mentions(mut self, value: Option>>) -> Self { + self._fields.3 = value; + self + } +} + +impl IssueBuilder { + /// Set the `references` field (optional) + pub fn references(mut self, value: impl Into>>>) -> Self { + self._fields.4 = value.into(); + self + } + /// Set the `references` field to an Option value (optional) + pub fn maybe_references(mut self, value: Option>>) -> Self { + self._fields.4 = value; + self + } +} + +impl IssueBuilder +where + St: issue_state::State, + St::Repo: issue_state::IsUnset, +{ + /// Set the `repo` field (required) + pub fn repo(mut self, value: impl Into>) -> IssueBuilder, S> { + self._fields.5 = Option::Some(value.into()); + IssueBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl IssueBuilder +where + St: issue_state::State, + St::Title: issue_state::IsUnset, +{ + /// Set the `title` field (required) + pub fn title(mut self, value: impl Into) -> IssueBuilder, S> { + self._fields.6 = Option::Some(value.into()); + IssueBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl IssueBuilder +where + St: issue_state::State, + St::CreatedAt: issue_state::IsSet, + St::Repo: issue_state::IsSet, + St::Title: issue_state::IsSet, +{ + /// Build the final struct. + pub fn build(self) -> Issue { + Issue { + blobs: self._fields.0, + body: self._fields.1, + created_at: self._fields.2.unwrap(), + mentions: self._fields.3, + references: self._fields.4, + repo: self._fields.5.unwrap(), + title: self._fields.6.unwrap(), + extra_data: Default::default(), + } + } + /// Build the final struct with custom extra_data. + pub fn build_with_data(self, extra_data: BTreeMap>) -> Issue { + Issue { + blobs: self._fields.0, + body: self._fields.1, + created_at: self._fields.2.unwrap(), + mentions: self._fields.3, + references: self._fields.4, + repo: self._fields.5.unwrap(), + title: self._fields.6.unwrap(), + extra_data: Some(extra_data), + } + } +} + +fn lexicon_doc_sh_tangled_repo_issue() -> LexiconDoc<'static> { + use alloc::collections::BTreeMap; + #[allow(unused_imports)] + use jacquard_common::{CowStr, deps::smol_str::SmolStr, types::blob::MimeType}; + use jacquard_lexicon::lexicon::*; + LexiconDoc { + lexicon: Lexicon::Lexicon1, + id: CowStr::new_static("sh.tangled.repo.issue"), + defs: { + let mut map = BTreeMap::new(); + map.insert( + SmolStr::new_static("main"), + LexUserType::Record(LexRecord { + key: Some(CowStr::new_static("tid")), + record: LexRecordRecord::Object(LexObject { + required: Some(vec![ + SmolStr::new_static("repo"), + SmolStr::new_static("title"), + SmolStr::new_static("createdAt"), + ]), + properties: { + #[allow(unused_mut)] + let mut map = BTreeMap::new(); + map.insert( + SmolStr::new_static("blobs"), + LexObjectProperty::Array(LexArray { + items: LexArrayItem::Blob(LexBlob { + ..Default::default() + }), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("body"), + LexObjectProperty::String(LexString { + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("createdAt"), + LexObjectProperty::String(LexString { + format: Some(LexStringFormat::Datetime), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("mentions"), + LexObjectProperty::Array(LexArray { + items: LexArrayItem::String(LexString { + format: Some(LexStringFormat::Did), + ..Default::default() + }), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("references"), + LexObjectProperty::Array(LexArray { + items: LexArrayItem::String(LexString { + format: Some(LexStringFormat::AtUri), + ..Default::default() + }), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("repo"), + LexObjectProperty::String(LexString { + format: Some(LexStringFormat::Did), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("title"), + LexObjectProperty::String(LexString { + ..Default::default() + }), + ); + map + }, + ..Default::default() + }), + ..Default::default() + }), + ); + map + }, + ..Default::default() + } +} diff --git a/vendor/tangled-lexicon/src/sh_tangled/repo/issue/comment.rs b/vendor/tangled-lexicon/src/sh_tangled/repo/issue/comment.rs new file mode 100644 index 0000000..c1da34c --- /dev/null +++ b/vendor/tangled-lexicon/src/sh_tangled/repo/issue/comment.rs @@ -0,0 +1,426 @@ +// @generated by jacquard-lexicon. DO NOT EDIT. +// +// Lexicon: sh.tangled.repo.issue.comment +// +// This file was automatically generated from Lexicon schemas. +// Any manual changes will be overwritten on the next regeneration. + +#[allow(unused_imports)] +use alloc::collections::BTreeMap; + +#[allow(unused_imports)] +use core::marker::PhantomData; +use jacquard_common::{BosStr, CowStr, DefaultStr, FromStaticStr}; + +#[allow(unused_imports)] +use jacquard_common::deps::codegen::unicode_segmentation::UnicodeSegmentation; +use jacquard_common::deps::smol_str::SmolStr; +use jacquard_common::types::collection::{Collection, RecordError}; +use jacquard_common::types::string::{AtUri, Cid, Datetime, Did}; +use jacquard_common::types::uri::{RecordUri, UriError}; +use jacquard_common::types::value::Data; +use jacquard_common::xrpc::XrpcResp; +use jacquard_derive::{IntoStatic, lexicon}; +use jacquard_lexicon::lexicon::LexiconDoc; +use jacquard_lexicon::schema::LexiconSchema; + +#[allow(unused_imports)] +use jacquard_lexicon::validation::{ConstraintError, ValidationPath}; +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + rename = "sh.tangled.repo.issue.comment", + tag = "$type", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct Comment { + pub body: S, + pub created_at: Datetime, + pub issue: AtUri, + #[serde(skip_serializing_if = "Option::is_none")] + pub mentions: Option>>, + #[serde(skip_serializing_if = "Option::is_none")] + pub references: Option>>, + #[serde(skip_serializing_if = "Option::is_none")] + pub reply_to: Option>, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +/// Typed wrapper for GetRecord response with this collection's record type. + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde(rename_all = "camelCase")] +pub struct CommentGetRecordOutput { + #[serde(skip_serializing_if = "Option::is_none")] + pub cid: Option>, + pub uri: AtUri, + pub value: Comment, +} + +impl Comment { + pub fn uri(uri: S) -> Result, UriError> { + RecordUri::try_from_uri(AtUri::new(uri)?) + } +} + +/// Marker type for deserializing records from this collection. + +#[derive(Debug, Serialize, Deserialize)] +pub struct CommentRecord; +impl XrpcResp for CommentRecord { + const NSID: &'static str = "sh.tangled.repo.issue.comment"; + const ENCODING: &'static str = "application/json"; + type Output = CommentGetRecordOutput; + type Err = RecordError; +} + +impl From> for Comment { + fn from(output: CommentGetRecordOutput) -> Self { + output.value + } +} + +impl Collection for Comment { + const NSID: &'static str = "sh.tangled.repo.issue.comment"; + type Record = CommentRecord; +} + +impl Collection for CommentRecord { + const NSID: &'static str = "sh.tangled.repo.issue.comment"; + type Record = CommentRecord; +} + +impl LexiconSchema for Comment { + fn nsid() -> &'static str { + "sh.tangled.repo.issue.comment" + } + fn def_name() -> &'static str { + "main" + } + fn lexicon_doc() -> LexiconDoc<'static> { + lexicon_doc_sh_tangled_repo_issue_comment() + } + fn validate(&self) -> Result<(), ConstraintError> { + Ok(()) + } +} + +pub mod comment_state { + + pub use crate::builder_types::{IsSet, IsUnset, Set, Unset}; + #[allow(unused)] + use ::core::marker::PhantomData; + mod sealed { + pub trait Sealed {} + } + /// State trait tracking which required fields have been set + pub trait State: sealed::Sealed { + type Body; + type CreatedAt; + type Issue; + } + /// Empty state - all required fields are unset + pub struct Empty(()); + impl sealed::Sealed for Empty {} + impl State for Empty { + type Body = Unset; + type CreatedAt = Unset; + type Issue = Unset; + } + ///State transition - sets the `body` field to Set + pub struct SetBody(PhantomData St>); + impl sealed::Sealed for SetBody {} + impl State for SetBody { + type Body = Set; + type CreatedAt = St::CreatedAt; + type Issue = St::Issue; + } + ///State transition - sets the `created_at` field to Set + pub struct SetCreatedAt(PhantomData St>); + impl sealed::Sealed for SetCreatedAt {} + impl State for SetCreatedAt { + type Body = St::Body; + type CreatedAt = Set; + type Issue = St::Issue; + } + ///State transition - sets the `issue` field to Set + pub struct SetIssue(PhantomData St>); + impl sealed::Sealed for SetIssue {} + impl State for SetIssue { + type Body = St::Body; + type CreatedAt = St::CreatedAt; + type Issue = Set; + } + /// Marker types for field names + #[allow(non_camel_case_types)] + pub mod members { + ///Marker type for the `body` field + pub struct body(()); + ///Marker type for the `created_at` field + pub struct created_at(()); + ///Marker type for the `issue` field + pub struct issue(()); + } +} + +/// Builder for constructing an instance of this type. +pub struct CommentBuilder { + _state: PhantomData St>, + _fields: ( + Option, + Option, + Option>, + Option>>, + Option>>, + Option>, + ), + _type: PhantomData S>, +} + +impl Comment { + /// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed + pub fn new() -> CommentBuilder { + CommentBuilder::new() + } +} + +impl Comment { + /// Create a new builder for this type + pub fn builder() -> CommentBuilder { + CommentBuilder::builder() + } +} + +impl CommentBuilder { + /// Create a new builder with all fields unset, using the default string type, if needed + pub fn new() -> Self { + CommentBuilder { + _state: PhantomData, + _fields: (None, None, None, None, None, None), + _type: PhantomData, + } + } +} + +impl CommentBuilder { + /// Create a new builder with all fields unset + pub fn builder() -> Self { + CommentBuilder { + _state: PhantomData, + _fields: (None, None, None, None, None, None), + _type: PhantomData, + } + } +} + +impl CommentBuilder +where + St: comment_state::State, + St::Body: comment_state::IsUnset, +{ + /// Set the `body` field (required) + pub fn body(mut self, value: impl Into) -> CommentBuilder, S> { + self._fields.0 = Option::Some(value.into()); + CommentBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl CommentBuilder +where + St: comment_state::State, + St::CreatedAt: comment_state::IsUnset, +{ + /// Set the `createdAt` field (required) + pub fn created_at( + mut self, + value: impl Into, + ) -> CommentBuilder, S> { + self._fields.1 = Option::Some(value.into()); + CommentBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl CommentBuilder +where + St: comment_state::State, + St::Issue: comment_state::IsUnset, +{ + /// Set the `issue` field (required) + pub fn issue( + mut self, + value: impl Into>, + ) -> CommentBuilder, S> { + self._fields.2 = Option::Some(value.into()); + CommentBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl CommentBuilder { + /// Set the `mentions` field (optional) + pub fn mentions(mut self, value: impl Into>>>) -> Self { + self._fields.3 = value.into(); + self + } + /// Set the `mentions` field to an Option value (optional) + pub fn maybe_mentions(mut self, value: Option>>) -> Self { + self._fields.3 = value; + self + } +} + +impl CommentBuilder { + /// Set the `references` field (optional) + pub fn references(mut self, value: impl Into>>>) -> Self { + self._fields.4 = value.into(); + self + } + /// Set the `references` field to an Option value (optional) + pub fn maybe_references(mut self, value: Option>>) -> Self { + self._fields.4 = value; + self + } +} + +impl CommentBuilder { + /// Set the `replyTo` field (optional) + pub fn reply_to(mut self, value: impl Into>>) -> Self { + self._fields.5 = value.into(); + self + } + /// Set the `replyTo` field to an Option value (optional) + pub fn maybe_reply_to(mut self, value: Option>) -> Self { + self._fields.5 = value; + self + } +} + +impl CommentBuilder +where + St: comment_state::State, + St::Body: comment_state::IsSet, + St::CreatedAt: comment_state::IsSet, + St::Issue: comment_state::IsSet, +{ + /// Build the final struct. + pub fn build(self) -> Comment { + Comment { + body: self._fields.0.unwrap(), + created_at: self._fields.1.unwrap(), + issue: self._fields.2.unwrap(), + mentions: self._fields.3, + references: self._fields.4, + reply_to: self._fields.5, + extra_data: Default::default(), + } + } + /// Build the final struct with custom extra_data. + pub fn build_with_data(self, extra_data: BTreeMap>) -> Comment { + Comment { + body: self._fields.0.unwrap(), + created_at: self._fields.1.unwrap(), + issue: self._fields.2.unwrap(), + mentions: self._fields.3, + references: self._fields.4, + reply_to: self._fields.5, + extra_data: Some(extra_data), + } + } +} + +fn lexicon_doc_sh_tangled_repo_issue_comment() -> LexiconDoc<'static> { + use alloc::collections::BTreeMap; + #[allow(unused_imports)] + use jacquard_common::{CowStr, deps::smol_str::SmolStr, types::blob::MimeType}; + use jacquard_lexicon::lexicon::*; + LexiconDoc { + lexicon: Lexicon::Lexicon1, + id: CowStr::new_static("sh.tangled.repo.issue.comment"), + defs: { + let mut map = BTreeMap::new(); + map.insert( + SmolStr::new_static("main"), + LexUserType::Record(LexRecord { + key: Some(CowStr::new_static("tid")), + record: LexRecordRecord::Object(LexObject { + required: Some(vec![ + SmolStr::new_static("issue"), + SmolStr::new_static("body"), + SmolStr::new_static("createdAt"), + ]), + properties: { + #[allow(unused_mut)] + let mut map = BTreeMap::new(); + map.insert( + SmolStr::new_static("body"), + LexObjectProperty::String(LexString { + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("createdAt"), + LexObjectProperty::String(LexString { + format: Some(LexStringFormat::Datetime), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("issue"), + LexObjectProperty::String(LexString { + format: Some(LexStringFormat::AtUri), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("mentions"), + LexObjectProperty::Array(LexArray { + items: LexArrayItem::String(LexString { + format: Some(LexStringFormat::Did), + ..Default::default() + }), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("references"), + LexObjectProperty::Array(LexArray { + items: LexArrayItem::String(LexString { + format: Some(LexStringFormat::AtUri), + ..Default::default() + }), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("replyTo"), + LexObjectProperty::String(LexString { + format: Some(LexStringFormat::AtUri), + ..Default::default() + }), + ); + map + }, + ..Default::default() + }), + ..Default::default() + }), + ); + map + }, + ..Default::default() + } +} diff --git a/vendor/tangled-lexicon/src/sh_tangled/repo/issue/state.rs b/vendor/tangled-lexicon/src/sh_tangled/repo/issue/state.rs new file mode 100644 index 0000000..83a2d87 --- /dev/null +++ b/vendor/tangled-lexicon/src/sh_tangled/repo/issue/state.rs @@ -0,0 +1,425 @@ +// @generated by jacquard-lexicon. DO NOT EDIT. +// +// Lexicon: sh.tangled.repo.issue.state +// +// This file was automatically generated from Lexicon schemas. +// Any manual changes will be overwritten on the next regeneration. + +#[allow(unused_imports)] +use alloc::collections::BTreeMap; + +#[allow(unused_imports)] +use core::marker::PhantomData; +use jacquard_common::{BosStr, CowStr, DefaultStr, FromStaticStr}; + +#[allow(unused_imports)] +use jacquard_common::deps::codegen::unicode_segmentation::UnicodeSegmentation; +use jacquard_common::deps::smol_str::SmolStr; +use jacquard_common::types::collection::{Collection, RecordError}; +use jacquard_common::types::string::{AtUri, Cid, Datetime}; +use jacquard_common::types::uri::{RecordUri, UriError}; +use jacquard_common::types::value::Data; +use jacquard_common::xrpc::XrpcResp; +use jacquard_derive::{IntoStatic, lexicon}; +use jacquard_lexicon::lexicon::LexiconDoc; +use jacquard_lexicon::schema::LexiconSchema; + +#[allow(unused_imports)] +use jacquard_lexicon::validation::{ConstraintError, ValidationPath}; +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + rename = "sh.tangled.repo.issue.state", + tag = "$type", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct State { + pub created_at: Datetime, + pub issue: AtUri, + ///state of the issue + pub state: StateState, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +/// state of the issue + +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub enum StateState { + ShTangledRepoIssueStateOpen, + ShTangledRepoIssueStateClosed, + Other(S), +} + +impl StateState { + pub fn as_str(&self) -> &str { + match self { + Self::ShTangledRepoIssueStateOpen => "sh.tangled.repo.issue.state.open", + Self::ShTangledRepoIssueStateClosed => "sh.tangled.repo.issue.state.closed", + Self::Other(s) => s.as_ref(), + } + } + /// Construct from a string-like value, matching known values. + pub fn from_value(s: S) -> Self { + match s.as_ref() { + "sh.tangled.repo.issue.state.open" => Self::ShTangledRepoIssueStateOpen, + "sh.tangled.repo.issue.state.closed" => Self::ShTangledRepoIssueStateClosed, + _ => Self::Other(s), + } + } +} + +impl core::fmt::Display for StateState { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!(f, "{}", self.as_str()) + } +} + +impl AsRef for StateState { + fn as_ref(&self) -> &str { + self.as_str() + } +} + +impl Serialize for StateState { + fn serialize(&self, serializer: Ser) -> Result + where + Ser: serde::Serializer, + { + serializer.serialize_str(self.as_str()) + } +} + +impl<'de, S: Deserialize<'de> + BosStr> Deserialize<'de> for StateState { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = S::deserialize(deserializer)?; + Ok(Self::from_value(s)) + } +} + +impl Default for StateState { + fn default() -> Self { + Self::Other(Default::default()) + } +} + +impl jacquard_common::IntoStatic for StateState +where + S: BosStr + jacquard_common::IntoStatic, + S::Output: BosStr, +{ + type Output = StateState; + fn into_static(self) -> Self::Output { + match self { + StateState::ShTangledRepoIssueStateOpen => StateState::ShTangledRepoIssueStateOpen, + StateState::ShTangledRepoIssueStateClosed => StateState::ShTangledRepoIssueStateClosed, + StateState::Other(v) => StateState::Other(v.into_static()), + } + } +} + +/// Typed wrapper for GetRecord response with this collection's record type. + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde(rename_all = "camelCase")] +pub struct StateGetRecordOutput { + #[serde(skip_serializing_if = "Option::is_none")] + pub cid: Option>, + pub uri: AtUri, + pub value: State, +} + +impl State { + pub fn uri(uri: S) -> Result, UriError> { + RecordUri::try_from_uri(AtUri::new(uri)?) + } +} + +/// Marker type for deserializing records from this collection. + +#[derive(Debug, Serialize, Deserialize)] +pub struct StateRecord; +impl XrpcResp for StateRecord { + const NSID: &'static str = "sh.tangled.repo.issue.state"; + const ENCODING: &'static str = "application/json"; + type Output = StateGetRecordOutput; + type Err = RecordError; +} + +impl From> for State { + fn from(output: StateGetRecordOutput) -> Self { + output.value + } +} + +impl Collection for State { + const NSID: &'static str = "sh.tangled.repo.issue.state"; + type Record = StateRecord; +} + +impl Collection for StateRecord { + const NSID: &'static str = "sh.tangled.repo.issue.state"; + type Record = StateRecord; +} + +impl LexiconSchema for State { + fn nsid() -> &'static str { + "sh.tangled.repo.issue.state" + } + fn def_name() -> &'static str { + "main" + } + fn lexicon_doc() -> LexiconDoc<'static> { + lexicon_doc_sh_tangled_repo_issue_state() + } + fn validate(&self) -> Result<(), ConstraintError> { + Ok(()) + } +} + +pub mod state_state { + + pub use crate::builder_types::{IsSet, IsUnset, Set, Unset}; + #[allow(unused)] + use ::core::marker::PhantomData; + mod sealed { + pub trait Sealed {} + } + /// State trait tracking which required fields have been set + pub trait State: sealed::Sealed { + type CreatedAt; + type Issue; + type State; + } + /// Empty state - all required fields are unset + pub struct Empty(()); + impl sealed::Sealed for Empty {} + impl State for Empty { + type CreatedAt = Unset; + type Issue = Unset; + type State = Unset; + } + ///State transition - sets the `created_at` field to Set + pub struct SetCreatedAt(PhantomData St>); + impl sealed::Sealed for SetCreatedAt {} + impl State for SetCreatedAt { + type CreatedAt = Set; + type Issue = St::Issue; + type State = St::State; + } + ///State transition - sets the `issue` field to Set + pub struct SetIssue(PhantomData St>); + impl sealed::Sealed for SetIssue {} + impl State for SetIssue { + type CreatedAt = St::CreatedAt; + type Issue = Set; + type State = St::State; + } + ///State transition - sets the `state` field to Set + pub struct SetState(PhantomData St>); + impl sealed::Sealed for SetState {} + impl State for SetState { + type CreatedAt = St::CreatedAt; + type Issue = St::Issue; + type State = Set; + } + /// Marker types for field names + #[allow(non_camel_case_types)] + pub mod members { + ///Marker type for the `created_at` field + pub struct created_at(()); + ///Marker type for the `issue` field + pub struct issue(()); + ///Marker type for the `state` field + pub struct state(()); + } +} + +/// Builder for constructing an instance of this type. +pub struct StateBuilder { + _state: PhantomData St>, + _fields: (Option, Option>, Option>), + _type: PhantomData S>, +} + +impl State { + /// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed + pub fn new() -> StateBuilder { + StateBuilder::new() + } +} + +impl State { + /// Create a new builder for this type + pub fn builder() -> StateBuilder { + StateBuilder::builder() + } +} + +impl StateBuilder { + /// Create a new builder with all fields unset, using the default string type, if needed + pub fn new() -> Self { + StateBuilder { + _state: PhantomData, + _fields: (None, None, None), + _type: PhantomData, + } + } +} + +impl StateBuilder { + /// Create a new builder with all fields unset + pub fn builder() -> Self { + StateBuilder { + _state: PhantomData, + _fields: (None, None, None), + _type: PhantomData, + } + } +} + +impl StateBuilder +where + St: state_state::State, + St::CreatedAt: state_state::IsUnset, +{ + /// Set the `createdAt` field (required) + pub fn created_at( + mut self, + value: impl Into, + ) -> StateBuilder, S> { + self._fields.0 = Option::Some(value.into()); + StateBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl StateBuilder +where + St: state_state::State, + St::Issue: state_state::IsUnset, +{ + /// Set the `issue` field (required) + pub fn issue( + mut self, + value: impl Into>, + ) -> StateBuilder, S> { + self._fields.1 = Option::Some(value.into()); + StateBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl StateBuilder +where + St: state_state::State, + St::State: state_state::IsUnset, +{ + /// Set the `state` field (required) + pub fn state( + mut self, + value: impl Into>, + ) -> StateBuilder, S> { + self._fields.2 = Option::Some(value.into()); + StateBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl StateBuilder +where + St: state_state::State, + St::CreatedAt: state_state::IsSet, + St::Issue: state_state::IsSet, + St::State: state_state::IsSet, +{ + /// Build the final struct. + pub fn build(self) -> State { + State { + created_at: self._fields.0.unwrap(), + issue: self._fields.1.unwrap(), + state: self._fields.2.unwrap(), + extra_data: Default::default(), + } + } + /// Build the final struct with custom extra_data. + pub fn build_with_data(self, extra_data: BTreeMap>) -> State { + State { + created_at: self._fields.0.unwrap(), + issue: self._fields.1.unwrap(), + state: self._fields.2.unwrap(), + extra_data: Some(extra_data), + } + } +} + +fn lexicon_doc_sh_tangled_repo_issue_state() -> LexiconDoc<'static> { + use alloc::collections::BTreeMap; + #[allow(unused_imports)] + use jacquard_common::{CowStr, deps::smol_str::SmolStr, types::blob::MimeType}; + use jacquard_lexicon::lexicon::*; + LexiconDoc { + lexicon: Lexicon::Lexicon1, + id: CowStr::new_static("sh.tangled.repo.issue.state"), + defs: { + let mut map = BTreeMap::new(); + map.insert( + SmolStr::new_static("main"), + LexUserType::Record(LexRecord { + key: Some(CowStr::new_static("tid")), + record: LexRecordRecord::Object(LexObject { + required: Some(vec![ + SmolStr::new_static("issue"), + SmolStr::new_static("state"), + SmolStr::new_static("createdAt"), + ]), + properties: { + #[allow(unused_mut)] + let mut map = BTreeMap::new(); + map.insert( + SmolStr::new_static("createdAt"), + LexObjectProperty::String(LexString { + format: Some(LexStringFormat::Datetime), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("issue"), + LexObjectProperty::String(LexString { + format: Some(LexStringFormat::AtUri), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("state"), + LexObjectProperty::String(LexString { + description: Some(CowStr::new_static("state of the issue")), + ..Default::default() + }), + ); + map + }, + ..Default::default() + }), + ..Default::default() + }), + ); + map + }, + ..Default::default() + } +} -- 2.51.2