From 1d030732182e3f2c5a069fcf91bcf3fd8cd44aa0 Mon Sep 17 00:00:00 2001 From: Orual Date: Wed, 12 Aug 2026 19:55:20 -0400 Subject: [PATCH] Harden permissioned repository verification Authenticate permissioned CAR commits and indexes, validate credential kinds, and cover mutation and replay boundaries. Epic: SPREN-4 Task: SPREN-6 --- Cargo.lock | 2 + crates/jacquard-api/src/app_rocksky/album.rs | 24 + crates/jacquard-api/src/app_rocksky/artist.rs | 24 + .../jacquard-api/src/app_rocksky/scrobble.rs | 24 + crates/jacquard-api/src/app_rocksky/song.rs | 24 + .../jacquard-api/src/at_margin/annotation.rs | 26 + .../jacquard-api/src/at_margin/preferences.rs | 12 + crates/jacquard-api/src/at_margin/profile.rs | 12 + .../src/blue_backyard/feed/post.rs | 26 + .../src/blue_backyard/feed/reblog.rs | 26 + .../src/blue_rito/feed/bookmark.rs | 52 + .../src/chat_bsky/group/create_group.rs | 1 + crates/jacquard-api/src/com_atproto.rs | 2 + .../src/com_atproto/repo/strong_ref.rs | 2 +- .../src/com_atproto/server/describe_server.rs | 3 + .../src/com_atproto/simplespace.rs | 410 ++++ .../src/com_atproto/simplespace/add_member.rs | 257 ++ .../simplespace/check_user_access.rs | 225 ++ .../com_atproto/simplespace/create_space.rs | 369 +++ .../com_atproto/simplespace/delete_space.rs | 220 ++ .../src/com_atproto/simplespace/get_space.rs | 241 ++ .../com_atproto/simplespace/list_members.rs | 469 ++++ .../com_atproto/simplespace/remove_member.rs | 257 ++ .../com_atproto/simplespace/update_space.rs | 307 +++ crates/jacquard-api/src/com_atproto/space.rs | 480 ++++ .../src/com_atproto/space/apply_writes.rs | 1825 ++++++++++++++ .../src/com_atproto/space/create_record.rs | 475 ++++ .../src/com_atproto/space/delete_record.rs | 341 +++ .../src/com_atproto/space/get_blob.rs | 340 +++ .../com_atproto/space/get_delegation_token.rs | 175 ++ .../com_atproto/space/get_latest_commit.rs | 282 +++ .../src/com_atproto/space/get_record.rs | 370 +++ .../src/com_atproto/space/get_repo.rs | 317 +++ .../com_atproto/space/get_space_credential.rs | 335 +++ .../src/com_atproto/space/list_blobs.rs | 342 +++ .../src/com_atproto/space/list_records.rs | 762 ++++++ .../src/com_atproto/space/list_repo_ops.rs | 809 +++++++ .../src/com_atproto/space/list_repos.rs | 566 +++++ .../src/com_atproto/space/list_spaces.rs | 444 ++++ .../com_atproto/space/notify_space_deleted.rs | 176 ++ .../src/com_atproto/space/notify_write.rs | 297 +++ .../src/com_atproto/space/put_record.rs | 487 ++++ .../src/com_atproto/space/register_notify.rs | 270 +++ .../com_atproto/space/unregister_notify.rs | 247 ++ .../src/com_crabdance/nandi/post.rs | 12 + .../src/com_deckbelcher/deck/list.rs | 72 + .../com_shinolabs/pinksea/app_view_defs.rs | 12 + .../src/com_shinolabs/pinksea/oekaki.rs | 12 + .../src/com_suibari/atsumeat/sticker.rs | 26 + .../src/community_lexicon/app/entry.rs | 26 + .../src/community_lexicon/app/profile.rs | 26 + .../app/profile_localization.rs | 26 + crates/jacquard-api/src/dev_atfs.rs | 9 + crates/jacquard-api/src/dev_atfs/file.rs | 386 +++ crates/jacquard-api/src/dev_atfs/repo.rs | 11 + .../src/dev_atfs/repo/delete_file.rs | 234 ++ .../src/dev_atfs/repo/get_file.rs | 241 ++ .../src/dev_atfs/repo/list_files.rs | 179 ++ .../src/dev_atfs/repo/pin_file.rs | 593 +++++ .../src/dev_atfs/repo/upload_file.rs | 122 + crates/jacquard-api/src/dev_atfs/server.rs | 327 +++ .../experimental/atforumv1/feed/post.rs | 20 + .../experimental/atforumv1/feed/question.rs | 20 + .../src/events_smokesignal/lfg.rs | 22 + .../src/fm_teal/alpha/feed/play.rs | 38 + .../games_gamesgamesgamesgames/list_games.rs | 74 +- crates/jacquard-api/src/garden_goals/goal.rs | 12 + .../src/garden_lexicon/service.rs | 12 + .../src/internal_bsky/actor/get_profiles.rs | 45 +- crates/jacquard-api/src/io_atcr.rs | 1 + .../jacquard-api/src/io_atcr/auth_full_app.rs | 8 + crates/jacquard-api/src/io_atcr/hold.rs | 1 + crates/jacquard-api/src/io_atcr/hold/crew.rs | 10 + .../src/io_atcr/hold/export_user_data.rs | 12 + .../io_atcr/hold/get_layers_for_manifest.rs | 177 ++ crates/jacquard-api/src/io_atcr/hold/scan.rs | 215 +- crates/jacquard-api/src/io_atcr/manifest.rs | 12 + crates/jacquard-api/src/io_atcr/repo/page.rs | 29 +- .../src/io_atcr/sailor/profile.rs | 189 +- crates/jacquard-api/src/io_atcr/tag.rs | 65 +- crates/jacquard-api/src/io_sound/sequence.rs | 26 + crates/jacquard-api/src/media_ionosphere.rs | 10 + .../src/media_ionosphere/group.rs | 12 + .../src/media_ionosphere/programme.rs | 12 + .../src/media_ionosphere/service.rs | 12 + .../src/net_alternativeproto/submission.rs | 24 + crates/jacquard-api/src/net_anisota.rs | 2 + .../jacquard-api/src/net_anisota/chronicle.rs | 3 + .../src/net_anisota/chronicle/achievement.rs | 4 +- .../src/net_anisota/chronicle/fieldwork.rs | 1206 ++++++++++ .../src/net_anisota/chronicle/log/daily.rs | 554 ++++- .../src/net_anisota/chronicle/log/monthly.rs | 214 +- .../src/net_anisota/chronicle/log/weekly.rs | 218 +- .../src/net_anisota/chronicle/log/yearly.rs | 202 +- .../src/net_anisota/chronicle/milestone.rs | 1262 ++++++++++ .../src/net_anisota/chronicle/walk.rs | 2129 +++++++++++++++++ .../src/net_anisota/chronicle/walk/camp.rs | 1290 ++++++++++ .../src/net_anisota/feed/draft.rs | 26 + .../jacquard-api/src/net_anisota/feed/list.rs | 12 + .../jacquard-api/src/net_anisota/feed/post.rs | 26 + .../jacquard-api/src/net_anisota/fieldwork.rs | 7 + .../src/net_anisota/fieldwork/state.rs | 518 ++++ crates/jacquard-api/src/net_anisota/graph.rs | 2 + .../src/net_anisota/graph/list_mute.rs | 26 +- .../src/net_anisota/graph/mute.rs | 26 +- .../src/net_anisota/graph/scoped_mute.rs | 627 +++++ .../src/net_anisota/graph/wordlist.rs | 1294 ++++++++++ crates/jacquard-api/src/net_anisota/lab.rs | 1 + .../src/net_anisota/lab/inkblot.rs | 4 +- .../src/net_anisota/lab/plasmodium.rs | 1207 ++++++++++ .../src/net_anisota/observatory/layout.rs | 68 +- .../src/net_anisota/player/state.rs | 351 ++- crates/jacquard-api/src/net_anisota/spell.rs | 8 + .../src/net_anisota/spell/book.rs | 468 ++++ .../src/net_anisota/spell/custom.rs | 1970 +++++++++++++++ .../src/net_shwilliam/hyphae/note.rs | 26 + .../org_hypercerts/helper/work_scope_tag.rs | 12 + .../src/org_hypercerts/workscope/tag.rs | 24 + .../src/org_impactindexer/review.rs | 11 + .../src/org_passingreads/book/registration.rs | 20 + .../src/org_stormlightlabs/malfestio/deck.rs | 12 + crates/jacquard-api/src/org_tangled.rs | 7 + crates/jacquard-api/src/org_tangled/temp.rs | 12 + .../src/org_tangled/temp/account.rs | 13 + .../org_tangled/temp/account/begin_signup.rs | 128 + .../temp/account/complete_signup.rs | 145 ++ .../org_tangled/temp/account/delete_email.rs | 96 + .../temp/account/dismiss_newsletter.rs | 52 + .../org_tangled/temp/account/list_emails.rs | 390 +++ .../temp/account/set_primary_email.rs | 106 + .../temp/account/subscribe_newsletter.rs | 52 + .../src/org_tangled/temp/focus.rs | 9 + .../org_tangled/temp/focus/begin_session.rs | 113 + .../src/org_tangled/temp/focus/end_session.rs | 52 + .../src/org_tangled/temp/focus/next_item.rs | 197 ++ .../src/org_tangled/temp/notification.rs | 13 + .../temp/notification/delete_notification.rs | 174 ++ .../temp/notification/get_preferences.rs | 717 ++++++ .../temp/notification/get_unread_count.rs | 62 + .../temp/notification/list_notifications.rs | 786 ++++++ .../temp/notification/mark_all_read.rs | 52 + .../temp/notification/update_preferences.rs | 77 + .../temp/notification/update_seen.rs | 209 ++ .../jacquard-api/src/org_tangled/temp/repo.rs | 16 + .../org_tangled/temp/repo/create_webhook.rs | 340 +++ .../org_tangled/temp/repo/delete_webhook.rs | 247 ++ .../src/org_tangled/temp/repo/disable_site.rs | 212 ++ .../org_tangled/temp/repo/get_site_config.rs | 484 ++++ .../temp/repo/list_webhook_deliveries.rs | 769 ++++++ .../org_tangled/temp/repo/list_webhooks.rs | 611 +++++ .../temp/repo/retry_webhook_delivery.rs | 300 +++ .../org_tangled/temp/repo/toggle_webhook.rs | 259 ++ .../temp/repo/update_site_config.rs | 304 +++ .../org_tangled/temp/repo/update_webhook.rs | 322 +++ .../src/org_tangled/temp/search.rs | 7 + .../org_tangled/temp/search/search_code.rs | 1060 ++++++++ .../jacquard-api/src/org_tangled/temp/site.rs | 9 + .../src/org_tangled/temp/site/claim_domain.rs | 126 + .../org_tangled/temp/site/get_domain_claim.rs | 64 + .../org_tangled/temp/site/release_domain.rs | 96 + crates/jacquard-api/src/pink_vase/pod/show.rs | 12 + crates/jacquard-api/src/place_stream.rs | 5 + .../src/place_stream/auth_full.rs | 8 + .../place_stream/broadcast/get_broadcaster.rs | 29 +- .../src/place_stream/chat/profile.rs | 1 - .../place_stream/live/subscribe_segments.rs | 29 +- .../src/place_stream/live/teleport.rs | 49 +- .../src/place_stream/livestream.rs | 27 +- crates/jacquard-api/src/place_stream/media.rs | 1 + .../src/place_stream/media/create_upload.rs | 44 +- .../place_stream/media/finalize_livestream.rs | 236 ++ .../jacquard-api/src/place_stream/server.rs | 12 + .../src/place_stream/server/settings.rs | 31 +- crates/jacquard-api/src/place_stream/video.rs | 26 + crates/jacquard-api/src/place_stream/vod.rs | 8 + .../src/place_stream/vod/create_draft.rs | 69 + .../src/place_stream/vod/delete_draft.rs | 106 + .../src/place_stream/vod/draft_defs.rs | 300 +++ .../src/place_stream/vod/draft_video.rs | 935 ++++++++ .../src/place_stream/vod/get_draft.rs | 207 ++ .../src/place_stream/vod/list_drafts.rs | 179 ++ .../src/place_stream/vod/publish_draft.rs | 121 + .../src/place_stream/vod/update_draft.rs | 140 ++ .../jacquard-api/src/place_wisp/settings.rs | 12 + crates/jacquard-api/src/pub_leaflet/blocks.rs | 4 + .../src/pub_leaflet/blocks/html.rs | 332 +++ .../src/pub_leaflet/blocks/iframe.rs | 171 +- .../src/pub_leaflet/blocks/image.rs | 29 +- .../src/pub_leaflet/blocks/image_gallery.rs | 838 +++++++ .../blocks/members_only_delimiter.rs | 95 + .../src/pub_leaflet/blocks/posts_list.rs | 4 + .../blocks/standard_site_publication.rs | 255 ++ .../jacquard-api/src/pub_leaflet/document.rs | 12 + crates/jacquard-api/src/pub_leaflet/graph.rs | 1 + .../src/pub_leaflet/graph/recommendations.rs | 335 +++ .../src/pub_leaflet/pages/canvas.rs | 18 + .../src/pub_leaflet/pages/linear_document.rs | 18 + .../src/pub_leaflet/publication.rs | 88 + .../jacquard-api/src/pub_quizzy/team_score.rs | 9 + .../src/science_alt/dataset/entry.rs | 12 + .../src/science_alt/dataset/lens.rs | 10 + .../science_alt/dataset/lens_verification.rs | 11 + .../science_alt/dataset/storage_external.rs | 10 + crates/jacquard-api/src/sh_tangled.rs | 2 + crates/jacquard-api/src/sh_tangled/actor.rs | 2 + .../src/sh_tangled/actor/get_profile.rs | 177 ++ .../src/sh_tangled/actor/get_profiles.rs | 453 ++++ crates/jacquard-api/src/sh_tangled/ci.rs | 16 + .../src/sh_tangled/ci/cancel_pipeline.rs | 229 ++ .../ci/describe_workflow_definition.rs | 275 +++ .../src/sh_tangled/ci/get_pipeline.rs | 208 ++ .../src/sh_tangled/ci/pipeline.rs | 619 +++++ .../src/sh_tangled/ci/query_pipelines.rs | 291 +++ .../sh_tangled/ci/subscribe_pipeline_logs.rs | 1038 ++++++++ .../jacquard-api/src/sh_tangled/ci/trigger.rs | 452 ++++ .../src/sh_tangled/ci/trigger_pipeline.rs | 294 +++ crates/jacquard-api/src/sh_tangled/feed.rs | 6 + .../src/sh_tangled/feed/count_comments.rs | 176 ++ .../src/sh_tangled/feed/count_comments_by.rs | 176 ++ .../src/sh_tangled/feed/count_reactions.rs | 176 ++ .../src/sh_tangled/feed/count_reactions_by.rs | 176 ++ .../src/sh_tangled/feed/count_stars.rs | 175 ++ .../src/sh_tangled/feed/count_stars_by.rs | 176 ++ .../src/sh_tangled/feed/list_comments.rs | 2 +- crates/jacquard-api/src/sh_tangled/git.rs | 2 + .../src/sh_tangled/git/count_ref_updates.rs | 176 ++ .../sh_tangled/git/count_ref_updates_by.rs | 176 ++ .../src/sh_tangled/git/ref_update.rs | 184 +- crates/jacquard-api/src/sh_tangled/graph.rs | 4 + .../src/sh_tangled/graph/count_follows.rs | 176 ++ .../src/sh_tangled/graph/count_follows_by.rs | 176 ++ .../src/sh_tangled/graph/count_vouches.rs | 176 ++ .../src/sh_tangled/graph/count_vouches_by.rs | 176 ++ crates/jacquard-api/src/sh_tangled/knot.rs | 5 + .../jacquard-api/src/sh_tangled/knot/ban.rs | 172 ++ .../src/sh_tangled/knot/count_knots.rs | 176 ++ .../src/sh_tangled/knot/count_members.rs | 175 ++ .../src/sh_tangled/knot/count_members_by.rs | 176 ++ .../jacquard-api/src/sh_tangled/knot/unban.rs | 175 ++ crates/jacquard-api/src/sh_tangled/label.rs | 3 + .../src/sh_tangled/label/count_definitions.rs | 175 ++ .../src/sh_tangled/label/count_ops.rs | 175 ++ .../src/sh_tangled/label/count_ops_by.rs | 176 ++ .../jacquard-api/src/sh_tangled/pipeline.rs | 155 +- .../sh_tangled/pipeline/count_pipelines.rs | 175 ++ .../sh_tangled/pipeline/count_pipelines_by.rs | 176 ++ .../src/sh_tangled/pipeline/count_statuses.rs | 176 ++ .../sh_tangled/pipeline/count_statuses_by.rs | 176 ++ .../src/sh_tangled/pipeline/status.rs | 3 + .../jacquard-api/src/sh_tangled/publicKey.rs | 1 + .../src/sh_tangled/publicKey/count_keys.rs | 176 ++ crates/jacquard-api/src/sh_tangled/repo.rs | 43 + .../src/sh_tangled/repo/count_artifacts.rs | 175 ++ .../src/sh_tangled/repo/count_artifacts_by.rs | 176 ++ .../sh_tangled/repo/count_collaborators.rs | 176 ++ .../sh_tangled/repo/count_collaborators_by.rs | 179 ++ .../src/sh_tangled/repo/count_issues.rs | 176 ++ .../src/sh_tangled/repo/count_issues_by.rs | 176 ++ .../src/sh_tangled/repo/count_pulls.rs | 176 ++ .../src/sh_tangled/repo/count_pulls_by.rs | 176 ++ .../src/sh_tangled/repo/count_repos.rs | 176 ++ .../src/sh_tangled/repo/create.rs | 206 +- .../src/sh_tangled/repo/delete.rs | 180 +- .../src/sh_tangled/repo/delete_branch.rs | 9 +- .../src/sh_tangled/repo/fork_sync.rs | 169 +- .../src/sh_tangled/repo/get_issue.rs | 177 ++ .../src/sh_tangled/repo/get_issues.rs | 453 ++++ .../src/sh_tangled/repo/get_pull.rs | 177 ++ .../src/sh_tangled/repo/get_pulls.rs | 453 ++++ .../src/sh_tangled/repo/get_repo.rs | 177 ++ .../sh_tangled/repo/get_repo_by_repo_did.rs | 177 ++ .../src/sh_tangled/repo/get_repos.rs | 453 ++++ .../src/sh_tangled/repo/hidden_ref.rs | 10 +- .../jacquard-api/src/sh_tangled/repo/issue.rs | 76 +- .../src/sh_tangled/repo/issue/count_states.rs | 176 ++ .../sh_tangled/repo/issue/count_states_by.rs | 176 ++ .../src/sh_tangled/repo/issue/state.rs | 65 +- .../src/sh_tangled/repo/languages.rs | 3 +- .../src/sh_tangled/repo/list_secrets.rs | 3 +- .../jacquard-api/src/sh_tangled/repo/merge.rs | 126 +- .../src/sh_tangled/repo/merge_check.rs | 262 +- .../jacquard-api/src/sh_tangled/repo/pull.rs | 97 +- .../sh_tangled/repo/pull/count_statuses.rs | 176 ++ .../sh_tangled/repo/pull/count_statuses_by.rs | 176 ++ .../src/sh_tangled/repo/pull/status.rs | 65 +- .../jacquard-api/src/sh_tangled/repo/push.rs | 52 + .../src/sh_tangled/repo/rename.rs | 243 ++ .../src/sh_tangled/repo/reserve_key.rs | 188 ++ .../src/sh_tangled/repo/set_default_branch.rs | 9 +- crates/jacquard-api/src/sh_tangled/search.rs | 7 + .../src/sh_tangled/search/query.rs | 731 ++++++ crates/jacquard-api/src/sh_tangled/spindle.rs | 3 + .../src/sh_tangled/spindle/count_members.rs | 175 ++ .../sh_tangled/spindle/count_members_by.rs | 176 ++ .../src/sh_tangled/spindle/count_spindles.rs | 176 ++ crates/jacquard-api/src/sh_tangled/string.rs | 1 + .../src/sh_tangled/string/count_strings.rs | 175 ++ crates/jacquard-api/src/sh_weaver/actor.rs | 72 + .../src/sh_weaver/actor/profile.rs | 36 + crates/jacquard-api/src/sh_weaver/notebook.rs | 148 ++ .../src/sh_weaver/notebook/book.rs | 52 + .../src/sh_weaver/notebook/chapter.rs | 42 + .../src/sh_weaver/notebook/entry.rs | 54 + .../src/sh_weaver/notebook/page.rs | 32 + .../src/site_standard/document.rs | 26 + .../src/social_arabica/alpha/bean.rs | 6 +- .../src/social_arabica/alpha/brew.rs | 8 +- crates/jacquard-api/src/social_coves.rs | 0 crates/jacquard-api/src/social_coves/actor.rs | 0 .../src/social_coves/actor/block.rs | 0 .../src/social_coves/actor/get_comments.rs | 0 .../src/social_coves/actor/get_posts.rs | 0 .../src/social_coves/actor/get_profile.rs | 0 .../src/social_coves/actor/profile.rs | 0 .../src/social_coves/actor/signup.rs | 0 .../src/social_coves/actor/update_profile.rs | 0 .../src/social_coves/aggregator.rs | 0 .../social_coves/aggregator/authorization.rs | 0 .../social_coves/aggregator/create_api_key.rs | 0 .../src/social_coves/aggregator/disable.rs | 0 .../src/social_coves/aggregator/enable.rs | 0 .../social_coves/aggregator/get_api_key.rs | 0 .../aggregator/get_authorizations.rs | 0 .../social_coves/aggregator/get_services.rs | 0 .../aggregator/list_for_community.rs | 0 .../src/social_coves/aggregator/register.rs | 0 .../social_coves/aggregator/revoke_api_key.rs | 0 .../src/social_coves/aggregator/service.rs | 0 .../social_coves/aggregator/update_config.rs | 0 .../src/social_coves/community.rs | 0 .../src/social_coves/community/block.rs | 0 .../src/social_coves/community/comment.rs | 0 .../social_coves/community/comment/delete.rs | 0 .../community/comment/get_comments.rs | 0 .../social_coves/community/comment/update.rs | 0 .../src/social_coves/community/create.rs | 0 .../src/social_coves/community/get.rs | 0 .../src/social_coves/community/get_members.rs | 0 .../social_coves/community/get_subscribers.rs | 0 .../src/social_coves/community/list.rs | 0 .../src/social_coves/community/post.rs | 0 .../src/social_coves/community/post/create.rs | 0 .../src/social_coves/community/post/delete.rs | 0 .../src/social_coves/community/post/get.rs | 0 .../src/social_coves/community/post/search.rs | 0 .../src/social_coves/community/post/update.rs | 0 .../src/social_coves/community/profile.rs | 0 .../src/social_coves/community/search.rs | 0 .../src/social_coves/community/subscribe.rs | 0 .../social_coves/community/subscription.rs | 0 .../src/social_coves/community/unsubscribe.rs | 0 .../src/social_coves/community/update.rs | 0 .../src/social_coves/community/wiki.rs | 0 crates/jacquard-api/src/social_coves/embed.rs | 0 .../src/social_coves/embed/external.rs | 0 .../src/social_coves/embed/images.rs | 0 .../src/social_coves/embed/post.rs | 0 .../src/social_coves/embed/video.rs | 0 crates/jacquard-api/src/social_coves/feed.rs | 0 .../src/social_coves/feed/get_all.rs | 0 .../src/social_coves/feed/get_community.rs | 0 .../src/social_coves/feed/get_discover.rs | 0 .../src/social_coves/feed/get_timeline.rs | 0 .../src/social_coves/feed/vote.rs | 0 .../src/social_coves/feed/vote/create.rs | 0 .../src/social_coves/feed/vote/delete.rs | 0 .../src/social_pace/feed/activity.rs | 11 + crates/jacquard-api/src/social_showcase.rs | 32 + .../src/social_showcase/library/item.rs | 10 + .../src/social_showcase/profile/profile.rs | 10 + .../src/systems_timker/hawlt/note.rs | 26 + .../src/tech_manos/twmirror/post.rs | 44 + crates/jacquard-api/src/tech_tokimeki/kaku.rs | 52 + .../src/tech_tokimeki/kaku/post.rs | 26 + .../src/tech_tokimeki/kaku/request.rs | 12 + .../src/tech_tokimeki/poll/poll.rs | 22 + crates/jacquard-api/src/tools_ozone/queue.rs | 193 +- .../src/tools_ozone/queue/create_queue.rs | 242 +- .../src/tools_ozone/queue/update_queue.rs | 71 +- crates/jacquard-api/src/tools_ozone/report.rs | 113 +- .../src/tools_ozone/report/close_reports.rs | 248 ++ .../src/tools_ozone/report/create_activity.rs | 97 +- .../src/zone_stratos/feed/post.rs | 26 + .../jacquard-common/src/serde_bytes_helper.rs | 44 +- crates/jacquard-common/src/types.rs | 2 +- crates/jacquard-common/src/types/aturi.rs | 16 +- crates/jacquard-common/src/types/cid.rs | 2 +- crates/jacquard-lexicon/src/codegen.rs | 1 + .../jacquard-lexicon/src/codegen/collect.rs | 5 + .../jacquard-lexicon/src/codegen/prettify.rs | 4 + .../jacquard-lexicon/src/codegen/structs.rs | 40 + .../src/codegen/type_param.rs | 1 + crates/jacquard-lexicon/src/codegen/types.rs | 1 + .../src/derive_impl/doc_to_tokens.rs | 51 + crates/jacquard-lexicon/src/lexicon.rs | 47 + crates/jacquard-oauth/src/dpop.rs | 1 + crates/jacquard-oauth/src/jose/jwt.rs | 28 +- crates/jacquard-repo/Cargo.toml | 2 + crates/jacquard-repo/src/lib.rs | 4 +- crates/jacquard-repo/src/permissioned/mod.rs | 822 ++++++- 400 files changed, 60704 insertions(+), 1580 deletions(-) create mode 100644 crates/jacquard-api/src/com_atproto/simplespace.rs create mode 100644 crates/jacquard-api/src/com_atproto/simplespace/add_member.rs create mode 100644 crates/jacquard-api/src/com_atproto/simplespace/check_user_access.rs create mode 100644 crates/jacquard-api/src/com_atproto/simplespace/create_space.rs create mode 100644 crates/jacquard-api/src/com_atproto/simplespace/delete_space.rs create mode 100644 crates/jacquard-api/src/com_atproto/simplespace/get_space.rs create mode 100644 crates/jacquard-api/src/com_atproto/simplespace/list_members.rs create mode 100644 crates/jacquard-api/src/com_atproto/simplespace/remove_member.rs create mode 100644 crates/jacquard-api/src/com_atproto/simplespace/update_space.rs create mode 100644 crates/jacquard-api/src/com_atproto/space.rs create mode 100644 crates/jacquard-api/src/com_atproto/space/apply_writes.rs create mode 100644 crates/jacquard-api/src/com_atproto/space/create_record.rs create mode 100644 crates/jacquard-api/src/com_atproto/space/delete_record.rs create mode 100644 crates/jacquard-api/src/com_atproto/space/get_blob.rs create mode 100644 crates/jacquard-api/src/com_atproto/space/get_delegation_token.rs create mode 100644 crates/jacquard-api/src/com_atproto/space/get_latest_commit.rs create mode 100644 crates/jacquard-api/src/com_atproto/space/get_record.rs create mode 100644 crates/jacquard-api/src/com_atproto/space/get_repo.rs create mode 100644 crates/jacquard-api/src/com_atproto/space/get_space_credential.rs create mode 100644 crates/jacquard-api/src/com_atproto/space/list_blobs.rs create mode 100644 crates/jacquard-api/src/com_atproto/space/list_records.rs create mode 100644 crates/jacquard-api/src/com_atproto/space/list_repo_ops.rs create mode 100644 crates/jacquard-api/src/com_atproto/space/list_repos.rs create mode 100644 crates/jacquard-api/src/com_atproto/space/list_spaces.rs create mode 100644 crates/jacquard-api/src/com_atproto/space/notify_space_deleted.rs create mode 100644 crates/jacquard-api/src/com_atproto/space/notify_write.rs create mode 100644 crates/jacquard-api/src/com_atproto/space/put_record.rs create mode 100644 crates/jacquard-api/src/com_atproto/space/register_notify.rs create mode 100644 crates/jacquard-api/src/com_atproto/space/unregister_notify.rs create mode 100644 crates/jacquard-api/src/dev_atfs.rs create mode 100644 crates/jacquard-api/src/dev_atfs/file.rs create mode 100644 crates/jacquard-api/src/dev_atfs/repo.rs create mode 100644 crates/jacquard-api/src/dev_atfs/repo/delete_file.rs create mode 100644 crates/jacquard-api/src/dev_atfs/repo/get_file.rs create mode 100644 crates/jacquard-api/src/dev_atfs/repo/list_files.rs create mode 100644 crates/jacquard-api/src/dev_atfs/repo/pin_file.rs create mode 100644 crates/jacquard-api/src/dev_atfs/repo/upload_file.rs create mode 100644 crates/jacquard-api/src/dev_atfs/server.rs create mode 100644 crates/jacquard-api/src/io_atcr/auth_full_app.rs create mode 100644 crates/jacquard-api/src/io_atcr/hold/get_layers_for_manifest.rs create mode 100644 crates/jacquard-api/src/net_anisota/chronicle/fieldwork.rs create mode 100644 crates/jacquard-api/src/net_anisota/chronicle/milestone.rs create mode 100644 crates/jacquard-api/src/net_anisota/chronicle/walk.rs create mode 100644 crates/jacquard-api/src/net_anisota/chronicle/walk/camp.rs create mode 100644 crates/jacquard-api/src/net_anisota/fieldwork.rs create mode 100644 crates/jacquard-api/src/net_anisota/fieldwork/state.rs create mode 100644 crates/jacquard-api/src/net_anisota/graph/scoped_mute.rs create mode 100644 crates/jacquard-api/src/net_anisota/graph/wordlist.rs create mode 100644 crates/jacquard-api/src/net_anisota/lab/plasmodium.rs create mode 100644 crates/jacquard-api/src/net_anisota/spell.rs create mode 100644 crates/jacquard-api/src/net_anisota/spell/book.rs create mode 100644 crates/jacquard-api/src/net_anisota/spell/custom.rs create mode 100644 crates/jacquard-api/src/org_tangled.rs create mode 100644 crates/jacquard-api/src/org_tangled/temp.rs create mode 100644 crates/jacquard-api/src/org_tangled/temp/account.rs create mode 100644 crates/jacquard-api/src/org_tangled/temp/account/begin_signup.rs create mode 100644 crates/jacquard-api/src/org_tangled/temp/account/complete_signup.rs create mode 100644 crates/jacquard-api/src/org_tangled/temp/account/delete_email.rs create mode 100644 crates/jacquard-api/src/org_tangled/temp/account/dismiss_newsletter.rs create mode 100644 crates/jacquard-api/src/org_tangled/temp/account/list_emails.rs create mode 100644 crates/jacquard-api/src/org_tangled/temp/account/set_primary_email.rs create mode 100644 crates/jacquard-api/src/org_tangled/temp/account/subscribe_newsletter.rs create mode 100644 crates/jacquard-api/src/org_tangled/temp/focus.rs create mode 100644 crates/jacquard-api/src/org_tangled/temp/focus/begin_session.rs create mode 100644 crates/jacquard-api/src/org_tangled/temp/focus/end_session.rs create mode 100644 crates/jacquard-api/src/org_tangled/temp/focus/next_item.rs create mode 100644 crates/jacquard-api/src/org_tangled/temp/notification.rs create mode 100644 crates/jacquard-api/src/org_tangled/temp/notification/delete_notification.rs create mode 100644 crates/jacquard-api/src/org_tangled/temp/notification/get_preferences.rs create mode 100644 crates/jacquard-api/src/org_tangled/temp/notification/get_unread_count.rs create mode 100644 crates/jacquard-api/src/org_tangled/temp/notification/list_notifications.rs create mode 100644 crates/jacquard-api/src/org_tangled/temp/notification/mark_all_read.rs create mode 100644 crates/jacquard-api/src/org_tangled/temp/notification/update_preferences.rs create mode 100644 crates/jacquard-api/src/org_tangled/temp/notification/update_seen.rs create mode 100644 crates/jacquard-api/src/org_tangled/temp/repo.rs create mode 100644 crates/jacquard-api/src/org_tangled/temp/repo/create_webhook.rs create mode 100644 crates/jacquard-api/src/org_tangled/temp/repo/delete_webhook.rs create mode 100644 crates/jacquard-api/src/org_tangled/temp/repo/disable_site.rs create mode 100644 crates/jacquard-api/src/org_tangled/temp/repo/get_site_config.rs create mode 100644 crates/jacquard-api/src/org_tangled/temp/repo/list_webhook_deliveries.rs create mode 100644 crates/jacquard-api/src/org_tangled/temp/repo/list_webhooks.rs create mode 100644 crates/jacquard-api/src/org_tangled/temp/repo/retry_webhook_delivery.rs create mode 100644 crates/jacquard-api/src/org_tangled/temp/repo/toggle_webhook.rs create mode 100644 crates/jacquard-api/src/org_tangled/temp/repo/update_site_config.rs create mode 100644 crates/jacquard-api/src/org_tangled/temp/repo/update_webhook.rs create mode 100644 crates/jacquard-api/src/org_tangled/temp/search.rs create mode 100644 crates/jacquard-api/src/org_tangled/temp/search/search_code.rs create mode 100644 crates/jacquard-api/src/org_tangled/temp/site.rs create mode 100644 crates/jacquard-api/src/org_tangled/temp/site/claim_domain.rs create mode 100644 crates/jacquard-api/src/org_tangled/temp/site/get_domain_claim.rs create mode 100644 crates/jacquard-api/src/org_tangled/temp/site/release_domain.rs create mode 100644 crates/jacquard-api/src/place_stream/auth_full.rs create mode 100644 crates/jacquard-api/src/place_stream/media/finalize_livestream.rs create mode 100644 crates/jacquard-api/src/place_stream/vod/create_draft.rs create mode 100644 crates/jacquard-api/src/place_stream/vod/delete_draft.rs create mode 100644 crates/jacquard-api/src/place_stream/vod/draft_defs.rs create mode 100644 crates/jacquard-api/src/place_stream/vod/draft_video.rs create mode 100644 crates/jacquard-api/src/place_stream/vod/get_draft.rs create mode 100644 crates/jacquard-api/src/place_stream/vod/list_drafts.rs create mode 100644 crates/jacquard-api/src/place_stream/vod/publish_draft.rs create mode 100644 crates/jacquard-api/src/place_stream/vod/update_draft.rs create mode 100644 crates/jacquard-api/src/pub_leaflet/blocks/html.rs create mode 100644 crates/jacquard-api/src/pub_leaflet/blocks/image_gallery.rs create mode 100644 crates/jacquard-api/src/pub_leaflet/blocks/members_only_delimiter.rs create mode 100644 crates/jacquard-api/src/pub_leaflet/blocks/standard_site_publication.rs create mode 100644 crates/jacquard-api/src/pub_leaflet/graph/recommendations.rs create mode 100644 crates/jacquard-api/src/sh_tangled/actor/get_profile.rs create mode 100644 crates/jacquard-api/src/sh_tangled/actor/get_profiles.rs create mode 100644 crates/jacquard-api/src/sh_tangled/ci.rs create mode 100644 crates/jacquard-api/src/sh_tangled/ci/cancel_pipeline.rs create mode 100644 crates/jacquard-api/src/sh_tangled/ci/describe_workflow_definition.rs create mode 100644 crates/jacquard-api/src/sh_tangled/ci/get_pipeline.rs create mode 100644 crates/jacquard-api/src/sh_tangled/ci/pipeline.rs create mode 100644 crates/jacquard-api/src/sh_tangled/ci/query_pipelines.rs create mode 100644 crates/jacquard-api/src/sh_tangled/ci/subscribe_pipeline_logs.rs create mode 100644 crates/jacquard-api/src/sh_tangled/ci/trigger.rs create mode 100644 crates/jacquard-api/src/sh_tangled/ci/trigger_pipeline.rs create mode 100644 crates/jacquard-api/src/sh_tangled/feed/count_comments.rs create mode 100644 crates/jacquard-api/src/sh_tangled/feed/count_comments_by.rs create mode 100644 crates/jacquard-api/src/sh_tangled/feed/count_reactions.rs create mode 100644 crates/jacquard-api/src/sh_tangled/feed/count_reactions_by.rs create mode 100644 crates/jacquard-api/src/sh_tangled/feed/count_stars.rs create mode 100644 crates/jacquard-api/src/sh_tangled/feed/count_stars_by.rs create mode 100644 crates/jacquard-api/src/sh_tangled/git/count_ref_updates.rs create mode 100644 crates/jacquard-api/src/sh_tangled/git/count_ref_updates_by.rs create mode 100644 crates/jacquard-api/src/sh_tangled/graph/count_follows.rs create mode 100644 crates/jacquard-api/src/sh_tangled/graph/count_follows_by.rs create mode 100644 crates/jacquard-api/src/sh_tangled/graph/count_vouches.rs create mode 100644 crates/jacquard-api/src/sh_tangled/graph/count_vouches_by.rs create mode 100644 crates/jacquard-api/src/sh_tangled/knot/ban.rs create mode 100644 crates/jacquard-api/src/sh_tangled/knot/count_knots.rs create mode 100644 crates/jacquard-api/src/sh_tangled/knot/count_members.rs create mode 100644 crates/jacquard-api/src/sh_tangled/knot/count_members_by.rs create mode 100644 crates/jacquard-api/src/sh_tangled/knot/unban.rs create mode 100644 crates/jacquard-api/src/sh_tangled/label/count_definitions.rs create mode 100644 crates/jacquard-api/src/sh_tangled/label/count_ops.rs create mode 100644 crates/jacquard-api/src/sh_tangled/label/count_ops_by.rs create mode 100644 crates/jacquard-api/src/sh_tangled/pipeline/count_pipelines.rs create mode 100644 crates/jacquard-api/src/sh_tangled/pipeline/count_pipelines_by.rs create mode 100644 crates/jacquard-api/src/sh_tangled/pipeline/count_statuses.rs create mode 100644 crates/jacquard-api/src/sh_tangled/pipeline/count_statuses_by.rs create mode 100644 crates/jacquard-api/src/sh_tangled/publicKey/count_keys.rs create mode 100644 crates/jacquard-api/src/sh_tangled/repo/count_artifacts.rs create mode 100644 crates/jacquard-api/src/sh_tangled/repo/count_artifacts_by.rs create mode 100644 crates/jacquard-api/src/sh_tangled/repo/count_collaborators.rs create mode 100644 crates/jacquard-api/src/sh_tangled/repo/count_collaborators_by.rs create mode 100644 crates/jacquard-api/src/sh_tangled/repo/count_issues.rs create mode 100644 crates/jacquard-api/src/sh_tangled/repo/count_issues_by.rs create mode 100644 crates/jacquard-api/src/sh_tangled/repo/count_pulls.rs create mode 100644 crates/jacquard-api/src/sh_tangled/repo/count_pulls_by.rs create mode 100644 crates/jacquard-api/src/sh_tangled/repo/count_repos.rs create mode 100644 crates/jacquard-api/src/sh_tangled/repo/get_issue.rs create mode 100644 crates/jacquard-api/src/sh_tangled/repo/get_issues.rs create mode 100644 crates/jacquard-api/src/sh_tangled/repo/get_pull.rs create mode 100644 crates/jacquard-api/src/sh_tangled/repo/get_pulls.rs create mode 100644 crates/jacquard-api/src/sh_tangled/repo/get_repo.rs create mode 100644 crates/jacquard-api/src/sh_tangled/repo/get_repo_by_repo_did.rs create mode 100644 crates/jacquard-api/src/sh_tangled/repo/get_repos.rs create mode 100644 crates/jacquard-api/src/sh_tangled/repo/issue/count_states.rs create mode 100644 crates/jacquard-api/src/sh_tangled/repo/issue/count_states_by.rs create mode 100644 crates/jacquard-api/src/sh_tangled/repo/pull/count_statuses.rs create mode 100644 crates/jacquard-api/src/sh_tangled/repo/pull/count_statuses_by.rs create mode 100644 crates/jacquard-api/src/sh_tangled/repo/push.rs create mode 100644 crates/jacquard-api/src/sh_tangled/repo/rename.rs create mode 100644 crates/jacquard-api/src/sh_tangled/repo/reserve_key.rs create mode 100644 crates/jacquard-api/src/sh_tangled/search.rs create mode 100644 crates/jacquard-api/src/sh_tangled/search/query.rs create mode 100644 crates/jacquard-api/src/sh_tangled/spindle/count_members.rs create mode 100644 crates/jacquard-api/src/sh_tangled/spindle/count_members_by.rs create mode 100644 crates/jacquard-api/src/sh_tangled/spindle/count_spindles.rs create mode 100644 crates/jacquard-api/src/sh_tangled/string/count_strings.rs create mode 100644 crates/jacquard-api/src/social_coves.rs create mode 100644 crates/jacquard-api/src/social_coves/actor.rs create mode 100644 crates/jacquard-api/src/social_coves/actor/block.rs create mode 100644 crates/jacquard-api/src/social_coves/actor/get_comments.rs create mode 100644 crates/jacquard-api/src/social_coves/actor/get_posts.rs create mode 100644 crates/jacquard-api/src/social_coves/actor/get_profile.rs create mode 100644 crates/jacquard-api/src/social_coves/actor/profile.rs create mode 100644 crates/jacquard-api/src/social_coves/actor/signup.rs create mode 100644 crates/jacquard-api/src/social_coves/actor/update_profile.rs create mode 100644 crates/jacquard-api/src/social_coves/aggregator.rs create mode 100644 crates/jacquard-api/src/social_coves/aggregator/authorization.rs create mode 100644 crates/jacquard-api/src/social_coves/aggregator/create_api_key.rs create mode 100644 crates/jacquard-api/src/social_coves/aggregator/disable.rs create mode 100644 crates/jacquard-api/src/social_coves/aggregator/enable.rs create mode 100644 crates/jacquard-api/src/social_coves/aggregator/get_api_key.rs create mode 100644 crates/jacquard-api/src/social_coves/aggregator/get_authorizations.rs create mode 100644 crates/jacquard-api/src/social_coves/aggregator/get_services.rs create mode 100644 crates/jacquard-api/src/social_coves/aggregator/list_for_community.rs create mode 100644 crates/jacquard-api/src/social_coves/aggregator/register.rs create mode 100644 crates/jacquard-api/src/social_coves/aggregator/revoke_api_key.rs create mode 100644 crates/jacquard-api/src/social_coves/aggregator/service.rs create mode 100644 crates/jacquard-api/src/social_coves/aggregator/update_config.rs create mode 100644 crates/jacquard-api/src/social_coves/community.rs create mode 100644 crates/jacquard-api/src/social_coves/community/block.rs create mode 100644 crates/jacquard-api/src/social_coves/community/comment.rs create mode 100644 crates/jacquard-api/src/social_coves/community/comment/delete.rs create mode 100644 crates/jacquard-api/src/social_coves/community/comment/get_comments.rs create mode 100644 crates/jacquard-api/src/social_coves/community/comment/update.rs create mode 100644 crates/jacquard-api/src/social_coves/community/create.rs create mode 100644 crates/jacquard-api/src/social_coves/community/get.rs create mode 100644 crates/jacquard-api/src/social_coves/community/get_members.rs create mode 100644 crates/jacquard-api/src/social_coves/community/get_subscribers.rs create mode 100644 crates/jacquard-api/src/social_coves/community/list.rs create mode 100644 crates/jacquard-api/src/social_coves/community/post.rs create mode 100644 crates/jacquard-api/src/social_coves/community/post/create.rs create mode 100644 crates/jacquard-api/src/social_coves/community/post/delete.rs create mode 100644 crates/jacquard-api/src/social_coves/community/post/get.rs create mode 100644 crates/jacquard-api/src/social_coves/community/post/search.rs create mode 100644 crates/jacquard-api/src/social_coves/community/post/update.rs create mode 100644 crates/jacquard-api/src/social_coves/community/profile.rs create mode 100644 crates/jacquard-api/src/social_coves/community/search.rs create mode 100644 crates/jacquard-api/src/social_coves/community/subscribe.rs create mode 100644 crates/jacquard-api/src/social_coves/community/subscription.rs create mode 100644 crates/jacquard-api/src/social_coves/community/unsubscribe.rs create mode 100644 crates/jacquard-api/src/social_coves/community/update.rs create mode 100644 crates/jacquard-api/src/social_coves/community/wiki.rs create mode 100644 crates/jacquard-api/src/social_coves/embed.rs create mode 100644 crates/jacquard-api/src/social_coves/embed/external.rs create mode 100644 crates/jacquard-api/src/social_coves/embed/images.rs create mode 100644 crates/jacquard-api/src/social_coves/embed/post.rs create mode 100644 crates/jacquard-api/src/social_coves/embed/video.rs create mode 100644 crates/jacquard-api/src/social_coves/feed.rs create mode 100644 crates/jacquard-api/src/social_coves/feed/get_all.rs create mode 100644 crates/jacquard-api/src/social_coves/feed/get_community.rs create mode 100644 crates/jacquard-api/src/social_coves/feed/get_discover.rs create mode 100644 crates/jacquard-api/src/social_coves/feed/get_timeline.rs create mode 100644 crates/jacquard-api/src/social_coves/feed/vote.rs create mode 100644 crates/jacquard-api/src/social_coves/feed/vote/create.rs create mode 100644 crates/jacquard-api/src/social_coves/feed/vote/delete.rs create mode 100644 crates/jacquard-api/src/tools_ozone/report/close_reports.rs diff --git a/Cargo.lock b/Cargo.lock index b96bd777a..171cfb1a6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2723,6 +2723,7 @@ dependencies = [ "jacquard-api", "jacquard-common", "jacquard-derive", + "jacquard-lexicon", "k256", "miette", "multihash", @@ -2740,6 +2741,7 @@ dependencies = [ "thiserror 2.0.18", "tokio", "trait-variant", + "url", ] [[package]] diff --git a/crates/jacquard-api/src/app_rocksky/album.rs b/crates/jacquard-api/src/app_rocksky/album.rs index 4c0aaf297..70c5567e5 100644 --- a/crates/jacquard-api/src/app_rocksky/album.rs +++ b/crates/jacquard-api/src/app_rocksky/album.rs @@ -293,6 +293,30 @@ impl LexiconSchema for Album { }); } } + if let Some(values) = &self.tags { + for value in values { + #[allow(unused_comparisons)] + if ::len(value.as_ref()) > 256usize { + return Err(ConstraintError::MaxLength { + path: ValidationPath::from_field("tags"), + max: 256usize, + actual: ::len(value.as_ref()), + }); + } + } + } + if let Some(values) = &self.tags { + for value in values { + #[allow(unused_comparisons)] + if ::len(value.as_ref()) < 1usize { + return Err(ConstraintError::MinLength { + path: ValidationPath::from_field("tags"), + min: 1usize, + actual: ::len(value.as_ref()), + }); + } + } + } { let value = &self.title; #[allow(unused_comparisons)] diff --git a/crates/jacquard-api/src/app_rocksky/artist.rs b/crates/jacquard-api/src/app_rocksky/artist.rs index 14c6ec2d9..80c9f183d 100644 --- a/crates/jacquard-api/src/app_rocksky/artist.rs +++ b/crates/jacquard-api/src/app_rocksky/artist.rs @@ -264,6 +264,30 @@ impl LexiconSchema for Artist { } } } + if let Some(values) = &self.tags { + for value in values { + #[allow(unused_comparisons)] + if ::len(value.as_ref()) > 256usize { + return Err(ConstraintError::MaxLength { + path: ValidationPath::from_field("tags"), + max: 256usize, + actual: ::len(value.as_ref()), + }); + } + } + } + if let Some(values) = &self.tags { + for value in values { + #[allow(unused_comparisons)] + if ::len(value.as_ref()) < 1usize { + return Err(ConstraintError::MinLength { + path: ValidationPath::from_field("tags"), + min: 1usize, + actual: ::len(value.as_ref()), + }); + } + } + } Ok(()) } } diff --git a/crates/jacquard-api/src/app_rocksky/scrobble.rs b/crates/jacquard-api/src/app_rocksky/scrobble.rs index b446cf584..9aa45a57f 100644 --- a/crates/jacquard-api/src/app_rocksky/scrobble.rs +++ b/crates/jacquard-api/src/app_rocksky/scrobble.rs @@ -427,6 +427,30 @@ impl LexiconSchema for Scrobble { }); } } + if let Some(values) = &self.tags { + for value in values { + #[allow(unused_comparisons)] + if ::len(value.as_ref()) > 256usize { + return Err(ConstraintError::MaxLength { + path: ValidationPath::from_field("tags"), + max: 256usize, + actual: ::len(value.as_ref()), + }); + } + } + } + if let Some(values) = &self.tags { + for value in values { + #[allow(unused_comparisons)] + if ::len(value.as_ref()) < 1usize { + return Err(ConstraintError::MinLength { + path: ValidationPath::from_field("tags"), + min: 1usize, + actual: ::len(value.as_ref()), + }); + } + } + } { let value = &self.title; #[allow(unused_comparisons)] diff --git a/crates/jacquard-api/src/app_rocksky/song.rs b/crates/jacquard-api/src/app_rocksky/song.rs index 432c07ca5..091eb219c 100644 --- a/crates/jacquard-api/src/app_rocksky/song.rs +++ b/crates/jacquard-api/src/app_rocksky/song.rs @@ -462,6 +462,30 @@ impl LexiconSchema for Song { }); } } + if let Some(values) = &self.tags { + for value in values { + #[allow(unused_comparisons)] + if ::len(value.as_ref()) > 256usize { + return Err(ConstraintError::MaxLength { + path: ValidationPath::from_field("tags"), + max: 256usize, + actual: ::len(value.as_ref()), + }); + } + } + } + if let Some(values) = &self.tags { + for value in values { + #[allow(unused_comparisons)] + if ::len(value.as_ref()) < 1usize { + return Err(ConstraintError::MinLength { + path: ValidationPath::from_field("tags"), + min: 1usize, + actual: ::len(value.as_ref()), + }); + } + } + } { let value = &self.title; #[allow(unused_comparisons)] diff --git a/crates/jacquard-api/src/at_margin/annotation.rs b/crates/jacquard-api/src/at_margin/annotation.rs index c61c4aa5a..e25f438a1 100644 --- a/crates/jacquard-api/src/at_margin/annotation.rs +++ b/crates/jacquard-api/src/at_margin/annotation.rs @@ -586,6 +586,32 @@ impl LexiconSchema for Annotation { }); } } + if let Some(values) = &self.tags { + for value in values { + #[allow(unused_comparisons)] + if ::len(value.as_ref()) > 64usize { + return Err(ConstraintError::MaxLength { + path: ValidationPath::from_field("tags"), + max: 64usize, + actual: ::len(value.as_ref()), + }); + } + } + } + if let Some(values) = &self.tags { + for value in values { + { + let count = UnicodeSegmentation::graphemes(value.as_ref(), true).count(); + if count > 32usize { + return Err(ConstraintError::MaxGraphemes { + path: ValidationPath::from_field("tags"), + max: 32usize, + actual: count, + }); + } + } + } + } Ok(()) } } diff --git a/crates/jacquard-api/src/at_margin/preferences.rs b/crates/jacquard-api/src/at_margin/preferences.rs index 91758eddb..bba4ebd2b 100644 --- a/crates/jacquard-api/src/at_margin/preferences.rs +++ b/crates/jacquard-api/src/at_margin/preferences.rs @@ -264,6 +264,18 @@ impl LexiconSchema for Preferences { }); } } + if let Some(values) = &self.external_link_skipped_hostnames { + for value in values { + #[allow(unused_comparisons)] + if ::len(value.as_ref()) > 255usize { + return Err(ConstraintError::MaxLength { + path: ValidationPath::from_field("external_link_skipped_hostnames"), + max: 255usize, + actual: ::len(value.as_ref()), + }); + } + } + } if let Some(ref value) = self.label_preferences { #[allow(unused_comparisons)] if value.len() > 500usize { diff --git a/crates/jacquard-api/src/at_margin/profile.rs b/crates/jacquard-api/src/at_margin/profile.rs index 135d62169..57face73c 100644 --- a/crates/jacquard-api/src/at_margin/profile.rs +++ b/crates/jacquard-api/src/at_margin/profile.rs @@ -178,6 +178,18 @@ impl LexiconSchema for Profile { }); } } + if let Some(values) = &self.links { + for value in values { + #[allow(unused_comparisons)] + if ::len(value.as_ref()) > 1000usize { + return Err(ConstraintError::MaxLength { + path: ValidationPath::from_field("links"), + max: 1000usize, + actual: ::len(value.as_ref()), + }); + } + } + } if let Some(ref value) = self.website { #[allow(unused_comparisons)] if ::len(value.as_ref()) > 1000usize { diff --git a/crates/jacquard-api/src/blue_backyard/feed/post.rs b/crates/jacquard-api/src/blue_backyard/feed/post.rs index 81ece4afb..8af6d8b4b 100644 --- a/crates/jacquard-api/src/blue_backyard/feed/post.rs +++ b/crates/jacquard-api/src/blue_backyard/feed/post.rs @@ -378,6 +378,32 @@ impl LexiconSchema for Post { }); } } + if let Some(values) = &self.tags { + for value in values { + #[allow(unused_comparisons)] + if ::len(value.as_ref()) > 640usize { + return Err(ConstraintError::MaxLength { + path: ValidationPath::from_field("tags"), + max: 640usize, + actual: ::len(value.as_ref()), + }); + } + } + } + if let Some(values) = &self.tags { + for value in values { + { + let count = UnicodeSegmentation::graphemes(value.as_ref(), true).count(); + if count > 64usize { + return Err(ConstraintError::MaxGraphemes { + path: ValidationPath::from_field("tags"), + max: 64usize, + actual: count, + }); + } + } + } + } Ok(()) } } diff --git a/crates/jacquard-api/src/blue_backyard/feed/reblog.rs b/crates/jacquard-api/src/blue_backyard/feed/reblog.rs index 4031c0177..f17a03e2d 100644 --- a/crates/jacquard-api/src/blue_backyard/feed/reblog.rs +++ b/crates/jacquard-api/src/blue_backyard/feed/reblog.rs @@ -141,6 +141,32 @@ impl LexiconSchema for Reblog { }); } } + if let Some(values) = &self.tags { + for value in values { + #[allow(unused_comparisons)] + if ::len(value.as_ref()) > 640usize { + return Err(ConstraintError::MaxLength { + path: ValidationPath::from_field("tags"), + max: 640usize, + actual: ::len(value.as_ref()), + }); + } + } + } + if let Some(values) = &self.tags { + for value in values { + { + let count = UnicodeSegmentation::graphemes(value.as_ref(), true).count(); + if count > 64usize { + return Err(ConstraintError::MaxGraphemes { + path: ValidationPath::from_field("tags"), + max: 64usize, + actual: count, + }); + } + } + } + } Ok(()) } } diff --git a/crates/jacquard-api/src/blue_rito/feed/bookmark.rs b/crates/jacquard-api/src/blue_rito/feed/bookmark.rs index 3ddf7c8be..da9335d7b 100644 --- a/crates/jacquard-api/src/blue_rito/feed/bookmark.rs +++ b/crates/jacquard-api/src/blue_rito/feed/bookmark.rs @@ -224,6 +224,58 @@ impl LexiconSchema for Bookmark { }); } } + if let Some(values) = &self.tags { + for value in values { + #[allow(unused_comparisons)] + if ::len(value.as_ref()) > 250usize { + return Err(ConstraintError::MaxLength { + path: ValidationPath::from_field("tags"), + max: 250usize, + actual: ::len(value.as_ref()), + }); + } + } + } + if let Some(values) = &self.tags { + for value in values { + #[allow(unused_comparisons)] + if ::len(value.as_ref()) < 1usize { + return Err(ConstraintError::MinLength { + path: ValidationPath::from_field("tags"), + min: 1usize, + actual: ::len(value.as_ref()), + }); + } + } + } + if let Some(values) = &self.tags { + for value in values { + { + let count = UnicodeSegmentation::graphemes(value.as_ref(), true).count(); + if count > 25usize { + return Err(ConstraintError::MaxGraphemes { + path: ValidationPath::from_field("tags"), + max: 25usize, + actual: count, + }); + } + } + } + } + if let Some(values) = &self.tags { + for value in values { + { + let count = UnicodeSegmentation::graphemes(value.as_ref(), true).count(); + if count < 1usize { + return Err(ConstraintError::MinGraphemes { + path: ValidationPath::from_field("tags"), + min: 1usize, + actual: count, + }); + } + } + } + } Ok(()) } } diff --git a/crates/jacquard-api/src/chat_bsky/group/create_group.rs b/crates/jacquard-api/src/chat_bsky/group/create_group.rs index 960a4f38b..76484b0a8 100644 --- a/crates/jacquard-api/src/chat_bsky/group/create_group.rs +++ b/crates/jacquard-api/src/chat_bsky/group/create_group.rs @@ -24,6 +24,7 @@ use serde::{Deserialize, Serialize}; bound(deserialize = "S: Deserialize<'de> + BosStr") )] pub struct CreateGroup { + ///The members to add to the group. The owner is automatically added. Implementations may enforce a lower maximum than the 10,000-item schema limit; Bluesky currently supports up to 100 total members. If the owner is included in this list, the list may contain up to the implementation's total member limit. Otherwise, it may contain one fewer. pub members: Vec>, pub name: S, #[serde(flatten, default, skip_serializing_if = "Option::is_none")] diff --git a/crates/jacquard-api/src/com_atproto.rs b/crates/jacquard-api/src/com_atproto.rs index 4e134e12b..1a41555cf 100644 --- a/crates/jacquard-api/src/com_atproto.rs +++ b/crates/jacquard-api/src/com_atproto.rs @@ -11,5 +11,7 @@ pub mod lexicon; pub mod moderation; pub mod repo; pub mod server; +pub mod simplespace; +pub mod space; pub mod sync; pub mod temp; diff --git a/crates/jacquard-api/src/com_atproto/repo/strong_ref.rs b/crates/jacquard-api/src/com_atproto/repo/strong_ref.rs index af4668948..333c20368 100644 --- a/crates/jacquard-api/src/com_atproto/repo/strong_ref.rs +++ b/crates/jacquard-api/src/com_atproto/repo/strong_ref.rs @@ -233,7 +233,7 @@ where fn lexicon_doc_com_atproto_repo_strongRef() -> LexiconDoc<'static> { use alloc::collections::BTreeMap; #[allow(unused_imports)] - use jacquard_common::{deps::smol_str::SmolStr, types::blob::MimeType, CowStr}; + use jacquard_common::{CowStr, deps::smol_str::SmolStr, types::blob::MimeType}; use jacquard_lexicon::lexicon::*; LexiconDoc { lexicon: Lexicon::Lexicon1, diff --git a/crates/jacquard-api/src/com_atproto/server/describe_server.rs b/crates/jacquard-api/src/com_atproto/server/describe_server.rs index ec0eee807..2343d33ab 100644 --- a/crates/jacquard-api/src/com_atproto/server/describe_server.rs +++ b/crates/jacquard-api/src/com_atproto/server/describe_server.rs @@ -60,6 +60,9 @@ pub struct Links { pub struct DescribeServerOutput { ///List of domain suffixes that can be used in account handles. pub available_user_domains: Vec, + ///Maximum size of a blob that can be uploaded via com.atproto.repo.uploadBlob, in bytes. + #[serde(skip_serializing_if = "Option::is_none")] + pub blob_upload_limit: Option, ///Contact information #[serde(skip_serializing_if = "Option::is_none")] pub contact: Option>, diff --git a/crates/jacquard-api/src/com_atproto/simplespace.rs b/crates/jacquard-api/src/com_atproto/simplespace.rs new file mode 100644 index 000000000..d541d99a5 --- /dev/null +++ b/crates/jacquard-api/src/com_atproto/simplespace.rs @@ -0,0 +1,410 @@ +// @generated by jacquard-lexicon. DO NOT EDIT. +// +// Lexicon: com.atproto.simplespace.defs +// +// This file was automatically generated from Lexicon schemas. +// Any manual changes will be overwritten on the next regeneration. + +//! Generated bindings for the `com.atproto.simplespace` Lexicon namespace/module. +pub mod add_member; +pub mod check_user_access; +pub mod create_space; +pub mod delete_space; +pub mod get_space; +pub mod list_members; +pub mod remove_member; +pub mod update_space; + +#[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::value::Data; +use jacquard_derive::IntoStatic; +use jacquard_lexicon::lexicon::LexiconDoc; +use jacquard_lexicon::schema::LexiconSchema; + +#[allow(unused_imports)] +use jacquard_lexicon::validation::{ConstraintError, ValidationPath}; +use serde::{Deserialize, Serialize}; +/// App access policy: only the named clients may access the space, evaluated against the attested client_id. + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct AllowList { + ///The OAuth client IDs permitted to access the space. + pub allowed: Vec, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +/// User access policy: the managing app is asked, via checkUserAccess, whether to authorize each user. + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic, Default)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct ManagingAppPolicy { + ///Service identifier of the managing app: a DID with an optional service fragment (e.g. 'did:web:example.com#forum'). + pub managing_app: S, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +/// User access policy: only users on the space's member list may access it. + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic, Default)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct MemberListPolicy { + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +/// App access policy: any app may access the space. No client attestation required. + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic, Default)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct Open { + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +/// User access policy: any user may access the space. + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic, Default)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct PublicPolicy { + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +impl LexiconSchema for AllowList { + fn nsid() -> &'static str { + "com.atproto.simplespace.defs" + } + fn def_name() -> &'static str { + "allowList" + } + fn lexicon_doc() -> LexiconDoc<'static> { + lexicon_doc_com_atproto_simplespace_defs() + } + fn validate(&self) -> Result<(), ConstraintError> { + Ok(()) + } +} + +impl LexiconSchema for ManagingAppPolicy { + fn nsid() -> &'static str { + "com.atproto.simplespace.defs" + } + fn def_name() -> &'static str { + "managingAppPolicy" + } + fn lexicon_doc() -> LexiconDoc<'static> { + lexicon_doc_com_atproto_simplespace_defs() + } + fn validate(&self) -> Result<(), ConstraintError> { + Ok(()) + } +} + +impl LexiconSchema for MemberListPolicy { + fn nsid() -> &'static str { + "com.atproto.simplespace.defs" + } + fn def_name() -> &'static str { + "memberListPolicy" + } + fn lexicon_doc() -> LexiconDoc<'static> { + lexicon_doc_com_atproto_simplespace_defs() + } + fn validate(&self) -> Result<(), ConstraintError> { + Ok(()) + } +} + +impl LexiconSchema for Open { + fn nsid() -> &'static str { + "com.atproto.simplespace.defs" + } + fn def_name() -> &'static str { + "open" + } + fn lexicon_doc() -> LexiconDoc<'static> { + lexicon_doc_com_atproto_simplespace_defs() + } + fn validate(&self) -> Result<(), ConstraintError> { + Ok(()) + } +} + +impl LexiconSchema for PublicPolicy { + fn nsid() -> &'static str { + "com.atproto.simplespace.defs" + } + fn def_name() -> &'static str { + "publicPolicy" + } + fn lexicon_doc() -> LexiconDoc<'static> { + lexicon_doc_com_atproto_simplespace_defs() + } + fn validate(&self) -> Result<(), ConstraintError> { + Ok(()) + } +} + +pub mod allow_list_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 Allowed; + } + /// Empty state - all required fields are unset + pub struct Empty(()); + impl sealed::Sealed for Empty {} + impl State for Empty { + type Allowed = Unset; + } + ///State transition - sets the `allowed` field to Set + pub struct SetAllowed(PhantomData St>); + impl sealed::Sealed for SetAllowed {} + impl State for SetAllowed { + type Allowed = Set; + } + /// Marker types for field names + #[allow(non_camel_case_types)] + pub mod members { + ///Marker type for the `allowed` field + pub struct allowed(()); + } +} + +/// Builder for constructing an instance of this type. +pub struct AllowListBuilder { + _state: PhantomData St>, + _fields: (Option>,), + _type: PhantomData S>, +} + +impl AllowList { + /// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed + pub fn new() -> AllowListBuilder { + AllowListBuilder::new() + } +} + +impl AllowList { + /// Create a new builder for this type + pub fn builder() -> AllowListBuilder { + AllowListBuilder::builder() + } +} + +impl AllowListBuilder { + /// Create a new builder with all fields unset, using the default string type, if needed + pub fn new() -> Self { + AllowListBuilder { + _state: PhantomData, + _fields: (None,), + _type: PhantomData, + } + } +} + +impl AllowListBuilder { + /// Create a new builder with all fields unset + pub fn builder() -> Self { + AllowListBuilder { + _state: PhantomData, + _fields: (None,), + _type: PhantomData, + } + } +} + +impl AllowListBuilder +where + St: allow_list_state::State, + St::Allowed: allow_list_state::IsUnset, +{ + /// Set the `allowed` field (required) + pub fn allowed( + mut self, + value: impl Into>, + ) -> AllowListBuilder, S> { + self._fields.0 = Option::Some(value.into()); + AllowListBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl AllowListBuilder +where + St: allow_list_state::State, + St::Allowed: allow_list_state::IsSet, +{ + /// Build the final struct. + pub fn build(self) -> AllowList { + AllowList { + allowed: self._fields.0.unwrap(), + extra_data: Default::default(), + } + } + /// Build the final struct with custom extra_data. + pub fn build_with_data(self, extra_data: BTreeMap>) -> AllowList { + AllowList { + allowed: self._fields.0.unwrap(), + extra_data: Some(extra_data), + } + } +} + +fn lexicon_doc_com_atproto_simplespace_defs() -> 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("com.atproto.simplespace.defs"), + defs: { + let mut map = BTreeMap::new(); + map.insert( + SmolStr::new_static("allowList"), + LexUserType::Object(LexObject { + description: Some( + CowStr::new_static( + "App access policy: only the named clients may access the space, evaluated against the attested client_id.", + ), + ), + required: Some(vec![SmolStr::new_static("allowed")]), + properties: { + #[allow(unused_mut)] + let mut map = BTreeMap::new(); + map.insert( + SmolStr::new_static("allowed"), + LexObjectProperty::Array(LexArray { + description: Some( + CowStr::new_static( + "The OAuth client IDs permitted to access the space.", + ), + ), + items: LexArrayItem::String(LexString { + description: Some( + CowStr::new_static("An OAuth client ID."), + ), + ..Default::default() + }), + ..Default::default() + }), + ); + map + }, + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("managingAppPolicy"), + LexUserType::Object(LexObject { + description: Some( + CowStr::new_static( + "User access policy: the managing app is asked, via checkUserAccess, whether to authorize each user.", + ), + ), + required: Some(vec![SmolStr::new_static("managingApp")]), + properties: { + #[allow(unused_mut)] + let mut map = BTreeMap::new(); + map.insert( + SmolStr::new_static("managingApp"), + LexObjectProperty::String(LexString { + description: Some( + CowStr::new_static( + "Service identifier of the managing app: a DID with an optional service fragment (e.g. 'did:web:example.com#forum').", + ), + ), + ..Default::default() + }), + ); + map + }, + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("memberListPolicy"), + LexUserType::Object(LexObject { + description: Some(CowStr::new_static( + "User access policy: only users on the space's member list may access it.", + )), + properties: { + #[allow(unused_mut)] + let mut map = BTreeMap::new(); + map + }, + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("open"), + LexUserType::Object(LexObject { + description: Some( + CowStr::new_static( + "App access policy: any app may access the space. No client attestation required.", + ), + ), + properties: { + #[allow(unused_mut)] + let mut map = BTreeMap::new(); + map + }, + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("publicPolicy"), + LexUserType::Object(LexObject { + description: Some(CowStr::new_static( + "User access policy: any user may access the space.", + )), + properties: { + #[allow(unused_mut)] + let mut map = BTreeMap::new(); + map + }, + ..Default::default() + }), + ); + map + }, + ..Default::default() + } +} diff --git a/crates/jacquard-api/src/com_atproto/simplespace/add_member.rs b/crates/jacquard-api/src/com_atproto/simplespace/add_member.rs new file mode 100644 index 000000000..a9b3acc8f --- /dev/null +++ b/crates/jacquard-api/src/com_atproto/simplespace/add_member.rs @@ -0,0 +1,257 @@ +// @generated by jacquard-lexicon. DO NOT EDIT. +// +// Lexicon: com.atproto.simplespace.addMember +// +// 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::deps::smol_str::SmolStr; +use jacquard_common::types::aturi::AtSpaceUri; +use jacquard_common::types::string::Did; +use jacquard_common::types::value::Data; +use jacquard_common::{BosStr, CowStr, DefaultStr, FromStaticStr}; +use jacquard_derive::{IntoStatic, open_union}; +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct AddMember { + ///The DID of the member to add. + pub did: Did, + ///Reference to the space. + pub space: AtSpaceUri, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +#[derive( + Serialize, Deserialize, Debug, Clone, PartialEq, Eq, thiserror::Error, miette::Diagnostic, +)] +#[serde(tag = "error", content = "message")] +pub enum AddMemberError { + #[serde(rename = "SpaceNotFound")] + SpaceNotFound(Option), + #[serde(rename = "NotSpaceOwner")] + NotSpaceOwner(Option), + /// Catch-all for unknown error codes. + #[serde(untagged)] + Other { + error: SmolStr, + message: Option, + }, +} + +impl core::fmt::Display for AddMemberError { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + match self { + Self::SpaceNotFound(msg) => { + write!(f, "SpaceNotFound")?; + if let Some(msg) = msg { + write!(f, ": {}", msg)?; + } + Ok(()) + } + Self::NotSpaceOwner(msg) => { + write!(f, "NotSpaceOwner")?; + if let Some(msg) = msg { + write!(f, ": {}", msg)?; + } + Ok(()) + } + Self::Other { error, message } => { + write!(f, "{}", error)?; + if let Some(msg) = message { + write!(f, ": {}", msg)?; + } + Ok(()) + } + } + } +} + +/** Response marker for the `com.atproto.simplespace.addMember` procedure. + +Implements `jacquard_common::xrpc::XrpcResp`; successful bodies decode as `Self::Output`, which is `()` for this endpoint.*/ +pub struct AddMemberResponse; +impl jacquard_common::xrpc::XrpcResp for AddMemberResponse { + const NSID: &'static str = "com.atproto.simplespace.addMember"; + const ENCODING: &'static str = "application/json"; + type Output = (); + type Err = AddMemberError; +} + +impl jacquard_common::xrpc::XrpcRequest for AddMember { + const NSID: &'static str = "com.atproto.simplespace.addMember"; + const METHOD: jacquard_common::xrpc::XrpcMethod = + jacquard_common::xrpc::XrpcMethod::Procedure("application/json"); + type Response = AddMemberResponse; +} + +/** Endpoint marker for the `com.atproto.simplespace.addMember` procedure. + +Path: `/xrpc/com.atproto.simplespace.addMember`. The request payload type is `AddMember`; send that request with `jacquard::Client` or use this marker through lower-level `XrpcEndpoint` APIs.*/ +pub struct AddMemberRequest; +impl jacquard_common::xrpc::XrpcEndpoint for AddMemberRequest { + const PATH: &'static str = "/xrpc/com.atproto.simplespace.addMember"; + const METHOD: jacquard_common::xrpc::XrpcMethod = + jacquard_common::xrpc::XrpcMethod::Procedure("application/json"); + type Request = AddMember; + type Response = AddMemberResponse; +} + +pub mod add_member_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 Did; + type Space; + } + /// Empty state - all required fields are unset + pub struct Empty(()); + impl sealed::Sealed for Empty {} + impl State for Empty { + type Did = Unset; + type Space = Unset; + } + ///State transition - sets the `did` field to Set + pub struct SetDid(PhantomData St>); + impl sealed::Sealed for SetDid {} + impl State for SetDid { + type Did = Set; + type Space = St::Space; + } + ///State transition - sets the `space` field to Set + pub struct SetSpace(PhantomData St>); + impl sealed::Sealed for SetSpace {} + impl State for SetSpace { + type Did = St::Did; + type Space = Set; + } + /// Marker types for field names + #[allow(non_camel_case_types)] + pub mod members { + ///Marker type for the `did` field + pub struct did(()); + ///Marker type for the `space` field + pub struct space(()); + } +} + +/// Builder for constructing an instance of this type. +pub struct AddMemberBuilder { + _state: PhantomData St>, + _fields: (Option>, Option>), + _type: PhantomData S>, +} + +impl AddMember { + /// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed + pub fn new() -> AddMemberBuilder { + AddMemberBuilder::new() + } +} + +impl AddMember { + /// Create a new builder for this type + pub fn builder() -> AddMemberBuilder { + AddMemberBuilder::builder() + } +} + +impl AddMemberBuilder { + /// Create a new builder with all fields unset, using the default string type, if needed + pub fn new() -> Self { + AddMemberBuilder { + _state: PhantomData, + _fields: (None, None), + _type: PhantomData, + } + } +} + +impl AddMemberBuilder { + /// Create a new builder with all fields unset + pub fn builder() -> Self { + AddMemberBuilder { + _state: PhantomData, + _fields: (None, None), + _type: PhantomData, + } + } +} + +impl AddMemberBuilder +where + St: add_member_state::State, + St::Did: add_member_state::IsUnset, +{ + /// Set the `did` field (required) + pub fn did( + mut self, + value: impl Into>, + ) -> AddMemberBuilder, S> { + self._fields.0 = Option::Some(value.into()); + AddMemberBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl AddMemberBuilder +where + St: add_member_state::State, + St::Space: add_member_state::IsUnset, +{ + /// Set the `space` field (required) + pub fn space( + mut self, + value: impl Into>, + ) -> AddMemberBuilder, S> { + self._fields.1 = Option::Some(value.into()); + AddMemberBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl AddMemberBuilder +where + St: add_member_state::State, + St::Did: add_member_state::IsSet, + St::Space: add_member_state::IsSet, +{ + /// Build the final struct. + pub fn build(self) -> AddMember { + AddMember { + did: self._fields.0.unwrap(), + space: self._fields.1.unwrap(), + extra_data: Default::default(), + } + } + /// Build the final struct with custom extra_data. + pub fn build_with_data(self, extra_data: BTreeMap>) -> AddMember { + AddMember { + did: self._fields.0.unwrap(), + space: self._fields.1.unwrap(), + extra_data: Some(extra_data), + } + } +} diff --git a/crates/jacquard-api/src/com_atproto/simplespace/check_user_access.rs b/crates/jacquard-api/src/com_atproto/simplespace/check_user_access.rs new file mode 100644 index 000000000..50c73dac3 --- /dev/null +++ b/crates/jacquard-api/src/com_atproto/simplespace/check_user_access.rs @@ -0,0 +1,225 @@ +// @generated by jacquard-lexicon. DO NOT EDIT. +// +// Lexicon: com.atproto.simplespace.checkUserAccess +// +// 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::deps::smol_str::SmolStr; +use jacquard_common::types::aturi::AtSpaceUri; +use jacquard_common::types::string::Did; +use jacquard_common::types::value::Data; +use jacquard_common::{BosStr, CowStr, DefaultStr, FromStaticStr}; +use jacquard_derive::IntoStatic; +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct CheckUserAccess { + #[serde(skip_serializing_if = "Option::is_none")] + pub client_id: Option, + pub space: AtSpaceUri, + pub user: Did, +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct CheckUserAccessOutput { + ///Whether the managing app authorizes the request. + pub authorized: bool, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +/** Response marker for the `com.atproto.simplespace.checkUserAccess` query. + +Implements `jacquard_common::xrpc::XrpcResp`; successful bodies decode as `Self::Output`, which is `CheckUserAccessOutput` for this endpoint.*/ +pub struct CheckUserAccessResponse; +impl jacquard_common::xrpc::XrpcResp for CheckUserAccessResponse { + const NSID: &'static str = "com.atproto.simplespace.checkUserAccess"; + const ENCODING: &'static str = "application/json"; + type Output = CheckUserAccessOutput; + type Err = jacquard_common::xrpc::GenericError; +} + +impl jacquard_common::xrpc::XrpcRequest for CheckUserAccess { + const NSID: &'static str = "com.atproto.simplespace.checkUserAccess"; + const METHOD: jacquard_common::xrpc::XrpcMethod = jacquard_common::xrpc::XrpcMethod::Query; + type Response = CheckUserAccessResponse; +} + +/** Endpoint marker for the `com.atproto.simplespace.checkUserAccess` query. + +Path: `/xrpc/com.atproto.simplespace.checkUserAccess`. The request payload type is `CheckUserAccess`; send that request with `jacquard::Client` or use this marker through lower-level `XrpcEndpoint` APIs.*/ +pub struct CheckUserAccessRequest; +impl jacquard_common::xrpc::XrpcEndpoint for CheckUserAccessRequest { + const PATH: &'static str = "/xrpc/com.atproto.simplespace.checkUserAccess"; + const METHOD: jacquard_common::xrpc::XrpcMethod = jacquard_common::xrpc::XrpcMethod::Query; + type Request = CheckUserAccess; + type Response = CheckUserAccessResponse; +} + +pub mod check_user_access_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 Space; + type User; + } + /// Empty state - all required fields are unset + pub struct Empty(()); + impl sealed::Sealed for Empty {} + impl State for Empty { + type Space = Unset; + type User = Unset; + } + ///State transition - sets the `space` field to Set + pub struct SetSpace(PhantomData St>); + impl sealed::Sealed for SetSpace {} + impl State for SetSpace { + type Space = Set; + type User = St::User; + } + ///State transition - sets the `user` field to Set + pub struct SetUser(PhantomData St>); + impl sealed::Sealed for SetUser {} + impl State for SetUser { + type Space = St::Space; + type User = Set; + } + /// Marker types for field names + #[allow(non_camel_case_types)] + pub mod members { + ///Marker type for the `space` field + pub struct space(()); + ///Marker type for the `user` field + pub struct user(()); + } +} + +/// Builder for constructing an instance of this type. +pub struct CheckUserAccessBuilder { + _state: PhantomData St>, + _fields: (Option, Option>, Option>), + _type: PhantomData S>, +} + +impl CheckUserAccess { + /// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed + pub fn new() -> CheckUserAccessBuilder { + CheckUserAccessBuilder::new() + } +} + +impl CheckUserAccess { + /// Create a new builder for this type + pub fn builder() -> CheckUserAccessBuilder { + CheckUserAccessBuilder::builder() + } +} + +impl CheckUserAccessBuilder { + /// Create a new builder with all fields unset, using the default string type, if needed + pub fn new() -> Self { + CheckUserAccessBuilder { + _state: PhantomData, + _fields: (None, None, None), + _type: PhantomData, + } + } +} + +impl CheckUserAccessBuilder { + /// Create a new builder with all fields unset + pub fn builder() -> Self { + CheckUserAccessBuilder { + _state: PhantomData, + _fields: (None, None, None), + _type: PhantomData, + } + } +} + +impl CheckUserAccessBuilder { + /// Set the `clientId` field (optional) + pub fn client_id(mut self, value: impl Into>) -> Self { + self._fields.0 = value.into(); + self + } + /// Set the `clientId` field to an Option value (optional) + pub fn maybe_client_id(mut self, value: Option) -> Self { + self._fields.0 = value; + self + } +} + +impl CheckUserAccessBuilder +where + St: check_user_access_state::State, + St::Space: check_user_access_state::IsUnset, +{ + /// Set the `space` field (required) + pub fn space( + mut self, + value: impl Into>, + ) -> CheckUserAccessBuilder, S> { + self._fields.1 = Option::Some(value.into()); + CheckUserAccessBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl CheckUserAccessBuilder +where + St: check_user_access_state::State, + St::User: check_user_access_state::IsUnset, +{ + /// Set the `user` field (required) + pub fn user( + mut self, + value: impl Into>, + ) -> CheckUserAccessBuilder, S> { + self._fields.2 = Option::Some(value.into()); + CheckUserAccessBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl CheckUserAccessBuilder +where + St: check_user_access_state::State, + St::Space: check_user_access_state::IsSet, + St::User: check_user_access_state::IsSet, +{ + /// Build the final struct. + pub fn build(self) -> CheckUserAccess { + CheckUserAccess { + client_id: self._fields.0, + space: self._fields.1.unwrap(), + user: self._fields.2.unwrap(), + } + } +} diff --git a/crates/jacquard-api/src/com_atproto/simplespace/create_space.rs b/crates/jacquard-api/src/com_atproto/simplespace/create_space.rs new file mode 100644 index 000000000..923eb5b24 --- /dev/null +++ b/crates/jacquard-api/src/com_atproto/simplespace/create_space.rs @@ -0,0 +1,369 @@ +// @generated by jacquard-lexicon. DO NOT EDIT. +// +// Lexicon: com.atproto.simplespace.createSpace +// +// 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; + +use crate::com_atproto::simplespace::AllowList; +use crate::com_atproto::simplespace::ManagingAppPolicy; +use crate::com_atproto::simplespace::MemberListPolicy; +use crate::com_atproto::simplespace::Open; +use crate::com_atproto::simplespace::PublicPolicy; +#[allow(unused_imports)] +use core::marker::PhantomData; +use jacquard_common::deps::smol_str::SmolStr; +use jacquard_common::types::aturi::AtSpaceUri; +use jacquard_common::types::string::{Nsid, RecordKey, Rkey}; +use jacquard_common::types::value::Data; +use jacquard_common::{BosStr, CowStr, DefaultStr, FromStaticStr}; +use jacquard_derive::{IntoStatic, open_union}; +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct CreateSpace { + ///How the authority decides whether to authorize a requesting app. + pub app_access: CreateSpaceAppAccess, + ///How the authority decides whether to authorize a requesting user. + pub policy: CreateSpacePolicy, + ///The space key. Used to differentiate multiple spaces of the same type under the same owner. Same syntax requirements as a record key. If not provided, one will be auto-generated (TID). + #[serde(skip_serializing_if = "Option::is_none")] + pub skey: Option>>, + ///The NSID of the space type, describing the modality of the space (e.g. app.bsky.group, app.bsky.personal). + pub r#type: Nsid, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +#[open_union] +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde(tag = "$type", bound(deserialize = "S: Deserialize<'de> + BosStr"))] +pub enum CreateSpaceAppAccess { + #[serde(rename = "com.atproto.simplespace.defs#open")] + Open(Box>), + #[serde(rename = "com.atproto.simplespace.defs#allowList")] + AllowList(Box>), +} + +#[open_union] +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde(tag = "$type", bound(deserialize = "S: Deserialize<'de> + BosStr"))] +pub enum CreateSpacePolicy { + #[serde(rename = "com.atproto.simplespace.defs#publicPolicy")] + PublicPolicy(Box>), + #[serde(rename = "com.atproto.simplespace.defs#memberListPolicy")] + MemberListPolicy(Box>), + #[serde(rename = "com.atproto.simplespace.defs#managingAppPolicy")] + ManagingAppPolicy(Box>), +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct CreateSpaceOutput { + ///URI of the created space. + pub uri: AtSpaceUri, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +#[derive( + Serialize, Deserialize, Debug, Clone, PartialEq, Eq, thiserror::Error, miette::Diagnostic, +)] +#[serde(tag = "error", content = "message")] +pub enum CreateSpaceError { + /// A space with this owner, type, and skey already exists. A space that was previously deleted may be created again. + #[serde(rename = "SpaceAlreadyExists")] + SpaceAlreadyExists(Option), + /// The requested policy is not one the host implements. + #[serde(rename = "UnsupportedPolicy")] + UnsupportedPolicy(Option), + /// The requested appAccess variant is not one the host implements. A host will not store an app access policy it cannot enforce. + #[serde(rename = "UnsupportedAppAccess")] + UnsupportedAppAccess(Option), + /// Catch-all for unknown error codes. + #[serde(untagged)] + Other { + error: SmolStr, + message: Option, + }, +} + +impl core::fmt::Display for CreateSpaceError { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + match self { + Self::SpaceAlreadyExists(msg) => { + write!(f, "SpaceAlreadyExists")?; + if let Some(msg) = msg { + write!(f, ": {}", msg)?; + } + Ok(()) + } + Self::UnsupportedPolicy(msg) => { + write!(f, "UnsupportedPolicy")?; + if let Some(msg) = msg { + write!(f, ": {}", msg)?; + } + Ok(()) + } + Self::UnsupportedAppAccess(msg) => { + write!(f, "UnsupportedAppAccess")?; + if let Some(msg) = msg { + write!(f, ": {}", msg)?; + } + Ok(()) + } + Self::Other { error, message } => { + write!(f, "{}", error)?; + if let Some(msg) = message { + write!(f, ": {}", msg)?; + } + Ok(()) + } + } + } +} + +/** Response marker for the `com.atproto.simplespace.createSpace` procedure. + +Implements `jacquard_common::xrpc::XrpcResp`; successful bodies decode as `Self::Output`, which is `CreateSpaceOutput` for this endpoint.*/ +pub struct CreateSpaceResponse; +impl jacquard_common::xrpc::XrpcResp for CreateSpaceResponse { + const NSID: &'static str = "com.atproto.simplespace.createSpace"; + const ENCODING: &'static str = "application/json"; + type Output = CreateSpaceOutput; + type Err = CreateSpaceError; +} + +impl jacquard_common::xrpc::XrpcRequest for CreateSpace { + const NSID: &'static str = "com.atproto.simplespace.createSpace"; + const METHOD: jacquard_common::xrpc::XrpcMethod = + jacquard_common::xrpc::XrpcMethod::Procedure("application/json"); + type Response = CreateSpaceResponse; +} + +/** Endpoint marker for the `com.atproto.simplespace.createSpace` procedure. + +Path: `/xrpc/com.atproto.simplespace.createSpace`. The request payload type is `CreateSpace`; send that request with `jacquard::Client` or use this marker through lower-level `XrpcEndpoint` APIs.*/ +pub struct CreateSpaceRequest; +impl jacquard_common::xrpc::XrpcEndpoint for CreateSpaceRequest { + const PATH: &'static str = "/xrpc/com.atproto.simplespace.createSpace"; + const METHOD: jacquard_common::xrpc::XrpcMethod = + jacquard_common::xrpc::XrpcMethod::Procedure("application/json"); + type Request = CreateSpace; + type Response = CreateSpaceResponse; +} + +pub mod create_space_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 AppAccess; + type Policy; + type Type; + } + /// Empty state - all required fields are unset + pub struct Empty(()); + impl sealed::Sealed for Empty {} + impl State for Empty { + type AppAccess = Unset; + type Policy = Unset; + type Type = Unset; + } + ///State transition - sets the `app_access` field to Set + pub struct SetAppAccess(PhantomData St>); + impl sealed::Sealed for SetAppAccess {} + impl State for SetAppAccess { + type AppAccess = Set; + type Policy = St::Policy; + type Type = St::Type; + } + ///State transition - sets the `policy` field to Set + pub struct SetPolicy(PhantomData St>); + impl sealed::Sealed for SetPolicy {} + impl State for SetPolicy { + type AppAccess = St::AppAccess; + type Policy = Set; + type Type = St::Type; + } + ///State transition - sets the `type` field to Set + pub struct SetType(PhantomData St>); + impl sealed::Sealed for SetType {} + impl State for SetType { + type AppAccess = St::AppAccess; + type Policy = St::Policy; + type Type = Set; + } + /// Marker types for field names + #[allow(non_camel_case_types)] + pub mod members { + ///Marker type for the `app_access` field + pub struct app_access(()); + ///Marker type for the `policy` field + pub struct policy(()); + ///Marker type for the `type` field + pub struct r#type(()); + } +} + +/// Builder for constructing an instance of this type. +pub struct CreateSpaceBuilder { + _state: PhantomData St>, + _fields: ( + Option>, + Option>, + Option>>, + Option>, + ), + _type: PhantomData S>, +} + +impl CreateSpace { + /// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed + pub fn new() -> CreateSpaceBuilder { + CreateSpaceBuilder::new() + } +} + +impl CreateSpace { + /// Create a new builder for this type + pub fn builder() -> CreateSpaceBuilder { + CreateSpaceBuilder::builder() + } +} + +impl CreateSpaceBuilder { + /// Create a new builder with all fields unset, using the default string type, if needed + pub fn new() -> Self { + CreateSpaceBuilder { + _state: PhantomData, + _fields: (None, None, None, None), + _type: PhantomData, + } + } +} + +impl CreateSpaceBuilder { + /// Create a new builder with all fields unset + pub fn builder() -> Self { + CreateSpaceBuilder { + _state: PhantomData, + _fields: (None, None, None, None), + _type: PhantomData, + } + } +} + +impl CreateSpaceBuilder +where + St: create_space_state::State, + St::AppAccess: create_space_state::IsUnset, +{ + /// Set the `appAccess` field (required) + pub fn app_access( + mut self, + value: impl Into>, + ) -> CreateSpaceBuilder, S> { + self._fields.0 = Option::Some(value.into()); + CreateSpaceBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl CreateSpaceBuilder +where + St: create_space_state::State, + St::Policy: create_space_state::IsUnset, +{ + /// Set the `policy` field (required) + pub fn policy( + mut self, + value: impl Into>, + ) -> CreateSpaceBuilder, S> { + self._fields.1 = Option::Some(value.into()); + CreateSpaceBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl CreateSpaceBuilder { + /// Set the `skey` field (optional) + pub fn skey(mut self, value: impl Into>>>) -> Self { + self._fields.2 = value.into(); + self + } + /// Set the `skey` field to an Option value (optional) + pub fn maybe_skey(mut self, value: Option>>) -> Self { + self._fields.2 = value; + self + } +} + +impl CreateSpaceBuilder +where + St: create_space_state::State, + St::Type: create_space_state::IsUnset, +{ + /// Set the `type` field (required) + pub fn r#type( + mut self, + value: impl Into>, + ) -> CreateSpaceBuilder, S> { + self._fields.3 = Option::Some(value.into()); + CreateSpaceBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl CreateSpaceBuilder +where + St: create_space_state::State, + St::AppAccess: create_space_state::IsSet, + St::Policy: create_space_state::IsSet, + St::Type: create_space_state::IsSet, +{ + /// Build the final struct. + pub fn build(self) -> CreateSpace { + CreateSpace { + app_access: self._fields.0.unwrap(), + policy: self._fields.1.unwrap(), + skey: self._fields.2, + r#type: self._fields.3.unwrap(), + extra_data: Default::default(), + } + } + /// Build the final struct with custom extra_data. + pub fn build_with_data(self, extra_data: BTreeMap>) -> CreateSpace { + CreateSpace { + app_access: self._fields.0.unwrap(), + policy: self._fields.1.unwrap(), + skey: self._fields.2, + r#type: self._fields.3.unwrap(), + extra_data: Some(extra_data), + } + } +} diff --git a/crates/jacquard-api/src/com_atproto/simplespace/delete_space.rs b/crates/jacquard-api/src/com_atproto/simplespace/delete_space.rs new file mode 100644 index 000000000..18f68131b --- /dev/null +++ b/crates/jacquard-api/src/com_atproto/simplespace/delete_space.rs @@ -0,0 +1,220 @@ +// @generated by jacquard-lexicon. DO NOT EDIT. +// +// Lexicon: com.atproto.simplespace.deleteSpace +// +// 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::deps::smol_str::SmolStr; +use jacquard_common::types::aturi::AtSpaceUri; +use jacquard_common::types::value::Data; +use jacquard_common::{BosStr, CowStr, DefaultStr, FromStaticStr}; +use jacquard_derive::{IntoStatic, open_union}; +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct DeleteSpace { + ///Reference to the space to delete. + pub space: AtSpaceUri, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +#[derive( + Serialize, Deserialize, Debug, Clone, PartialEq, Eq, thiserror::Error, miette::Diagnostic, +)] +#[serde(tag = "error", content = "message")] +pub enum DeleteSpaceError { + #[serde(rename = "SpaceNotFound")] + SpaceNotFound(Option), + #[serde(rename = "NotSpaceOwner")] + NotSpaceOwner(Option), + /// Catch-all for unknown error codes. + #[serde(untagged)] + Other { + error: SmolStr, + message: Option, + }, +} + +impl core::fmt::Display for DeleteSpaceError { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + match self { + Self::SpaceNotFound(msg) => { + write!(f, "SpaceNotFound")?; + if let Some(msg) = msg { + write!(f, ": {}", msg)?; + } + Ok(()) + } + Self::NotSpaceOwner(msg) => { + write!(f, "NotSpaceOwner")?; + if let Some(msg) = msg { + write!(f, ": {}", msg)?; + } + Ok(()) + } + Self::Other { error, message } => { + write!(f, "{}", error)?; + if let Some(msg) = message { + write!(f, ": {}", msg)?; + } + Ok(()) + } + } + } +} + +/** Response marker for the `com.atproto.simplespace.deleteSpace` procedure. + +Implements `jacquard_common::xrpc::XrpcResp`; successful bodies decode as `Self::Output`, which is `()` for this endpoint.*/ +pub struct DeleteSpaceResponse; +impl jacquard_common::xrpc::XrpcResp for DeleteSpaceResponse { + const NSID: &'static str = "com.atproto.simplespace.deleteSpace"; + const ENCODING: &'static str = "application/json"; + type Output = (); + type Err = DeleteSpaceError; +} + +impl jacquard_common::xrpc::XrpcRequest for DeleteSpace { + const NSID: &'static str = "com.atproto.simplespace.deleteSpace"; + const METHOD: jacquard_common::xrpc::XrpcMethod = + jacquard_common::xrpc::XrpcMethod::Procedure("application/json"); + type Response = DeleteSpaceResponse; +} + +/** Endpoint marker for the `com.atproto.simplespace.deleteSpace` procedure. + +Path: `/xrpc/com.atproto.simplespace.deleteSpace`. The request payload type is `DeleteSpace`; send that request with `jacquard::Client` or use this marker through lower-level `XrpcEndpoint` APIs.*/ +pub struct DeleteSpaceRequest; +impl jacquard_common::xrpc::XrpcEndpoint for DeleteSpaceRequest { + const PATH: &'static str = "/xrpc/com.atproto.simplespace.deleteSpace"; + const METHOD: jacquard_common::xrpc::XrpcMethod = + jacquard_common::xrpc::XrpcMethod::Procedure("application/json"); + type Request = DeleteSpace; + type Response = DeleteSpaceResponse; +} + +pub mod delete_space_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 Space; + } + /// Empty state - all required fields are unset + pub struct Empty(()); + impl sealed::Sealed for Empty {} + impl State for Empty { + type Space = Unset; + } + ///State transition - sets the `space` field to Set + pub struct SetSpace(PhantomData St>); + impl sealed::Sealed for SetSpace {} + impl State for SetSpace { + type Space = Set; + } + /// Marker types for field names + #[allow(non_camel_case_types)] + pub mod members { + ///Marker type for the `space` field + pub struct space(()); + } +} + +/// Builder for constructing an instance of this type. +pub struct DeleteSpaceBuilder { + _state: PhantomData St>, + _fields: (Option>,), + _type: PhantomData S>, +} + +impl DeleteSpace { + /// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed + pub fn new() -> DeleteSpaceBuilder { + DeleteSpaceBuilder::new() + } +} + +impl DeleteSpace { + /// Create a new builder for this type + pub fn builder() -> DeleteSpaceBuilder { + DeleteSpaceBuilder::builder() + } +} + +impl DeleteSpaceBuilder { + /// Create a new builder with all fields unset, using the default string type, if needed + pub fn new() -> Self { + DeleteSpaceBuilder { + _state: PhantomData, + _fields: (None,), + _type: PhantomData, + } + } +} + +impl DeleteSpaceBuilder { + /// Create a new builder with all fields unset + pub fn builder() -> Self { + DeleteSpaceBuilder { + _state: PhantomData, + _fields: (None,), + _type: PhantomData, + } + } +} + +impl DeleteSpaceBuilder +where + St: delete_space_state::State, + St::Space: delete_space_state::IsUnset, +{ + /// Set the `space` field (required) + pub fn space( + mut self, + value: impl Into>, + ) -> DeleteSpaceBuilder, S> { + self._fields.0 = Option::Some(value.into()); + DeleteSpaceBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl DeleteSpaceBuilder +where + St: delete_space_state::State, + St::Space: delete_space_state::IsSet, +{ + /// Build the final struct. + pub fn build(self) -> DeleteSpace { + DeleteSpace { + space: self._fields.0.unwrap(), + extra_data: Default::default(), + } + } + /// Build the final struct with custom extra_data. + pub fn build_with_data(self, extra_data: BTreeMap>) -> DeleteSpace { + DeleteSpace { + space: self._fields.0.unwrap(), + extra_data: Some(extra_data), + } + } +} diff --git a/crates/jacquard-api/src/com_atproto/simplespace/get_space.rs b/crates/jacquard-api/src/com_atproto/simplespace/get_space.rs new file mode 100644 index 000000000..e430a48d2 --- /dev/null +++ b/crates/jacquard-api/src/com_atproto/simplespace/get_space.rs @@ -0,0 +1,241 @@ +// @generated by jacquard-lexicon. DO NOT EDIT. +// +// Lexicon: com.atproto.simplespace.getSpace +// +// 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; + +use crate::com_atproto::simplespace::AllowList; +use crate::com_atproto::simplespace::ManagingAppPolicy; +use crate::com_atproto::simplespace::MemberListPolicy; +use crate::com_atproto::simplespace::Open; +use crate::com_atproto::simplespace::PublicPolicy; +#[allow(unused_imports)] +use core::marker::PhantomData; +use jacquard_common::deps::smol_str::SmolStr; +use jacquard_common::types::aturi::AtSpaceUri; +use jacquard_common::types::value::Data; +use jacquard_common::{BosStr, CowStr, DefaultStr, FromStaticStr}; +use jacquard_derive::{IntoStatic, open_union}; +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct GetSpace { + pub space: AtSpaceUri, +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct GetSpaceOutput { + ///How the authority decides whether to authorize a requesting app. + pub app_access: GetSpaceOutputAppAccess, + ///How the authority decides whether to authorize a requesting user. + pub policy: GetSpaceOutputPolicy, + ///URI of the space. + pub uri: AtSpaceUri, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +#[open_union] +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde(tag = "$type", bound(deserialize = "S: Deserialize<'de> + BosStr"))] +pub enum GetSpaceOutputAppAccess { + #[serde(rename = "com.atproto.simplespace.defs#open")] + Open(Box>), + #[serde(rename = "com.atproto.simplespace.defs#allowList")] + AllowList(Box>), +} + +#[open_union] +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde(tag = "$type", bound(deserialize = "S: Deserialize<'de> + BosStr"))] +pub enum GetSpaceOutputPolicy { + #[serde(rename = "com.atproto.simplespace.defs#publicPolicy")] + PublicPolicy(Box>), + #[serde(rename = "com.atproto.simplespace.defs#memberListPolicy")] + MemberListPolicy(Box>), + #[serde(rename = "com.atproto.simplespace.defs#managingAppPolicy")] + ManagingAppPolicy(Box>), +} + +#[derive( + Serialize, Deserialize, Debug, Clone, PartialEq, Eq, thiserror::Error, miette::Diagnostic, +)] +#[serde(tag = "error", content = "message")] +pub enum GetSpaceError { + #[serde(rename = "SpaceNotFound")] + SpaceNotFound(Option), + /// Catch-all for unknown error codes. + #[serde(untagged)] + Other { + error: SmolStr, + message: Option, + }, +} + +impl core::fmt::Display for GetSpaceError { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + match self { + Self::SpaceNotFound(msg) => { + write!(f, "SpaceNotFound")?; + if let Some(msg) = msg { + write!(f, ": {}", msg)?; + } + Ok(()) + } + Self::Other { error, message } => { + write!(f, "{}", error)?; + if let Some(msg) = message { + write!(f, ": {}", msg)?; + } + Ok(()) + } + } + } +} + +/** Response marker for the `com.atproto.simplespace.getSpace` query. + +Implements `jacquard_common::xrpc::XrpcResp`; successful bodies decode as `Self::Output`, which is `GetSpaceOutput` for this endpoint.*/ +pub struct GetSpaceResponse; +impl jacquard_common::xrpc::XrpcResp for GetSpaceResponse { + const NSID: &'static str = "com.atproto.simplespace.getSpace"; + const ENCODING: &'static str = "application/json"; + type Output = GetSpaceOutput; + type Err = GetSpaceError; +} + +impl jacquard_common::xrpc::XrpcRequest for GetSpace { + const NSID: &'static str = "com.atproto.simplespace.getSpace"; + const METHOD: jacquard_common::xrpc::XrpcMethod = jacquard_common::xrpc::XrpcMethod::Query; + type Response = GetSpaceResponse; +} + +/** Endpoint marker for the `com.atproto.simplespace.getSpace` query. + +Path: `/xrpc/com.atproto.simplespace.getSpace`. The request payload type is `GetSpace`; send that request with `jacquard::Client` or use this marker through lower-level `XrpcEndpoint` APIs.*/ +pub struct GetSpaceRequest; +impl jacquard_common::xrpc::XrpcEndpoint for GetSpaceRequest { + const PATH: &'static str = "/xrpc/com.atproto.simplespace.getSpace"; + const METHOD: jacquard_common::xrpc::XrpcMethod = jacquard_common::xrpc::XrpcMethod::Query; + type Request = GetSpace; + type Response = GetSpaceResponse; +} + +pub mod get_space_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 Space; + } + /// Empty state - all required fields are unset + pub struct Empty(()); + impl sealed::Sealed for Empty {} + impl State for Empty { + type Space = Unset; + } + ///State transition - sets the `space` field to Set + pub struct SetSpace(PhantomData St>); + impl sealed::Sealed for SetSpace {} + impl State for SetSpace { + type Space = Set; + } + /// Marker types for field names + #[allow(non_camel_case_types)] + pub mod members { + ///Marker type for the `space` field + pub struct space(()); + } +} + +/// Builder for constructing an instance of this type. +pub struct GetSpaceBuilder { + _state: PhantomData St>, + _fields: (Option>,), + _type: PhantomData S>, +} + +impl GetSpace { + /// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed + pub fn new() -> GetSpaceBuilder { + GetSpaceBuilder::new() + } +} + +impl GetSpace { + /// Create a new builder for this type + pub fn builder() -> GetSpaceBuilder { + GetSpaceBuilder::builder() + } +} + +impl GetSpaceBuilder { + /// Create a new builder with all fields unset, using the default string type, if needed + pub fn new() -> Self { + GetSpaceBuilder { + _state: PhantomData, + _fields: (None,), + _type: PhantomData, + } + } +} + +impl GetSpaceBuilder { + /// Create a new builder with all fields unset + pub fn builder() -> Self { + GetSpaceBuilder { + _state: PhantomData, + _fields: (None,), + _type: PhantomData, + } + } +} + +impl GetSpaceBuilder +where + St: get_space_state::State, + St::Space: get_space_state::IsUnset, +{ + /// Set the `space` field (required) + pub fn space( + mut self, + value: impl Into>, + ) -> GetSpaceBuilder, S> { + self._fields.0 = Option::Some(value.into()); + GetSpaceBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl GetSpaceBuilder +where + St: get_space_state::State, + St::Space: get_space_state::IsSet, +{ + /// Build the final struct. + pub fn build(self) -> GetSpace { + GetSpace { + space: self._fields.0.unwrap(), + } + } +} diff --git a/crates/jacquard-api/src/com_atproto/simplespace/list_members.rs b/crates/jacquard-api/src/com_atproto/simplespace/list_members.rs new file mode 100644 index 000000000..638b97ae2 --- /dev/null +++ b/crates/jacquard-api/src/com_atproto/simplespace/list_members.rs @@ -0,0 +1,469 @@ +// @generated by jacquard-lexicon. DO NOT EDIT. +// +// Lexicon: com.atproto.simplespace.listMembers +// +// 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::aturi::AtSpaceUri; +use jacquard_common::types::string::Did; +use jacquard_common::types::value::Data; +use jacquard_derive::{IntoStatic, open_union}; +use jacquard_lexicon::lexicon::LexiconDoc; +use jacquard_lexicon::schema::LexiconSchema; + +use crate::com_atproto::simplespace::list_members; +#[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", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct ListMembers { + #[serde(skip_serializing_if = "Option::is_none")] + pub cursor: Option, + /// Defaults to `100`. Min: 1. Max: 1000. + #[serde(default = "_default_limit")] + #[serde(skip_serializing_if = "Option::is_none")] + pub limit: Option, + pub space: AtSpaceUri, +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct ListMembersOutput { + #[serde(skip_serializing_if = "Option::is_none")] + pub cursor: Option, + pub members: Vec>, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +#[derive( + Serialize, Deserialize, Debug, Clone, PartialEq, Eq, thiserror::Error, miette::Diagnostic, +)] +#[serde(tag = "error", content = "message")] +pub enum ListMembersError { + #[serde(rename = "SpaceNotFound")] + SpaceNotFound(Option), + /// Catch-all for unknown error codes. + #[serde(untagged)] + Other { + error: SmolStr, + message: Option, + }, +} + +impl core::fmt::Display for ListMembersError { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + match self { + Self::SpaceNotFound(msg) => { + write!(f, "SpaceNotFound")?; + if let Some(msg) = msg { + write!(f, ": {}", msg)?; + } + Ok(()) + } + Self::Other { error, message } => { + write!(f, "{}", error)?; + if let Some(msg) = message { + write!(f, ": {}", msg)?; + } + Ok(()) + } + } + } +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct Member { + pub did: Did, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +/** Response marker for the `com.atproto.simplespace.listMembers` query. + +Implements `jacquard_common::xrpc::XrpcResp`; successful bodies decode as `Self::Output`, which is `ListMembersOutput` for this endpoint.*/ +pub struct ListMembersResponse; +impl jacquard_common::xrpc::XrpcResp for ListMembersResponse { + const NSID: &'static str = "com.atproto.simplespace.listMembers"; + const ENCODING: &'static str = "application/json"; + type Output = ListMembersOutput; + type Err = ListMembersError; +} + +impl jacquard_common::xrpc::XrpcRequest for ListMembers { + const NSID: &'static str = "com.atproto.simplespace.listMembers"; + const METHOD: jacquard_common::xrpc::XrpcMethod = jacquard_common::xrpc::XrpcMethod::Query; + type Response = ListMembersResponse; +} + +/** Endpoint marker for the `com.atproto.simplespace.listMembers` query. + +Path: `/xrpc/com.atproto.simplespace.listMembers`. The request payload type is `ListMembers`; send that request with `jacquard::Client` or use this marker through lower-level `XrpcEndpoint` APIs.*/ +pub struct ListMembersRequest; +impl jacquard_common::xrpc::XrpcEndpoint for ListMembersRequest { + const PATH: &'static str = "/xrpc/com.atproto.simplespace.listMembers"; + const METHOD: jacquard_common::xrpc::XrpcMethod = jacquard_common::xrpc::XrpcMethod::Query; + type Request = ListMembers; + type Response = ListMembersResponse; +} + +impl LexiconSchema for Member { + fn nsid() -> &'static str { + "com.atproto.simplespace.listMembers" + } + fn def_name() -> &'static str { + "member" + } + fn lexicon_doc() -> LexiconDoc<'static> { + lexicon_doc_com_atproto_simplespace_listMembers() + } + fn validate(&self) -> Result<(), ConstraintError> { + Ok(()) + } +} + +fn _default_limit() -> Option { + Some(100i64) +} + +pub mod list_members_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 Space; + } + /// Empty state - all required fields are unset + pub struct Empty(()); + impl sealed::Sealed for Empty {} + impl State for Empty { + type Space = Unset; + } + ///State transition - sets the `space` field to Set + pub struct SetSpace(PhantomData St>); + impl sealed::Sealed for SetSpace {} + impl State for SetSpace { + type Space = Set; + } + /// Marker types for field names + #[allow(non_camel_case_types)] + pub mod members { + ///Marker type for the `space` field + pub struct space(()); + } +} + +/// Builder for constructing an instance of this type. +pub struct ListMembersBuilder { + _state: PhantomData St>, + _fields: (Option, Option, Option>), + _type: PhantomData S>, +} + +impl ListMembers { + /// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed + pub fn new() -> ListMembersBuilder { + ListMembersBuilder::new() + } +} + +impl ListMembers { + /// Create a new builder for this type + pub fn builder() -> ListMembersBuilder { + ListMembersBuilder::builder() + } +} + +impl ListMembersBuilder { + /// Create a new builder with all fields unset, using the default string type, if needed + pub fn new() -> Self { + ListMembersBuilder { + _state: PhantomData, + _fields: (None, None, None), + _type: PhantomData, + } + } +} + +impl ListMembersBuilder { + /// Create a new builder with all fields unset + pub fn builder() -> Self { + ListMembersBuilder { + _state: PhantomData, + _fields: (None, None, None), + _type: PhantomData, + } + } +} + +impl ListMembersBuilder { + /// Set the `cursor` field (optional) + pub fn cursor(mut self, value: impl Into>) -> Self { + self._fields.0 = value.into(); + self + } + /// Set the `cursor` field to an Option value (optional) + pub fn maybe_cursor(mut self, value: Option) -> Self { + self._fields.0 = value; + self + } +} + +impl ListMembersBuilder { + /// Set the `limit` field (optional) + pub fn limit(mut self, value: impl Into>) -> Self { + self._fields.1 = value.into(); + self + } + /// Set the `limit` field to an Option value (optional) + pub fn maybe_limit(mut self, value: Option) -> Self { + self._fields.1 = value; + self + } +} + +impl ListMembersBuilder +where + St: list_members_state::State, + St::Space: list_members_state::IsUnset, +{ + /// Set the `space` field (required) + pub fn space( + mut self, + value: impl Into>, + ) -> ListMembersBuilder, S> { + self._fields.2 = Option::Some(value.into()); + ListMembersBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl ListMembersBuilder +where + St: list_members_state::State, + St::Space: list_members_state::IsSet, +{ + /// Build the final struct. + pub fn build(self) -> ListMembers { + ListMembers { + cursor: self._fields.0, + limit: self._fields.1, + space: self._fields.2.unwrap(), + } + } +} + +pub mod member_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 Did; + } + /// Empty state - all required fields are unset + pub struct Empty(()); + impl sealed::Sealed for Empty {} + impl State for Empty { + type Did = Unset; + } + ///State transition - sets the `did` field to Set + pub struct SetDid(PhantomData St>); + impl sealed::Sealed for SetDid {} + impl State for SetDid { + type Did = Set; + } + /// Marker types for field names + #[allow(non_camel_case_types)] + pub mod members { + ///Marker type for the `did` field + pub struct did(()); + } +} + +/// Builder for constructing an instance of this type. +pub struct MemberBuilder { + _state: PhantomData St>, + _fields: (Option>,), + _type: PhantomData S>, +} + +impl Member { + /// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed + pub fn new() -> MemberBuilder { + MemberBuilder::new() + } +} + +impl Member { + /// Create a new builder for this type + pub fn builder() -> MemberBuilder { + MemberBuilder::builder() + } +} + +impl MemberBuilder { + /// Create a new builder with all fields unset, using the default string type, if needed + pub fn new() -> Self { + MemberBuilder { + _state: PhantomData, + _fields: (None,), + _type: PhantomData, + } + } +} + +impl MemberBuilder { + /// Create a new builder with all fields unset + pub fn builder() -> Self { + MemberBuilder { + _state: PhantomData, + _fields: (None,), + _type: PhantomData, + } + } +} + +impl MemberBuilder +where + St: member_state::State, + St::Did: member_state::IsUnset, +{ + /// Set the `did` field (required) + pub fn did(mut self, value: impl Into>) -> MemberBuilder, S> { + self._fields.0 = Option::Some(value.into()); + MemberBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl MemberBuilder +where + St: member_state::State, + St::Did: member_state::IsSet, +{ + /// Build the final struct. + pub fn build(self) -> Member { + Member { + did: self._fields.0.unwrap(), + extra_data: Default::default(), + } + } + /// Build the final struct with custom extra_data. + pub fn build_with_data(self, extra_data: BTreeMap>) -> Member { + Member { + did: self._fields.0.unwrap(), + extra_data: Some(extra_data), + } + } +} + +fn lexicon_doc_com_atproto_simplespace_listMembers() -> 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("com.atproto.simplespace.listMembers"), + defs: { + let mut map = BTreeMap::new(); + map.insert( + SmolStr::new_static("main"), + LexUserType::XrpcQuery(LexXrpcQuery { + parameters: Some(LexXrpcQueryParameter::Params(LexXrpcParameters { + required: Some(vec![SmolStr::new_static("space")]), + properties: { + #[allow(unused_mut)] + let mut map = BTreeMap::new(); + map.insert( + SmolStr::new_static("cursor"), + LexXrpcParametersProperty::String(LexString { + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("limit"), + LexXrpcParametersProperty::Integer(LexInteger { + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("space"), + LexXrpcParametersProperty::String(LexString { + description: Some(CowStr::new_static( + "Reference to the space.", + )), + format: Some(LexStringFormat::SpaceRef), + ..Default::default() + }), + ); + map + }, + ..Default::default() + })), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("member"), + LexUserType::Object(LexObject { + required: Some(vec![SmolStr::new_static("did")]), + properties: { + #[allow(unused_mut)] + let mut map = BTreeMap::new(); + map.insert( + SmolStr::new_static("did"), + LexObjectProperty::String(LexString { + format: Some(LexStringFormat::Did), + ..Default::default() + }), + ); + map + }, + ..Default::default() + }), + ); + map + }, + ..Default::default() + } +} diff --git a/crates/jacquard-api/src/com_atproto/simplespace/remove_member.rs b/crates/jacquard-api/src/com_atproto/simplespace/remove_member.rs new file mode 100644 index 000000000..75050e766 --- /dev/null +++ b/crates/jacquard-api/src/com_atproto/simplespace/remove_member.rs @@ -0,0 +1,257 @@ +// @generated by jacquard-lexicon. DO NOT EDIT. +// +// Lexicon: com.atproto.simplespace.removeMember +// +// 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::deps::smol_str::SmolStr; +use jacquard_common::types::aturi::AtSpaceUri; +use jacquard_common::types::string::Did; +use jacquard_common::types::value::Data; +use jacquard_common::{BosStr, CowStr, DefaultStr, FromStaticStr}; +use jacquard_derive::{IntoStatic, open_union}; +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct RemoveMember { + ///The DID of the member to remove. + pub did: Did, + ///Reference to the space. + pub space: AtSpaceUri, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +#[derive( + Serialize, Deserialize, Debug, Clone, PartialEq, Eq, thiserror::Error, miette::Diagnostic, +)] +#[serde(tag = "error", content = "message")] +pub enum RemoveMemberError { + #[serde(rename = "SpaceNotFound")] + SpaceNotFound(Option), + #[serde(rename = "NotSpaceOwner")] + NotSpaceOwner(Option), + /// Catch-all for unknown error codes. + #[serde(untagged)] + Other { + error: SmolStr, + message: Option, + }, +} + +impl core::fmt::Display for RemoveMemberError { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + match self { + Self::SpaceNotFound(msg) => { + write!(f, "SpaceNotFound")?; + if let Some(msg) = msg { + write!(f, ": {}", msg)?; + } + Ok(()) + } + Self::NotSpaceOwner(msg) => { + write!(f, "NotSpaceOwner")?; + if let Some(msg) = msg { + write!(f, ": {}", msg)?; + } + Ok(()) + } + Self::Other { error, message } => { + write!(f, "{}", error)?; + if let Some(msg) = message { + write!(f, ": {}", msg)?; + } + Ok(()) + } + } + } +} + +/** Response marker for the `com.atproto.simplespace.removeMember` procedure. + +Implements `jacquard_common::xrpc::XrpcResp`; successful bodies decode as `Self::Output`, which is `()` for this endpoint.*/ +pub struct RemoveMemberResponse; +impl jacquard_common::xrpc::XrpcResp for RemoveMemberResponse { + const NSID: &'static str = "com.atproto.simplespace.removeMember"; + const ENCODING: &'static str = "application/json"; + type Output = (); + type Err = RemoveMemberError; +} + +impl jacquard_common::xrpc::XrpcRequest for RemoveMember { + const NSID: &'static str = "com.atproto.simplespace.removeMember"; + const METHOD: jacquard_common::xrpc::XrpcMethod = + jacquard_common::xrpc::XrpcMethod::Procedure("application/json"); + type Response = RemoveMemberResponse; +} + +/** Endpoint marker for the `com.atproto.simplespace.removeMember` procedure. + +Path: `/xrpc/com.atproto.simplespace.removeMember`. The request payload type is `RemoveMember`; send that request with `jacquard::Client` or use this marker through lower-level `XrpcEndpoint` APIs.*/ +pub struct RemoveMemberRequest; +impl jacquard_common::xrpc::XrpcEndpoint for RemoveMemberRequest { + const PATH: &'static str = "/xrpc/com.atproto.simplespace.removeMember"; + const METHOD: jacquard_common::xrpc::XrpcMethod = + jacquard_common::xrpc::XrpcMethod::Procedure("application/json"); + type Request = RemoveMember; + type Response = RemoveMemberResponse; +} + +pub mod remove_member_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 Did; + type Space; + } + /// Empty state - all required fields are unset + pub struct Empty(()); + impl sealed::Sealed for Empty {} + impl State for Empty { + type Did = Unset; + type Space = Unset; + } + ///State transition - sets the `did` field to Set + pub struct SetDid(PhantomData St>); + impl sealed::Sealed for SetDid {} + impl State for SetDid { + type Did = Set; + type Space = St::Space; + } + ///State transition - sets the `space` field to Set + pub struct SetSpace(PhantomData St>); + impl sealed::Sealed for SetSpace {} + impl State for SetSpace { + type Did = St::Did; + type Space = Set; + } + /// Marker types for field names + #[allow(non_camel_case_types)] + pub mod members { + ///Marker type for the `did` field + pub struct did(()); + ///Marker type for the `space` field + pub struct space(()); + } +} + +/// Builder for constructing an instance of this type. +pub struct RemoveMemberBuilder { + _state: PhantomData St>, + _fields: (Option>, Option>), + _type: PhantomData S>, +} + +impl RemoveMember { + /// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed + pub fn new() -> RemoveMemberBuilder { + RemoveMemberBuilder::new() + } +} + +impl RemoveMember { + /// Create a new builder for this type + pub fn builder() -> RemoveMemberBuilder { + RemoveMemberBuilder::builder() + } +} + +impl RemoveMemberBuilder { + /// Create a new builder with all fields unset, using the default string type, if needed + pub fn new() -> Self { + RemoveMemberBuilder { + _state: PhantomData, + _fields: (None, None), + _type: PhantomData, + } + } +} + +impl RemoveMemberBuilder { + /// Create a new builder with all fields unset + pub fn builder() -> Self { + RemoveMemberBuilder { + _state: PhantomData, + _fields: (None, None), + _type: PhantomData, + } + } +} + +impl RemoveMemberBuilder +where + St: remove_member_state::State, + St::Did: remove_member_state::IsUnset, +{ + /// Set the `did` field (required) + pub fn did( + mut self, + value: impl Into>, + ) -> RemoveMemberBuilder, S> { + self._fields.0 = Option::Some(value.into()); + RemoveMemberBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl RemoveMemberBuilder +where + St: remove_member_state::State, + St::Space: remove_member_state::IsUnset, +{ + /// Set the `space` field (required) + pub fn space( + mut self, + value: impl Into>, + ) -> RemoveMemberBuilder, S> { + self._fields.1 = Option::Some(value.into()); + RemoveMemberBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl RemoveMemberBuilder +where + St: remove_member_state::State, + St::Did: remove_member_state::IsSet, + St::Space: remove_member_state::IsSet, +{ + /// Build the final struct. + pub fn build(self) -> RemoveMember { + RemoveMember { + did: self._fields.0.unwrap(), + space: self._fields.1.unwrap(), + extra_data: Default::default(), + } + } + /// Build the final struct with custom extra_data. + pub fn build_with_data(self, extra_data: BTreeMap>) -> RemoveMember { + RemoveMember { + did: self._fields.0.unwrap(), + space: self._fields.1.unwrap(), + extra_data: Some(extra_data), + } + } +} diff --git a/crates/jacquard-api/src/com_atproto/simplespace/update_space.rs b/crates/jacquard-api/src/com_atproto/simplespace/update_space.rs new file mode 100644 index 000000000..0fd76cfcc --- /dev/null +++ b/crates/jacquard-api/src/com_atproto/simplespace/update_space.rs @@ -0,0 +1,307 @@ +// @generated by jacquard-lexicon. DO NOT EDIT. +// +// Lexicon: com.atproto.simplespace.updateSpace +// +// 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; + +use crate::com_atproto::simplespace::AllowList; +use crate::com_atproto::simplespace::ManagingAppPolicy; +use crate::com_atproto::simplespace::MemberListPolicy; +use crate::com_atproto::simplespace::Open; +use crate::com_atproto::simplespace::PublicPolicy; +#[allow(unused_imports)] +use core::marker::PhantomData; +use jacquard_common::deps::smol_str::SmolStr; +use jacquard_common::types::aturi::AtSpaceUri; +use jacquard_common::types::value::Data; +use jacquard_common::{BosStr, CowStr, DefaultStr, FromStaticStr}; +use jacquard_derive::{IntoStatic, open_union}; +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct UpdateSpace { + ///How the authority decides whether to authorize a requesting app. When supplied, replaces the current policy wholesale. + #[serde(skip_serializing_if = "Option::is_none")] + pub app_access: Option>, + ///How the authority decides whether to authorize a requesting user. When supplied, replaces the current policy wholesale. + #[serde(skip_serializing_if = "Option::is_none")] + pub policy: Option>, + ///Reference to the space to update. + pub space: AtSpaceUri, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +#[open_union] +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde(tag = "$type", bound(deserialize = "S: Deserialize<'de> + BosStr"))] +pub enum UpdateSpaceAppAccess { + #[serde(rename = "com.atproto.simplespace.defs#open")] + Open(Box>), + #[serde(rename = "com.atproto.simplespace.defs#allowList")] + AllowList(Box>), +} + +#[open_union] +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde(tag = "$type", bound(deserialize = "S: Deserialize<'de> + BosStr"))] +pub enum UpdateSpacePolicy { + #[serde(rename = "com.atproto.simplespace.defs#publicPolicy")] + PublicPolicy(Box>), + #[serde(rename = "com.atproto.simplespace.defs#memberListPolicy")] + MemberListPolicy(Box>), + #[serde(rename = "com.atproto.simplespace.defs#managingAppPolicy")] + ManagingAppPolicy(Box>), +} + +#[derive( + Serialize, Deserialize, Debug, Clone, PartialEq, Eq, thiserror::Error, miette::Diagnostic, +)] +#[serde(tag = "error", content = "message")] +pub enum UpdateSpaceError { + #[serde(rename = "SpaceNotFound")] + SpaceNotFound(Option), + #[serde(rename = "NotSpaceOwner")] + NotSpaceOwner(Option), + /// The requested policy is not one the host implements. + #[serde(rename = "UnsupportedPolicy")] + UnsupportedPolicy(Option), + /// The requested appAccess variant is not one the host implements. A host will not store an app access policy it cannot enforce. + #[serde(rename = "UnsupportedAppAccess")] + UnsupportedAppAccess(Option), + /// Catch-all for unknown error codes. + #[serde(untagged)] + Other { + error: SmolStr, + message: Option, + }, +} + +impl core::fmt::Display for UpdateSpaceError { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + match self { + Self::SpaceNotFound(msg) => { + write!(f, "SpaceNotFound")?; + if let Some(msg) = msg { + write!(f, ": {}", msg)?; + } + Ok(()) + } + Self::NotSpaceOwner(msg) => { + write!(f, "NotSpaceOwner")?; + if let Some(msg) = msg { + write!(f, ": {}", msg)?; + } + Ok(()) + } + Self::UnsupportedPolicy(msg) => { + write!(f, "UnsupportedPolicy")?; + if let Some(msg) = msg { + write!(f, ": {}", msg)?; + } + Ok(()) + } + Self::UnsupportedAppAccess(msg) => { + write!(f, "UnsupportedAppAccess")?; + if let Some(msg) = msg { + write!(f, ": {}", msg)?; + } + Ok(()) + } + Self::Other { error, message } => { + write!(f, "{}", error)?; + if let Some(msg) = message { + write!(f, ": {}", msg)?; + } + Ok(()) + } + } + } +} + +/** Response marker for the `com.atproto.simplespace.updateSpace` procedure. + +Implements `jacquard_common::xrpc::XrpcResp`; successful bodies decode as `Self::Output`, which is `()` for this endpoint.*/ +pub struct UpdateSpaceResponse; +impl jacquard_common::xrpc::XrpcResp for UpdateSpaceResponse { + const NSID: &'static str = "com.atproto.simplespace.updateSpace"; + const ENCODING: &'static str = "application/json"; + type Output = (); + type Err = UpdateSpaceError; +} + +impl jacquard_common::xrpc::XrpcRequest for UpdateSpace { + const NSID: &'static str = "com.atproto.simplespace.updateSpace"; + const METHOD: jacquard_common::xrpc::XrpcMethod = + jacquard_common::xrpc::XrpcMethod::Procedure("application/json"); + type Response = UpdateSpaceResponse; +} + +/** Endpoint marker for the `com.atproto.simplespace.updateSpace` procedure. + +Path: `/xrpc/com.atproto.simplespace.updateSpace`. The request payload type is `UpdateSpace`; send that request with `jacquard::Client` or use this marker through lower-level `XrpcEndpoint` APIs.*/ +pub struct UpdateSpaceRequest; +impl jacquard_common::xrpc::XrpcEndpoint for UpdateSpaceRequest { + const PATH: &'static str = "/xrpc/com.atproto.simplespace.updateSpace"; + const METHOD: jacquard_common::xrpc::XrpcMethod = + jacquard_common::xrpc::XrpcMethod::Procedure("application/json"); + type Request = UpdateSpace; + type Response = UpdateSpaceResponse; +} + +pub mod update_space_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 Space; + } + /// Empty state - all required fields are unset + pub struct Empty(()); + impl sealed::Sealed for Empty {} + impl State for Empty { + type Space = Unset; + } + ///State transition - sets the `space` field to Set + pub struct SetSpace(PhantomData St>); + impl sealed::Sealed for SetSpace {} + impl State for SetSpace { + type Space = Set; + } + /// Marker types for field names + #[allow(non_camel_case_types)] + pub mod members { + ///Marker type for the `space` field + pub struct space(()); + } +} + +/// Builder for constructing an instance of this type. +pub struct UpdateSpaceBuilder { + _state: PhantomData St>, + _fields: ( + Option>, + Option>, + Option>, + ), + _type: PhantomData S>, +} + +impl UpdateSpace { + /// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed + pub fn new() -> UpdateSpaceBuilder { + UpdateSpaceBuilder::new() + } +} + +impl UpdateSpace { + /// Create a new builder for this type + pub fn builder() -> UpdateSpaceBuilder { + UpdateSpaceBuilder::builder() + } +} + +impl UpdateSpaceBuilder { + /// Create a new builder with all fields unset, using the default string type, if needed + pub fn new() -> Self { + UpdateSpaceBuilder { + _state: PhantomData, + _fields: (None, None, None), + _type: PhantomData, + } + } +} + +impl UpdateSpaceBuilder { + /// Create a new builder with all fields unset + pub fn builder() -> Self { + UpdateSpaceBuilder { + _state: PhantomData, + _fields: (None, None, None), + _type: PhantomData, + } + } +} + +impl UpdateSpaceBuilder { + /// Set the `appAccess` field (optional) + pub fn app_access(mut self, value: impl Into>>) -> Self { + self._fields.0 = value.into(); + self + } + /// Set the `appAccess` field to an Option value (optional) + pub fn maybe_app_access(mut self, value: Option>) -> Self { + self._fields.0 = value; + self + } +} + +impl UpdateSpaceBuilder { + /// Set the `policy` field (optional) + pub fn policy(mut self, value: impl Into>>) -> Self { + self._fields.1 = value.into(); + self + } + /// Set the `policy` field to an Option value (optional) + pub fn maybe_policy(mut self, value: Option>) -> Self { + self._fields.1 = value; + self + } +} + +impl UpdateSpaceBuilder +where + St: update_space_state::State, + St::Space: update_space_state::IsUnset, +{ + /// Set the `space` field (required) + pub fn space( + mut self, + value: impl Into>, + ) -> UpdateSpaceBuilder, S> { + self._fields.2 = Option::Some(value.into()); + UpdateSpaceBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl UpdateSpaceBuilder +where + St: update_space_state::State, + St::Space: update_space_state::IsSet, +{ + /// Build the final struct. + pub fn build(self) -> UpdateSpace { + UpdateSpace { + app_access: self._fields.0, + policy: self._fields.1, + space: 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>) -> UpdateSpace { + UpdateSpace { + app_access: self._fields.0, + policy: self._fields.1, + space: self._fields.2.unwrap(), + extra_data: Some(extra_data), + } + } +} diff --git a/crates/jacquard-api/src/com_atproto/space.rs b/crates/jacquard-api/src/com_atproto/space.rs new file mode 100644 index 000000000..ef3c562e3 --- /dev/null +++ b/crates/jacquard-api/src/com_atproto/space.rs @@ -0,0 +1,480 @@ +// @generated by jacquard-lexicon. DO NOT EDIT. +// +// Lexicon: com.atproto.space.defs +// +// This file was automatically generated from Lexicon schemas. +// Any manual changes will be overwritten on the next regeneration. + +//! Generated bindings for the `com.atproto.space` Lexicon namespace/module. +pub mod apply_writes; +pub mod create_record; +pub mod delete_record; +pub mod get_blob; +pub mod get_delegation_token; +pub mod get_latest_commit; +pub mod get_record; +pub mod get_repo; +pub mod get_space_credential; +pub mod list_blobs; +pub mod list_records; +pub mod list_repo_ops; +pub mod list_repos; +pub mod list_spaces; +pub mod notify_space_deleted; +pub mod notify_write; +pub mod put_record; +pub mod register_notify; +pub mod unregister_notify; + +#[allow(unused_imports)] +use alloc::collections::BTreeMap; + +#[allow(unused_imports)] +use core::marker::PhantomData; +use jacquard_common::deps::bytes::Bytes; +use jacquard_common::{BosStr, DefaultStr, FromStaticStr}; + +#[allow(unused_imports)] +use jacquard_common::deps::codegen::unicode_segmentation::UnicodeSegmentation; +use jacquard_common::deps::smol_str::SmolStr; +use jacquard_common::types::string::Tid; +use jacquard_common::types::value::Data; +use jacquard_derive::IntoStatic; +use jacquard_lexicon::lexicon::LexiconDoc; +use jacquard_lexicon::schema::LexiconSchema; + +#[allow(unused_imports)] +use jacquard_lexicon::validation::{ConstraintError, ValidationPath}; +use serde::{Deserialize, Serialize}; +/// A signed commit over the current state of a permissioned repo. + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct SignedCommit { + ///sha256 digest of the LtHash state (32 bytes). + #[serde(with = "jacquard_common::serde_bytes_helper")] + pub hash: Bytes, + ///Per-signature input keying material (32 random bytes) + #[serde(with = "jacquard_common::serde_bytes_helper")] + pub ikm: Bytes, + ///HMAC-SHA256 over hash, keyed by HKDF-SHA256(ikm, info=ctx). Binds the repo hash to this commit's context. + #[serde(with = "jacquard_common::serde_bytes_helper")] + pub mac: Bytes, + ///Commit revision (TID), also bound into ctx. + pub rev: Tid, + ///Signature over ctx (space, author DID, rev, ikm) by the user's atproto signing key. Does not cover the repo hash. + #[serde(with = "jacquard_common::serde_bytes_helper")] + pub sig: Bytes, + ///Commit format version, currently 1. Corresponds to the version in the ctx protocol tag (atproto-space-v1). + pub ver: i64, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +impl LexiconSchema for SignedCommit { + fn nsid() -> &'static str { + "com.atproto.space.defs" + } + fn def_name() -> &'static str { + "signedCommit" + } + fn lexicon_doc() -> LexiconDoc<'static> { + lexicon_doc_com_atproto_space_defs() + } + fn validate(&self) -> Result<(), ConstraintError> { + Ok(()) + } +} + +pub mod signed_commit_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 Hash; + type Ikm; + type Mac; + type Rev; + type Sig; + type Ver; + } + /// Empty state - all required fields are unset + pub struct Empty(()); + impl sealed::Sealed for Empty {} + impl State for Empty { + type Hash = Unset; + type Ikm = Unset; + type Mac = Unset; + type Rev = Unset; + type Sig = Unset; + type Ver = Unset; + } + ///State transition - sets the `hash` field to Set + pub struct SetHash(PhantomData St>); + impl sealed::Sealed for SetHash {} + impl State for SetHash { + type Hash = Set; + type Ikm = St::Ikm; + type Mac = St::Mac; + type Rev = St::Rev; + type Sig = St::Sig; + type Ver = St::Ver; + } + ///State transition - sets the `ikm` field to Set + pub struct SetIkm(PhantomData St>); + impl sealed::Sealed for SetIkm {} + impl State for SetIkm { + type Hash = St::Hash; + type Ikm = Set; + type Mac = St::Mac; + type Rev = St::Rev; + type Sig = St::Sig; + type Ver = St::Ver; + } + ///State transition - sets the `mac` field to Set + pub struct SetMac(PhantomData St>); + impl sealed::Sealed for SetMac {} + impl State for SetMac { + type Hash = St::Hash; + type Ikm = St::Ikm; + type Mac = Set; + type Rev = St::Rev; + type Sig = St::Sig; + type Ver = St::Ver; + } + ///State transition - sets the `rev` field to Set + pub struct SetRev(PhantomData St>); + impl sealed::Sealed for SetRev {} + impl State for SetRev { + type Hash = St::Hash; + type Ikm = St::Ikm; + type Mac = St::Mac; + type Rev = Set; + type Sig = St::Sig; + type Ver = St::Ver; + } + ///State transition - sets the `sig` field to Set + pub struct SetSig(PhantomData St>); + impl sealed::Sealed for SetSig {} + impl State for SetSig { + type Hash = St::Hash; + type Ikm = St::Ikm; + type Mac = St::Mac; + type Rev = St::Rev; + type Sig = Set; + type Ver = St::Ver; + } + ///State transition - sets the `ver` field to Set + pub struct SetVer(PhantomData St>); + impl sealed::Sealed for SetVer {} + impl State for SetVer { + type Hash = St::Hash; + type Ikm = St::Ikm; + type Mac = St::Mac; + type Rev = St::Rev; + type Sig = St::Sig; + type Ver = Set; + } + /// Marker types for field names + #[allow(non_camel_case_types)] + pub mod members { + ///Marker type for the `hash` field + pub struct hash(()); + ///Marker type for the `ikm` field + pub struct ikm(()); + ///Marker type for the `mac` field + pub struct mac(()); + ///Marker type for the `rev` field + pub struct rev(()); + ///Marker type for the `sig` field + pub struct sig(()); + ///Marker type for the `ver` field + pub struct ver(()); + } +} + +/// Builder for constructing an instance of this type. +pub struct SignedCommitBuilder { + _state: PhantomData St>, + _fields: ( + Option, + Option, + Option, + Option, + Option, + Option, + ), + _type: PhantomData S>, +} + +impl SignedCommit { + /// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed + pub fn new() -> SignedCommitBuilder { + SignedCommitBuilder::new() + } +} + +impl SignedCommit { + /// Create a new builder for this type + pub fn builder() -> SignedCommitBuilder { + SignedCommitBuilder::builder() + } +} + +impl SignedCommitBuilder { + /// Create a new builder with all fields unset, using the default string type, if needed + pub fn new() -> Self { + SignedCommitBuilder { + _state: PhantomData, + _fields: (None, None, None, None, None, None), + _type: PhantomData, + } + } +} + +impl SignedCommitBuilder { + /// Create a new builder with all fields unset + pub fn builder() -> Self { + SignedCommitBuilder { + _state: PhantomData, + _fields: (None, None, None, None, None, None), + _type: PhantomData, + } + } +} + +impl SignedCommitBuilder +where + St: signed_commit_state::State, + St::Hash: signed_commit_state::IsUnset, +{ + /// Set the `hash` field (required) + pub fn hash( + mut self, + value: impl Into, + ) -> SignedCommitBuilder, S> { + self._fields.0 = Option::Some(value.into()); + SignedCommitBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl SignedCommitBuilder +where + St: signed_commit_state::State, + St::Ikm: signed_commit_state::IsUnset, +{ + /// Set the `ikm` field (required) + pub fn ikm( + mut self, + value: impl Into, + ) -> SignedCommitBuilder, S> { + self._fields.1 = Option::Some(value.into()); + SignedCommitBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl SignedCommitBuilder +where + St: signed_commit_state::State, + St::Mac: signed_commit_state::IsUnset, +{ + /// Set the `mac` field (required) + pub fn mac( + mut self, + value: impl Into, + ) -> SignedCommitBuilder, S> { + self._fields.2 = Option::Some(value.into()); + SignedCommitBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl SignedCommitBuilder +where + St: signed_commit_state::State, + St::Rev: signed_commit_state::IsUnset, +{ + /// Set the `rev` field (required) + pub fn rev( + mut self, + value: impl Into, + ) -> SignedCommitBuilder, S> { + self._fields.3 = Option::Some(value.into()); + SignedCommitBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl SignedCommitBuilder +where + St: signed_commit_state::State, + St::Sig: signed_commit_state::IsUnset, +{ + /// Set the `sig` field (required) + pub fn sig( + mut self, + value: impl Into, + ) -> SignedCommitBuilder, S> { + self._fields.4 = Option::Some(value.into()); + SignedCommitBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl SignedCommitBuilder +where + St: signed_commit_state::State, + St::Ver: signed_commit_state::IsUnset, +{ + /// Set the `ver` field (required) + pub fn ver( + mut self, + value: impl Into, + ) -> SignedCommitBuilder, S> { + self._fields.5 = Option::Some(value.into()); + SignedCommitBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl SignedCommitBuilder +where + St: signed_commit_state::State, + St::Hash: signed_commit_state::IsSet, + St::Ikm: signed_commit_state::IsSet, + St::Mac: signed_commit_state::IsSet, + St::Rev: signed_commit_state::IsSet, + St::Sig: signed_commit_state::IsSet, + St::Ver: signed_commit_state::IsSet, +{ + /// Build the final struct. + pub fn build(self) -> SignedCommit { + SignedCommit { + hash: self._fields.0.unwrap(), + ikm: self._fields.1.unwrap(), + mac: self._fields.2.unwrap(), + rev: self._fields.3.unwrap(), + sig: self._fields.4.unwrap(), + ver: self._fields.5.unwrap(), + extra_data: Default::default(), + } + } + /// Build the final struct with custom extra_data. + pub fn build_with_data(self, extra_data: BTreeMap>) -> SignedCommit { + SignedCommit { + hash: self._fields.0.unwrap(), + ikm: self._fields.1.unwrap(), + mac: self._fields.2.unwrap(), + rev: self._fields.3.unwrap(), + sig: self._fields.4.unwrap(), + ver: self._fields.5.unwrap(), + extra_data: Some(extra_data), + } + } +} + +fn lexicon_doc_com_atproto_space_defs() -> 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("com.atproto.space.defs"), + defs: { + let mut map = BTreeMap::new(); + map.insert( + SmolStr::new_static("signedCommit"), + LexUserType::Object(LexObject { + description: Some(CowStr::new_static( + "A signed commit over the current state of a permissioned repo.", + )), + required: Some(vec![ + SmolStr::new_static("ver"), + SmolStr::new_static("hash"), + SmolStr::new_static("mac"), + SmolStr::new_static("ikm"), + SmolStr::new_static("sig"), + SmolStr::new_static("rev"), + ]), + properties: { + #[allow(unused_mut)] + let mut map = BTreeMap::new(); + map.insert( + SmolStr::new_static("hash"), + LexObjectProperty::Bytes(LexBytes { + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("ikm"), + LexObjectProperty::Bytes(LexBytes { + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("mac"), + LexObjectProperty::Bytes(LexBytes { + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("rev"), + LexObjectProperty::String(LexString { + description: Some(CowStr::new_static( + "Commit revision (TID), also bound into ctx.", + )), + format: Some(LexStringFormat::Tid), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("sig"), + LexObjectProperty::Bytes(LexBytes { + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("ver"), + LexObjectProperty::Integer(LexInteger { + ..Default::default() + }), + ); + map + }, + ..Default::default() + }), + ); + map + }, + ..Default::default() + } +} diff --git a/crates/jacquard-api/src/com_atproto/space/apply_writes.rs b/crates/jacquard-api/src/com_atproto/space/apply_writes.rs new file mode 100644 index 000000000..40f0cb83a --- /dev/null +++ b/crates/jacquard-api/src/com_atproto/space/apply_writes.rs @@ -0,0 +1,1825 @@ +// @generated by jacquard-lexicon. DO NOT EDIT. +// +// Lexicon: com.atproto.space.applyWrites +// +// 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::aturi::AtSpaceUri; +use jacquard_common::types::string::{AtUri, Cid, Did, Nsid, RecordKey, Rkey}; +use jacquard_common::types::value::Data; +use jacquard_derive::{IntoStatic, open_union}; +use jacquard_lexicon::lexicon::LexiconDoc; +use jacquard_lexicon::schema::LexiconSchema; + +use crate::com_atproto::space::apply_writes; +#[allow(unused_imports)] +use jacquard_lexicon::validation::{ConstraintError, ValidationPath}; +use serde::{Deserialize, Serialize}; +/// Operation which creates a new record. + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct Create { + pub collection: Nsid, + #[serde(skip_serializing_if = "Option::is_none")] + pub rkey: Option>>, + pub value: Data, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct CreateResult { + pub cid: Cid, + pub uri: AtUri, + #[serde(skip_serializing_if = "Option::is_none")] + pub validation_status: Option>, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub enum CreateResultValidationStatus { + Valid, + Unknown, + Other(S), +} + +impl CreateResultValidationStatus { + pub fn as_str(&self) -> &str { + match self { + Self::Valid => "valid", + Self::Unknown => "unknown", + 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() { + "valid" => Self::Valid, + "unknown" => Self::Unknown, + _ => Self::Other(s), + } + } +} + +impl core::fmt::Display for CreateResultValidationStatus { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!(f, "{}", self.as_str()) + } +} + +impl AsRef for CreateResultValidationStatus { + fn as_ref(&self) -> &str { + self.as_str() + } +} + +impl Serialize for CreateResultValidationStatus { + 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 CreateResultValidationStatus { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = S::deserialize(deserializer)?; + Ok(Self::from_value(s)) + } +} + +impl Default for CreateResultValidationStatus { + fn default() -> Self { + Self::Other(Default::default()) + } +} + +impl jacquard_common::IntoStatic for CreateResultValidationStatus +where + S: BosStr + jacquard_common::IntoStatic, + S::Output: BosStr, +{ + type Output = CreateResultValidationStatus; + fn into_static(self) -> Self::Output { + match self { + CreateResultValidationStatus::Valid => CreateResultValidationStatus::Valid, + CreateResultValidationStatus::Unknown => CreateResultValidationStatus::Unknown, + CreateResultValidationStatus::Other(v) => { + CreateResultValidationStatus::Other(v.into_static()) + } + } + } +} + +/// Operation which deletes an existing record. + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct Delete { + pub collection: Nsid, + pub rkey: RecordKey>, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic, Default)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct DeleteResult { + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct ApplyWrites { + ///The DID of the repo to write to (the authenticated member). + pub repo: Did, + ///Reference to the space. + pub space: AtSpaceUri, + ///Can be set to 'false' to skip Lexicon schema validation of record data across all operations, 'true' to require it, or leave unset to validate only for known Lexicons. + #[serde(skip_serializing_if = "Option::is_none")] + pub validate: Option, + pub writes: Vec>, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde(tag = "$type", bound(deserialize = "S: Deserialize<'de> + BosStr"))] +pub enum ApplyWritesWritesItem { + #[serde(rename = "com.atproto.space.applyWrites#create")] + Create(Box>), + #[serde(rename = "com.atproto.space.applyWrites#update")] + Update(Box>), + #[serde(rename = "com.atproto.space.applyWrites#delete")] + Delete(Box>), +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic, Default)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct ApplyWritesOutput { + #[serde(skip_serializing_if = "Option::is_none")] + pub results: Option>>, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde(tag = "$type", bound(deserialize = "S: Deserialize<'de> + BosStr"))] +pub enum ApplyWritesOutputResultsItem { + #[serde(rename = "com.atproto.space.applyWrites#createResult")] + CreateResult(Box>), + #[serde(rename = "com.atproto.space.applyWrites#updateResult")] + UpdateResult(Box>), + #[serde(rename = "com.atproto.space.applyWrites#deleteResult")] + DeleteResult(Box>), +} + +#[derive( + Serialize, Deserialize, Debug, Clone, PartialEq, Eq, thiserror::Error, miette::Diagnostic, +)] +#[serde(tag = "error", content = "message")] +pub enum ApplyWritesError { + #[serde(rename = "SpaceNotFound")] + SpaceNotFound(Option), + /// An update or delete targeted a record that does not exist. + #[serde(rename = "RecordNotFound")] + RecordNotFound(Option), + /// A create targeted a collection and rkey that already holds a record. + #[serde(rename = "RecordAlreadyExists")] + RecordAlreadyExists(Option), + /// Catch-all for unknown error codes. + #[serde(untagged)] + Other { + error: SmolStr, + message: Option, + }, +} + +impl core::fmt::Display for ApplyWritesError { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + match self { + Self::SpaceNotFound(msg) => { + write!(f, "SpaceNotFound")?; + if let Some(msg) = msg { + write!(f, ": {}", msg)?; + } + Ok(()) + } + Self::RecordNotFound(msg) => { + write!(f, "RecordNotFound")?; + if let Some(msg) = msg { + write!(f, ": {}", msg)?; + } + Ok(()) + } + Self::RecordAlreadyExists(msg) => { + write!(f, "RecordAlreadyExists")?; + if let Some(msg) = msg { + write!(f, ": {}", msg)?; + } + Ok(()) + } + Self::Other { error, message } => { + write!(f, "{}", error)?; + if let Some(msg) = message { + write!(f, ": {}", msg)?; + } + Ok(()) + } + } + } +} + +/// Operation which updates an existing record. + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct Update { + pub collection: Nsid, + pub rkey: RecordKey>, + pub value: Data, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct UpdateResult { + pub cid: Cid, + pub uri: AtUri, + #[serde(skip_serializing_if = "Option::is_none")] + pub validation_status: Option>, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub enum UpdateResultValidationStatus { + Valid, + Unknown, + Other(S), +} + +impl UpdateResultValidationStatus { + pub fn as_str(&self) -> &str { + match self { + Self::Valid => "valid", + Self::Unknown => "unknown", + 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() { + "valid" => Self::Valid, + "unknown" => Self::Unknown, + _ => Self::Other(s), + } + } +} + +impl core::fmt::Display for UpdateResultValidationStatus { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!(f, "{}", self.as_str()) + } +} + +impl AsRef for UpdateResultValidationStatus { + fn as_ref(&self) -> &str { + self.as_str() + } +} + +impl Serialize for UpdateResultValidationStatus { + 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 UpdateResultValidationStatus { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = S::deserialize(deserializer)?; + Ok(Self::from_value(s)) + } +} + +impl Default for UpdateResultValidationStatus { + fn default() -> Self { + Self::Other(Default::default()) + } +} + +impl jacquard_common::IntoStatic for UpdateResultValidationStatus +where + S: BosStr + jacquard_common::IntoStatic, + S::Output: BosStr, +{ + type Output = UpdateResultValidationStatus; + fn into_static(self) -> Self::Output { + match self { + UpdateResultValidationStatus::Valid => UpdateResultValidationStatus::Valid, + UpdateResultValidationStatus::Unknown => UpdateResultValidationStatus::Unknown, + UpdateResultValidationStatus::Other(v) => { + UpdateResultValidationStatus::Other(v.into_static()) + } + } + } +} + +impl LexiconSchema for Create { + fn nsid() -> &'static str { + "com.atproto.space.applyWrites" + } + fn def_name() -> &'static str { + "create" + } + fn lexicon_doc() -> LexiconDoc<'static> { + lexicon_doc_com_atproto_space_applyWrites() + } + fn validate(&self) -> Result<(), ConstraintError> { + if let Some(ref value) = self.rkey { + #[allow(unused_comparisons)] + if ::len(value.as_ref()) > 512usize { + return Err(ConstraintError::MaxLength { + path: ValidationPath::from_field("rkey"), + max: 512usize, + actual: ::len(value.as_ref()), + }); + } + } + Ok(()) + } +} + +impl LexiconSchema for CreateResult { + fn nsid() -> &'static str { + "com.atproto.space.applyWrites" + } + fn def_name() -> &'static str { + "createResult" + } + fn lexicon_doc() -> LexiconDoc<'static> { + lexicon_doc_com_atproto_space_applyWrites() + } + fn validate(&self) -> Result<(), ConstraintError> { + Ok(()) + } +} + +impl LexiconSchema for Delete { + fn nsid() -> &'static str { + "com.atproto.space.applyWrites" + } + fn def_name() -> &'static str { + "delete" + } + fn lexicon_doc() -> LexiconDoc<'static> { + lexicon_doc_com_atproto_space_applyWrites() + } + fn validate(&self) -> Result<(), ConstraintError> { + Ok(()) + } +} + +impl LexiconSchema for DeleteResult { + fn nsid() -> &'static str { + "com.atproto.space.applyWrites" + } + fn def_name() -> &'static str { + "deleteResult" + } + fn lexicon_doc() -> LexiconDoc<'static> { + lexicon_doc_com_atproto_space_applyWrites() + } + fn validate(&self) -> Result<(), ConstraintError> { + Ok(()) + } +} + +/** Response marker for the `com.atproto.space.applyWrites` procedure. + +Implements `jacquard_common::xrpc::XrpcResp`; successful bodies decode as `Self::Output`, which is `ApplyWritesOutput` for this endpoint.*/ +pub struct ApplyWritesResponse; +impl jacquard_common::xrpc::XrpcResp for ApplyWritesResponse { + const NSID: &'static str = "com.atproto.space.applyWrites"; + const ENCODING: &'static str = "application/json"; + type Output = ApplyWritesOutput; + type Err = ApplyWritesError; +} + +impl jacquard_common::xrpc::XrpcRequest for ApplyWrites { + const NSID: &'static str = "com.atproto.space.applyWrites"; + const METHOD: jacquard_common::xrpc::XrpcMethod = + jacquard_common::xrpc::XrpcMethod::Procedure("application/json"); + type Response = ApplyWritesResponse; +} + +/** Endpoint marker for the `com.atproto.space.applyWrites` procedure. + +Path: `/xrpc/com.atproto.space.applyWrites`. The request payload type is `ApplyWrites`; send that request with `jacquard::Client` or use this marker through lower-level `XrpcEndpoint` APIs.*/ +pub struct ApplyWritesRequest; +impl jacquard_common::xrpc::XrpcEndpoint for ApplyWritesRequest { + const PATH: &'static str = "/xrpc/com.atproto.space.applyWrites"; + const METHOD: jacquard_common::xrpc::XrpcMethod = + jacquard_common::xrpc::XrpcMethod::Procedure("application/json"); + type Request = ApplyWrites; + type Response = ApplyWritesResponse; +} + +impl LexiconSchema for Update { + fn nsid() -> &'static str { + "com.atproto.space.applyWrites" + } + fn def_name() -> &'static str { + "update" + } + fn lexicon_doc() -> LexiconDoc<'static> { + lexicon_doc_com_atproto_space_applyWrites() + } + fn validate(&self) -> Result<(), ConstraintError> { + Ok(()) + } +} + +impl LexiconSchema for UpdateResult { + fn nsid() -> &'static str { + "com.atproto.space.applyWrites" + } + fn def_name() -> &'static str { + "updateResult" + } + fn lexicon_doc() -> LexiconDoc<'static> { + lexicon_doc_com_atproto_space_applyWrites() + } + fn validate(&self) -> Result<(), ConstraintError> { + Ok(()) + } +} + +pub mod create_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 Collection; + type Value; + } + /// Empty state - all required fields are unset + pub struct Empty(()); + impl sealed::Sealed for Empty {} + impl State for Empty { + type Collection = Unset; + type Value = Unset; + } + ///State transition - sets the `collection` field to Set + pub struct SetCollection(PhantomData St>); + impl sealed::Sealed for SetCollection {} + impl State for SetCollection { + type Collection = Set; + type Value = St::Value; + } + ///State transition - sets the `value` field to Set + pub struct SetValue(PhantomData St>); + impl sealed::Sealed for SetValue {} + impl State for SetValue { + type Collection = St::Collection; + type Value = Set; + } + /// Marker types for field names + #[allow(non_camel_case_types)] + pub mod members { + ///Marker type for the `collection` field + pub struct collection(()); + ///Marker type for the `value` field + pub struct value(()); + } +} + +/// Builder for constructing an instance of this type. +pub struct CreateBuilder { + _state: PhantomData St>, + _fields: (Option>, Option>>, Option>), + _type: PhantomData S>, +} + +impl Create { + /// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed + pub fn new() -> CreateBuilder { + CreateBuilder::new() + } +} + +impl Create { + /// Create a new builder for this type + pub fn builder() -> CreateBuilder { + CreateBuilder::builder() + } +} + +impl CreateBuilder { + /// Create a new builder with all fields unset, using the default string type, if needed + pub fn new() -> Self { + CreateBuilder { + _state: PhantomData, + _fields: (None, None, None), + _type: PhantomData, + } + } +} + +impl CreateBuilder { + /// Create a new builder with all fields unset + pub fn builder() -> Self { + CreateBuilder { + _state: PhantomData, + _fields: (None, None, None), + _type: PhantomData, + } + } +} + +impl CreateBuilder +where + St: create_state::State, + St::Collection: create_state::IsUnset, +{ + /// Set the `collection` field (required) + pub fn collection( + mut self, + value: impl Into>, + ) -> CreateBuilder, S> { + self._fields.0 = Option::Some(value.into()); + CreateBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl CreateBuilder { + /// Set the `rkey` field (optional) + pub fn rkey(mut self, value: impl Into>>>) -> Self { + self._fields.1 = value.into(); + self + } + /// Set the `rkey` field to an Option value (optional) + pub fn maybe_rkey(mut self, value: Option>>) -> Self { + self._fields.1 = value; + self + } +} + +impl CreateBuilder +where + St: create_state::State, + St::Value: create_state::IsUnset, +{ + /// Set the `value` field (required) + pub fn value( + mut self, + value: impl Into>, + ) -> CreateBuilder, S> { + self._fields.2 = Option::Some(value.into()); + CreateBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl CreateBuilder +where + St: create_state::State, + St::Collection: create_state::IsSet, + St::Value: create_state::IsSet, +{ + /// Build the final struct. + pub fn build(self) -> Create { + Create { + collection: self._fields.0.unwrap(), + rkey: self._fields.1, + value: 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>) -> Create { + Create { + collection: self._fields.0.unwrap(), + rkey: self._fields.1, + value: self._fields.2.unwrap(), + extra_data: Some(extra_data), + } + } +} + +fn lexicon_doc_com_atproto_space_applyWrites() -> 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("com.atproto.space.applyWrites"), + defs: { + let mut map = BTreeMap::new(); + map.insert( + SmolStr::new_static("create"), + LexUserType::Object(LexObject { + description: Some(CowStr::new_static("Operation which creates a new record.")), + required: Some(vec![ + SmolStr::new_static("collection"), + SmolStr::new_static("value"), + ]), + properties: { + #[allow(unused_mut)] + let mut map = BTreeMap::new(); + map.insert( + SmolStr::new_static("collection"), + LexObjectProperty::String(LexString { + format: Some(LexStringFormat::Nsid), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("rkey"), + LexObjectProperty::String(LexString { + format: Some(LexStringFormat::RecordKey), + max_length: Some(512usize), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("value"), + LexObjectProperty::Unknown(LexUnknown { + ..Default::default() + }), + ); + map + }, + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("createResult"), + LexUserType::Object(LexObject { + required: Some(vec![SmolStr::new_static("uri"), SmolStr::new_static("cid")]), + properties: { + #[allow(unused_mut)] + let mut map = BTreeMap::new(); + map.insert( + SmolStr::new_static("cid"), + LexObjectProperty::String(LexString { + format: Some(LexStringFormat::Cid), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("uri"), + LexObjectProperty::String(LexString { + format: Some(LexStringFormat::AtUri), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("validationStatus"), + LexObjectProperty::String(LexString { + ..Default::default() + }), + ); + map + }, + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("delete"), + LexUserType::Object(LexObject { + description: Some(CowStr::new_static( + "Operation which deletes an existing record.", + )), + required: Some(vec![ + SmolStr::new_static("collection"), + SmolStr::new_static("rkey"), + ]), + properties: { + #[allow(unused_mut)] + let mut map = BTreeMap::new(); + map.insert( + SmolStr::new_static("collection"), + LexObjectProperty::String(LexString { + format: Some(LexStringFormat::Nsid), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("rkey"), + LexObjectProperty::String(LexString { + format: Some(LexStringFormat::RecordKey), + ..Default::default() + }), + ); + map + }, + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("deleteResult"), + LexUserType::Object(LexObject { + required: Some(vec![]), + properties: { + #[allow(unused_mut)] + let mut map = BTreeMap::new(); + map + }, + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("main"), + LexUserType::XrpcProcedure(LexXrpcProcedure { + input: Some(LexXrpcBody { + encoding: CowStr::new_static("application/json"), + schema: Some( + LexXrpcBodySchema::Object(LexObject { + required: Some( + vec![ + SmolStr::new_static("space"), SmolStr::new_static("repo"), + SmolStr::new_static("writes") + ], + ), + properties: { + #[allow(unused_mut)] + let mut map = BTreeMap::new(); + map.insert( + SmolStr::new_static("repo"), + LexObjectProperty::String(LexString { + description: Some( + CowStr::new_static( + "The DID of the repo to write to (the authenticated member).", + ), + ), + format: Some(LexStringFormat::Did), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("space"), + LexObjectProperty::String(LexString { + description: Some( + CowStr::new_static("Reference to the space."), + ), + format: Some(LexStringFormat::SpaceRef), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("validate"), + LexObjectProperty::Boolean(LexBoolean { + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("writes"), + LexObjectProperty::Array(LexArray { + items: LexArrayItem::Union(LexRefUnion { + refs: vec![ + CowStr::new_static("#create"), + CowStr::new_static("#update"), CowStr::new_static("#delete") + ], + closed: Some(true), + ..Default::default() + }), + ..Default::default() + }), + ); + map + }, + ..Default::default() + }), + ), + ..Default::default() + }), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("update"), + LexUserType::Object(LexObject { + description: Some(CowStr::new_static( + "Operation which updates an existing record.", + )), + required: Some(vec![ + SmolStr::new_static("collection"), + SmolStr::new_static("rkey"), + SmolStr::new_static("value"), + ]), + properties: { + #[allow(unused_mut)] + let mut map = BTreeMap::new(); + map.insert( + SmolStr::new_static("collection"), + LexObjectProperty::String(LexString { + format: Some(LexStringFormat::Nsid), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("rkey"), + LexObjectProperty::String(LexString { + format: Some(LexStringFormat::RecordKey), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("value"), + LexObjectProperty::Unknown(LexUnknown { + ..Default::default() + }), + ); + map + }, + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("updateResult"), + LexUserType::Object(LexObject { + required: Some(vec![SmolStr::new_static("uri"), SmolStr::new_static("cid")]), + properties: { + #[allow(unused_mut)] + let mut map = BTreeMap::new(); + map.insert( + SmolStr::new_static("cid"), + LexObjectProperty::String(LexString { + format: Some(LexStringFormat::Cid), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("uri"), + LexObjectProperty::String(LexString { + format: Some(LexStringFormat::AtUri), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("validationStatus"), + LexObjectProperty::String(LexString { + ..Default::default() + }), + ); + map + }, + ..Default::default() + }), + ); + map + }, + ..Default::default() + } +} + +pub mod create_result_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 Cid; + type Uri; + } + /// Empty state - all required fields are unset + pub struct Empty(()); + impl sealed::Sealed for Empty {} + impl State for Empty { + type Cid = Unset; + type Uri = Unset; + } + ///State transition - sets the `cid` field to Set + pub struct SetCid(PhantomData St>); + impl sealed::Sealed for SetCid {} + impl State for SetCid { + type Cid = Set; + type Uri = St::Uri; + } + ///State transition - sets the `uri` field to Set + pub struct SetUri(PhantomData St>); + impl sealed::Sealed for SetUri {} + impl State for SetUri { + type Cid = St::Cid; + type Uri = Set; + } + /// Marker types for field names + #[allow(non_camel_case_types)] + pub mod members { + ///Marker type for the `cid` field + pub struct cid(()); + ///Marker type for the `uri` field + pub struct uri(()); + } +} + +/// Builder for constructing an instance of this type. +pub struct CreateResultBuilder { + _state: PhantomData St>, + _fields: ( + Option>, + Option>, + Option>, + ), + _type: PhantomData S>, +} + +impl CreateResult { + /// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed + pub fn new() -> CreateResultBuilder { + CreateResultBuilder::new() + } +} + +impl CreateResult { + /// Create a new builder for this type + pub fn builder() -> CreateResultBuilder { + CreateResultBuilder::builder() + } +} + +impl CreateResultBuilder { + /// Create a new builder with all fields unset, using the default string type, if needed + pub fn new() -> Self { + CreateResultBuilder { + _state: PhantomData, + _fields: (None, None, None), + _type: PhantomData, + } + } +} + +impl CreateResultBuilder { + /// Create a new builder with all fields unset + pub fn builder() -> Self { + CreateResultBuilder { + _state: PhantomData, + _fields: (None, None, None), + _type: PhantomData, + } + } +} + +impl CreateResultBuilder +where + St: create_result_state::State, + St::Cid: create_result_state::IsUnset, +{ + /// Set the `cid` field (required) + pub fn cid( + mut self, + value: impl Into>, + ) -> CreateResultBuilder, S> { + self._fields.0 = Option::Some(value.into()); + CreateResultBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl CreateResultBuilder +where + St: create_result_state::State, + St::Uri: create_result_state::IsUnset, +{ + /// Set the `uri` field (required) + pub fn uri( + mut self, + value: impl Into>, + ) -> CreateResultBuilder, S> { + self._fields.1 = Option::Some(value.into()); + CreateResultBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl CreateResultBuilder { + /// Set the `validationStatus` field (optional) + pub fn validation_status( + mut self, + value: impl Into>>, + ) -> Self { + self._fields.2 = value.into(); + self + } + /// Set the `validationStatus` field to an Option value (optional) + pub fn maybe_validation_status( + mut self, + value: Option>, + ) -> Self { + self._fields.2 = value; + self + } +} + +impl CreateResultBuilder +where + St: create_result_state::State, + St::Cid: create_result_state::IsSet, + St::Uri: create_result_state::IsSet, +{ + /// Build the final struct. + pub fn build(self) -> CreateResult { + CreateResult { + cid: self._fields.0.unwrap(), + uri: self._fields.1.unwrap(), + validation_status: self._fields.2, + extra_data: Default::default(), + } + } + /// Build the final struct with custom extra_data. + pub fn build_with_data(self, extra_data: BTreeMap>) -> CreateResult { + CreateResult { + cid: self._fields.0.unwrap(), + uri: self._fields.1.unwrap(), + validation_status: self._fields.2, + extra_data: Some(extra_data), + } + } +} + +pub mod delete_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 Collection; + type Rkey; + } + /// Empty state - all required fields are unset + pub struct Empty(()); + impl sealed::Sealed for Empty {} + impl State for Empty { + type Collection = Unset; + type Rkey = Unset; + } + ///State transition - sets the `collection` field to Set + pub struct SetCollection(PhantomData St>); + impl sealed::Sealed for SetCollection {} + impl State for SetCollection { + type Collection = Set; + type Rkey = St::Rkey; + } + ///State transition - sets the `rkey` field to Set + pub struct SetRkey(PhantomData St>); + impl sealed::Sealed for SetRkey {} + impl State for SetRkey { + type Collection = St::Collection; + type Rkey = Set; + } + /// Marker types for field names + #[allow(non_camel_case_types)] + pub mod members { + ///Marker type for the `collection` field + pub struct collection(()); + ///Marker type for the `rkey` field + pub struct rkey(()); + } +} + +/// Builder for constructing an instance of this type. +pub struct DeleteBuilder { + _state: PhantomData St>, + _fields: (Option>, Option>>), + _type: PhantomData S>, +} + +impl Delete { + /// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed + pub fn new() -> DeleteBuilder { + DeleteBuilder::new() + } +} + +impl Delete { + /// Create a new builder for this type + pub fn builder() -> DeleteBuilder { + DeleteBuilder::builder() + } +} + +impl DeleteBuilder { + /// Create a new builder with all fields unset, using the default string type, if needed + pub fn new() -> Self { + DeleteBuilder { + _state: PhantomData, + _fields: (None, None), + _type: PhantomData, + } + } +} + +impl DeleteBuilder { + /// Create a new builder with all fields unset + pub fn builder() -> Self { + DeleteBuilder { + _state: PhantomData, + _fields: (None, None), + _type: PhantomData, + } + } +} + +impl DeleteBuilder +where + St: delete_state::State, + St::Collection: delete_state::IsUnset, +{ + /// Set the `collection` field (required) + pub fn collection( + mut self, + value: impl Into>, + ) -> DeleteBuilder, S> { + self._fields.0 = Option::Some(value.into()); + DeleteBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl DeleteBuilder +where + St: delete_state::State, + St::Rkey: delete_state::IsUnset, +{ + /// Set the `rkey` field (required) + pub fn rkey( + mut self, + value: impl Into>>, + ) -> DeleteBuilder, S> { + self._fields.1 = Option::Some(value.into()); + DeleteBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl DeleteBuilder +where + St: delete_state::State, + St::Collection: delete_state::IsSet, + St::Rkey: delete_state::IsSet, +{ + /// Build the final struct. + pub fn build(self) -> Delete { + Delete { + collection: self._fields.0.unwrap(), + rkey: self._fields.1.unwrap(), + extra_data: Default::default(), + } + } + /// Build the final struct with custom extra_data. + pub fn build_with_data(self, extra_data: BTreeMap>) -> Delete { + Delete { + collection: self._fields.0.unwrap(), + rkey: self._fields.1.unwrap(), + extra_data: Some(extra_data), + } + } +} + +pub mod apply_writes_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 Repo; + type Space; + type Writes; + } + /// Empty state - all required fields are unset + pub struct Empty(()); + impl sealed::Sealed for Empty {} + impl State for Empty { + type Repo = Unset; + type Space = Unset; + type Writes = Unset; + } + ///State transition - sets the `repo` field to Set + pub struct SetRepo(PhantomData St>); + impl sealed::Sealed for SetRepo {} + impl State for SetRepo { + type Repo = Set; + type Space = St::Space; + type Writes = St::Writes; + } + ///State transition - sets the `space` field to Set + pub struct SetSpace(PhantomData St>); + impl sealed::Sealed for SetSpace {} + impl State for SetSpace { + type Repo = St::Repo; + type Space = Set; + type Writes = St::Writes; + } + ///State transition - sets the `writes` field to Set + pub struct SetWrites(PhantomData St>); + impl sealed::Sealed for SetWrites {} + impl State for SetWrites { + type Repo = St::Repo; + type Space = St::Space; + type Writes = Set; + } + /// Marker types for field names + #[allow(non_camel_case_types)] + pub mod members { + ///Marker type for the `repo` field + pub struct repo(()); + ///Marker type for the `space` field + pub struct space(()); + ///Marker type for the `writes` field + pub struct writes(()); + } +} + +/// Builder for constructing an instance of this type. +pub struct ApplyWritesBuilder { + _state: PhantomData St>, + _fields: ( + Option>, + Option>, + Option, + Option>>, + ), + _type: PhantomData S>, +} + +impl ApplyWrites { + /// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed + pub fn new() -> ApplyWritesBuilder { + ApplyWritesBuilder::new() + } +} + +impl ApplyWrites { + /// Create a new builder for this type + pub fn builder() -> ApplyWritesBuilder { + ApplyWritesBuilder::builder() + } +} + +impl ApplyWritesBuilder { + /// Create a new builder with all fields unset, using the default string type, if needed + pub fn new() -> Self { + ApplyWritesBuilder { + _state: PhantomData, + _fields: (None, None, None, None), + _type: PhantomData, + } + } +} + +impl ApplyWritesBuilder { + /// Create a new builder with all fields unset + pub fn builder() -> Self { + ApplyWritesBuilder { + _state: PhantomData, + _fields: (None, None, None, None), + _type: PhantomData, + } + } +} + +impl ApplyWritesBuilder +where + St: apply_writes_state::State, + St::Repo: apply_writes_state::IsUnset, +{ + /// Set the `repo` field (required) + pub fn repo( + mut self, + value: impl Into>, + ) -> ApplyWritesBuilder, S> { + self._fields.0 = Option::Some(value.into()); + ApplyWritesBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl ApplyWritesBuilder +where + St: apply_writes_state::State, + St::Space: apply_writes_state::IsUnset, +{ + /// Set the `space` field (required) + pub fn space( + mut self, + value: impl Into>, + ) -> ApplyWritesBuilder, S> { + self._fields.1 = Option::Some(value.into()); + ApplyWritesBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl ApplyWritesBuilder { + /// Set the `validate` field (optional) + pub fn validate(mut self, value: impl Into>) -> Self { + self._fields.2 = value.into(); + self + } + /// Set the `validate` field to an Option value (optional) + pub fn maybe_validate(mut self, value: Option) -> Self { + self._fields.2 = value; + self + } +} + +impl ApplyWritesBuilder +where + St: apply_writes_state::State, + St::Writes: apply_writes_state::IsUnset, +{ + /// Set the `writes` field (required) + pub fn writes( + mut self, + value: impl Into>>, + ) -> ApplyWritesBuilder, S> { + self._fields.3 = Option::Some(value.into()); + ApplyWritesBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl ApplyWritesBuilder +where + St: apply_writes_state::State, + St::Repo: apply_writes_state::IsSet, + St::Space: apply_writes_state::IsSet, + St::Writes: apply_writes_state::IsSet, +{ + /// Build the final struct. + pub fn build(self) -> ApplyWrites { + ApplyWrites { + repo: self._fields.0.unwrap(), + space: self._fields.1.unwrap(), + validate: self._fields.2, + writes: self._fields.3.unwrap(), + extra_data: Default::default(), + } + } + /// Build the final struct with custom extra_data. + pub fn build_with_data(self, extra_data: BTreeMap>) -> ApplyWrites { + ApplyWrites { + repo: self._fields.0.unwrap(), + space: self._fields.1.unwrap(), + validate: self._fields.2, + writes: self._fields.3.unwrap(), + extra_data: Some(extra_data), + } + } +} + +pub mod update_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 Collection; + type Rkey; + type Value; + } + /// Empty state - all required fields are unset + pub struct Empty(()); + impl sealed::Sealed for Empty {} + impl State for Empty { + type Collection = Unset; + type Rkey = Unset; + type Value = Unset; + } + ///State transition - sets the `collection` field to Set + pub struct SetCollection(PhantomData St>); + impl sealed::Sealed for SetCollection {} + impl State for SetCollection { + type Collection = Set; + type Rkey = St::Rkey; + type Value = St::Value; + } + ///State transition - sets the `rkey` field to Set + pub struct SetRkey(PhantomData St>); + impl sealed::Sealed for SetRkey {} + impl State for SetRkey { + type Collection = St::Collection; + type Rkey = Set; + type Value = St::Value; + } + ///State transition - sets the `value` field to Set + pub struct SetValue(PhantomData St>); + impl sealed::Sealed for SetValue {} + impl State for SetValue { + type Collection = St::Collection; + type Rkey = St::Rkey; + type Value = Set; + } + /// Marker types for field names + #[allow(non_camel_case_types)] + pub mod members { + ///Marker type for the `collection` field + pub struct collection(()); + ///Marker type for the `rkey` field + pub struct rkey(()); + ///Marker type for the `value` field + pub struct value(()); + } +} + +/// Builder for constructing an instance of this type. +pub struct UpdateBuilder { + _state: PhantomData St>, + _fields: (Option>, Option>>, Option>), + _type: PhantomData S>, +} + +impl Update { + /// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed + pub fn new() -> UpdateBuilder { + UpdateBuilder::new() + } +} + +impl Update { + /// Create a new builder for this type + pub fn builder() -> UpdateBuilder { + UpdateBuilder::builder() + } +} + +impl UpdateBuilder { + /// Create a new builder with all fields unset, using the default string type, if needed + pub fn new() -> Self { + UpdateBuilder { + _state: PhantomData, + _fields: (None, None, None), + _type: PhantomData, + } + } +} + +impl UpdateBuilder { + /// Create a new builder with all fields unset + pub fn builder() -> Self { + UpdateBuilder { + _state: PhantomData, + _fields: (None, None, None), + _type: PhantomData, + } + } +} + +impl UpdateBuilder +where + St: update_state::State, + St::Collection: update_state::IsUnset, +{ + /// Set the `collection` field (required) + pub fn collection( + mut self, + value: impl Into>, + ) -> UpdateBuilder, S> { + self._fields.0 = Option::Some(value.into()); + UpdateBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl UpdateBuilder +where + St: update_state::State, + St::Rkey: update_state::IsUnset, +{ + /// Set the `rkey` field (required) + pub fn rkey( + mut self, + value: impl Into>>, + ) -> UpdateBuilder, S> { + self._fields.1 = Option::Some(value.into()); + UpdateBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl UpdateBuilder +where + St: update_state::State, + St::Value: update_state::IsUnset, +{ + /// Set the `value` field (required) + pub fn value( + mut self, + value: impl Into>, + ) -> UpdateBuilder, S> { + self._fields.2 = Option::Some(value.into()); + UpdateBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl UpdateBuilder +where + St: update_state::State, + St::Collection: update_state::IsSet, + St::Rkey: update_state::IsSet, + St::Value: update_state::IsSet, +{ + /// Build the final struct. + pub fn build(self) -> Update { + Update { + collection: self._fields.0.unwrap(), + rkey: self._fields.1.unwrap(), + value: 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>) -> Update { + Update { + collection: self._fields.0.unwrap(), + rkey: self._fields.1.unwrap(), + value: self._fields.2.unwrap(), + extra_data: Some(extra_data), + } + } +} + +pub mod update_result_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 Cid; + type Uri; + } + /// Empty state - all required fields are unset + pub struct Empty(()); + impl sealed::Sealed for Empty {} + impl State for Empty { + type Cid = Unset; + type Uri = Unset; + } + ///State transition - sets the `cid` field to Set + pub struct SetCid(PhantomData St>); + impl sealed::Sealed for SetCid {} + impl State for SetCid { + type Cid = Set; + type Uri = St::Uri; + } + ///State transition - sets the `uri` field to Set + pub struct SetUri(PhantomData St>); + impl sealed::Sealed for SetUri {} + impl State for SetUri { + type Cid = St::Cid; + type Uri = Set; + } + /// Marker types for field names + #[allow(non_camel_case_types)] + pub mod members { + ///Marker type for the `cid` field + pub struct cid(()); + ///Marker type for the `uri` field + pub struct uri(()); + } +} + +/// Builder for constructing an instance of this type. +pub struct UpdateResultBuilder { + _state: PhantomData St>, + _fields: ( + Option>, + Option>, + Option>, + ), + _type: PhantomData S>, +} + +impl UpdateResult { + /// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed + pub fn new() -> UpdateResultBuilder { + UpdateResultBuilder::new() + } +} + +impl UpdateResult { + /// Create a new builder for this type + pub fn builder() -> UpdateResultBuilder { + UpdateResultBuilder::builder() + } +} + +impl UpdateResultBuilder { + /// Create a new builder with all fields unset, using the default string type, if needed + pub fn new() -> Self { + UpdateResultBuilder { + _state: PhantomData, + _fields: (None, None, None), + _type: PhantomData, + } + } +} + +impl UpdateResultBuilder { + /// Create a new builder with all fields unset + pub fn builder() -> Self { + UpdateResultBuilder { + _state: PhantomData, + _fields: (None, None, None), + _type: PhantomData, + } + } +} + +impl UpdateResultBuilder +where + St: update_result_state::State, + St::Cid: update_result_state::IsUnset, +{ + /// Set the `cid` field (required) + pub fn cid( + mut self, + value: impl Into>, + ) -> UpdateResultBuilder, S> { + self._fields.0 = Option::Some(value.into()); + UpdateResultBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl UpdateResultBuilder +where + St: update_result_state::State, + St::Uri: update_result_state::IsUnset, +{ + /// Set the `uri` field (required) + pub fn uri( + mut self, + value: impl Into>, + ) -> UpdateResultBuilder, S> { + self._fields.1 = Option::Some(value.into()); + UpdateResultBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl UpdateResultBuilder { + /// Set the `validationStatus` field (optional) + pub fn validation_status( + mut self, + value: impl Into>>, + ) -> Self { + self._fields.2 = value.into(); + self + } + /// Set the `validationStatus` field to an Option value (optional) + pub fn maybe_validation_status( + mut self, + value: Option>, + ) -> Self { + self._fields.2 = value; + self + } +} + +impl UpdateResultBuilder +where + St: update_result_state::State, + St::Cid: update_result_state::IsSet, + St::Uri: update_result_state::IsSet, +{ + /// Build the final struct. + pub fn build(self) -> UpdateResult { + UpdateResult { + cid: self._fields.0.unwrap(), + uri: self._fields.1.unwrap(), + validation_status: self._fields.2, + extra_data: Default::default(), + } + } + /// Build the final struct with custom extra_data. + pub fn build_with_data(self, extra_data: BTreeMap>) -> UpdateResult { + UpdateResult { + cid: self._fields.0.unwrap(), + uri: self._fields.1.unwrap(), + validation_status: self._fields.2, + extra_data: Some(extra_data), + } + } +} diff --git a/crates/jacquard-api/src/com_atproto/space/create_record.rs b/crates/jacquard-api/src/com_atproto/space/create_record.rs new file mode 100644 index 000000000..fc7cf90e2 --- /dev/null +++ b/crates/jacquard-api/src/com_atproto/space/create_record.rs @@ -0,0 +1,475 @@ +// @generated by jacquard-lexicon. DO NOT EDIT. +// +// Lexicon: com.atproto.space.createRecord +// +// 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::deps::smol_str::SmolStr; +use jacquard_common::types::aturi::AtSpaceUri; +use jacquard_common::types::string::{AtUri, Cid, Did, Nsid, RecordKey, Rkey}; +use jacquard_common::types::value::Data; +use jacquard_common::{BosStr, CowStr, DefaultStr, FromStaticStr}; +use jacquard_derive::{IntoStatic, open_union}; +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct CreateRecord { + ///The NSID of the record collection. + pub collection: Nsid, + ///The record itself. Must contain a $type field. + pub record: Data, + ///The DID of the repo to write to (the authenticated member). + pub repo: Did, + ///The Record Key. + #[serde(skip_serializing_if = "Option::is_none")] + pub rkey: Option>>, + ///Reference to the space. + pub space: AtSpaceUri, + ///Can be set to 'false' to skip Lexicon schema validation of record data, 'true' to require it, or leave unset to validate only for known Lexicons. + #[serde(skip_serializing_if = "Option::is_none")] + pub validate: Option, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct CreateRecordOutput { + pub cid: Cid, + ///URI of the created record. + pub uri: AtUri, + #[serde(skip_serializing_if = "Option::is_none")] + pub validation_status: Option>, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub enum CreateRecordOutputValidationStatus { + Valid, + Unknown, + Other(S), +} + +impl CreateRecordOutputValidationStatus { + pub fn as_str(&self) -> &str { + match self { + Self::Valid => "valid", + Self::Unknown => "unknown", + 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() { + "valid" => Self::Valid, + "unknown" => Self::Unknown, + _ => Self::Other(s), + } + } +} + +impl core::fmt::Display for CreateRecordOutputValidationStatus { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!(f, "{}", self.as_str()) + } +} + +impl AsRef for CreateRecordOutputValidationStatus { + fn as_ref(&self) -> &str { + self.as_str() + } +} + +impl Serialize for CreateRecordOutputValidationStatus { + 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 CreateRecordOutputValidationStatus { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = S::deserialize(deserializer)?; + Ok(Self::from_value(s)) + } +} + +impl Default for CreateRecordOutputValidationStatus { + fn default() -> Self { + Self::Other(Default::default()) + } +} + +impl jacquard_common::IntoStatic for CreateRecordOutputValidationStatus +where + S: BosStr + jacquard_common::IntoStatic, + S::Output: BosStr, +{ + type Output = CreateRecordOutputValidationStatus; + fn into_static(self) -> Self::Output { + match self { + CreateRecordOutputValidationStatus::Valid => CreateRecordOutputValidationStatus::Valid, + CreateRecordOutputValidationStatus::Unknown => { + CreateRecordOutputValidationStatus::Unknown + } + CreateRecordOutputValidationStatus::Other(v) => { + CreateRecordOutputValidationStatus::Other(v.into_static()) + } + } + } +} + +#[derive( + Serialize, Deserialize, Debug, Clone, PartialEq, Eq, thiserror::Error, miette::Diagnostic, +)] +#[serde(tag = "error", content = "message")] +pub enum CreateRecordError { + #[serde(rename = "SpaceNotFound")] + SpaceNotFound(Option), + /// A record already exists at this collection and rkey. Retry with a different rkey, or use putRecord. + #[serde(rename = "RecordAlreadyExists")] + RecordAlreadyExists(Option), + /// Catch-all for unknown error codes. + #[serde(untagged)] + Other { + error: SmolStr, + message: Option, + }, +} + +impl core::fmt::Display for CreateRecordError { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + match self { + Self::SpaceNotFound(msg) => { + write!(f, "SpaceNotFound")?; + if let Some(msg) = msg { + write!(f, ": {}", msg)?; + } + Ok(()) + } + Self::RecordAlreadyExists(msg) => { + write!(f, "RecordAlreadyExists")?; + if let Some(msg) = msg { + write!(f, ": {}", msg)?; + } + Ok(()) + } + Self::Other { error, message } => { + write!(f, "{}", error)?; + if let Some(msg) = message { + write!(f, ": {}", msg)?; + } + Ok(()) + } + } + } +} + +/** Response marker for the `com.atproto.space.createRecord` procedure. + +Implements `jacquard_common::xrpc::XrpcResp`; successful bodies decode as `Self::Output`, which is `CreateRecordOutput` for this endpoint.*/ +pub struct CreateRecordResponse; +impl jacquard_common::xrpc::XrpcResp for CreateRecordResponse { + const NSID: &'static str = "com.atproto.space.createRecord"; + const ENCODING: &'static str = "application/json"; + type Output = CreateRecordOutput; + type Err = CreateRecordError; +} + +impl jacquard_common::xrpc::XrpcRequest for CreateRecord { + const NSID: &'static str = "com.atproto.space.createRecord"; + const METHOD: jacquard_common::xrpc::XrpcMethod = + jacquard_common::xrpc::XrpcMethod::Procedure("application/json"); + type Response = CreateRecordResponse; +} + +/** Endpoint marker for the `com.atproto.space.createRecord` procedure. + +Path: `/xrpc/com.atproto.space.createRecord`. The request payload type is `CreateRecord`; send that request with `jacquard::Client` or use this marker through lower-level `XrpcEndpoint` APIs.*/ +pub struct CreateRecordRequest; +impl jacquard_common::xrpc::XrpcEndpoint for CreateRecordRequest { + const PATH: &'static str = "/xrpc/com.atproto.space.createRecord"; + const METHOD: jacquard_common::xrpc::XrpcMethod = + jacquard_common::xrpc::XrpcMethod::Procedure("application/json"); + type Request = CreateRecord; + type Response = CreateRecordResponse; +} + +pub mod create_record_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 Collection; + type Record; + type Repo; + type Space; + } + /// Empty state - all required fields are unset + pub struct Empty(()); + impl sealed::Sealed for Empty {} + impl State for Empty { + type Collection = Unset; + type Record = Unset; + type Repo = Unset; + type Space = Unset; + } + ///State transition - sets the `collection` field to Set + pub struct SetCollection(PhantomData St>); + impl sealed::Sealed for SetCollection {} + impl State for SetCollection { + type Collection = Set; + type Record = St::Record; + type Repo = St::Repo; + type Space = St::Space; + } + ///State transition - sets the `record` field to Set + pub struct SetRecord(PhantomData St>); + impl sealed::Sealed for SetRecord {} + impl State for SetRecord { + type Collection = St::Collection; + type Record = Set; + type Repo = St::Repo; + type Space = St::Space; + } + ///State transition - sets the `repo` field to Set + pub struct SetRepo(PhantomData St>); + impl sealed::Sealed for SetRepo {} + impl State for SetRepo { + type Collection = St::Collection; + type Record = St::Record; + type Repo = Set; + type Space = St::Space; + } + ///State transition - sets the `space` field to Set + pub struct SetSpace(PhantomData St>); + impl sealed::Sealed for SetSpace {} + impl State for SetSpace { + type Collection = St::Collection; + type Record = St::Record; + type Repo = St::Repo; + type Space = Set; + } + /// Marker types for field names + #[allow(non_camel_case_types)] + pub mod members { + ///Marker type for the `collection` field + pub struct collection(()); + ///Marker type for the `record` field + pub struct record(()); + ///Marker type for the `repo` field + pub struct repo(()); + ///Marker type for the `space` field + pub struct space(()); + } +} + +/// Builder for constructing an instance of this type. +pub struct CreateRecordBuilder { + _state: PhantomData St>, + _fields: ( + Option>, + Option>, + Option>, + Option>>, + Option>, + Option, + ), + _type: PhantomData S>, +} + +impl CreateRecord { + /// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed + pub fn new() -> CreateRecordBuilder { + CreateRecordBuilder::new() + } +} + +impl CreateRecord { + /// Create a new builder for this type + pub fn builder() -> CreateRecordBuilder { + CreateRecordBuilder::builder() + } +} + +impl CreateRecordBuilder { + /// Create a new builder with all fields unset, using the default string type, if needed + pub fn new() -> Self { + CreateRecordBuilder { + _state: PhantomData, + _fields: (None, None, None, None, None, None), + _type: PhantomData, + } + } +} + +impl CreateRecordBuilder { + /// Create a new builder with all fields unset + pub fn builder() -> Self { + CreateRecordBuilder { + _state: PhantomData, + _fields: (None, None, None, None, None, None), + _type: PhantomData, + } + } +} + +impl CreateRecordBuilder +where + St: create_record_state::State, + St::Collection: create_record_state::IsUnset, +{ + /// Set the `collection` field (required) + pub fn collection( + mut self, + value: impl Into>, + ) -> CreateRecordBuilder, S> { + self._fields.0 = Option::Some(value.into()); + CreateRecordBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl CreateRecordBuilder +where + St: create_record_state::State, + St::Record: create_record_state::IsUnset, +{ + /// Set the `record` field (required) + pub fn record( + mut self, + value: impl Into>, + ) -> CreateRecordBuilder, S> { + self._fields.1 = Option::Some(value.into()); + CreateRecordBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl CreateRecordBuilder +where + St: create_record_state::State, + St::Repo: create_record_state::IsUnset, +{ + /// Set the `repo` field (required) + pub fn repo( + mut self, + value: impl Into>, + ) -> CreateRecordBuilder, S> { + self._fields.2 = Option::Some(value.into()); + CreateRecordBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl CreateRecordBuilder { + /// Set the `rkey` field (optional) + pub fn rkey(mut self, value: impl Into>>>) -> Self { + self._fields.3 = value.into(); + self + } + /// Set the `rkey` field to an Option value (optional) + pub fn maybe_rkey(mut self, value: Option>>) -> Self { + self._fields.3 = value; + self + } +} + +impl CreateRecordBuilder +where + St: create_record_state::State, + St::Space: create_record_state::IsUnset, +{ + /// Set the `space` field (required) + pub fn space( + mut self, + value: impl Into>, + ) -> CreateRecordBuilder, S> { + self._fields.4 = Option::Some(value.into()); + CreateRecordBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl CreateRecordBuilder { + /// Set the `validate` field (optional) + pub fn validate(mut self, value: impl Into>) -> Self { + self._fields.5 = value.into(); + self + } + /// Set the `validate` field to an Option value (optional) + pub fn maybe_validate(mut self, value: Option) -> Self { + self._fields.5 = value; + self + } +} + +impl CreateRecordBuilder +where + St: create_record_state::State, + St::Collection: create_record_state::IsSet, + St::Record: create_record_state::IsSet, + St::Repo: create_record_state::IsSet, + St::Space: create_record_state::IsSet, +{ + /// Build the final struct. + pub fn build(self) -> CreateRecord { + CreateRecord { + collection: self._fields.0.unwrap(), + record: self._fields.1.unwrap(), + repo: self._fields.2.unwrap(), + rkey: self._fields.3, + space: self._fields.4.unwrap(), + validate: self._fields.5, + extra_data: Default::default(), + } + } + /// Build the final struct with custom extra_data. + pub fn build_with_data(self, extra_data: BTreeMap>) -> CreateRecord { + CreateRecord { + collection: self._fields.0.unwrap(), + record: self._fields.1.unwrap(), + repo: self._fields.2.unwrap(), + rkey: self._fields.3, + space: self._fields.4.unwrap(), + validate: self._fields.5, + extra_data: Some(extra_data), + } + } +} diff --git a/crates/jacquard-api/src/com_atproto/space/delete_record.rs b/crates/jacquard-api/src/com_atproto/space/delete_record.rs new file mode 100644 index 000000000..55fa14905 --- /dev/null +++ b/crates/jacquard-api/src/com_atproto/space/delete_record.rs @@ -0,0 +1,341 @@ +// @generated by jacquard-lexicon. DO NOT EDIT. +// +// Lexicon: com.atproto.space.deleteRecord +// +// 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::deps::smol_str::SmolStr; +use jacquard_common::types::aturi::AtSpaceUri; +use jacquard_common::types::string::{Did, Nsid, RecordKey, Rkey}; +use jacquard_common::types::value::Data; +use jacquard_common::{BosStr, CowStr, DefaultStr, FromStaticStr}; +use jacquard_derive::{IntoStatic, open_union}; +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct DeleteRecord { + ///The NSID of the record collection. + pub collection: Nsid, + ///The DID of the repo to delete from (the authenticated member). + pub repo: Did, + ///The Record Key. + pub rkey: RecordKey>, + ///Reference to the space. + pub space: AtSpaceUri, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic, Default)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct DeleteRecordOutput { + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +#[derive( + Serialize, Deserialize, Debug, Clone, PartialEq, Eq, thiserror::Error, miette::Diagnostic, +)] +#[serde(tag = "error", content = "message")] +pub enum DeleteRecordError { + #[serde(rename = "SpaceNotFound")] + SpaceNotFound(Option), + /// Catch-all for unknown error codes. + #[serde(untagged)] + Other { + error: SmolStr, + message: Option, + }, +} + +impl core::fmt::Display for DeleteRecordError { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + match self { + Self::SpaceNotFound(msg) => { + write!(f, "SpaceNotFound")?; + if let Some(msg) = msg { + write!(f, ": {}", msg)?; + } + Ok(()) + } + Self::Other { error, message } => { + write!(f, "{}", error)?; + if let Some(msg) = message { + write!(f, ": {}", msg)?; + } + Ok(()) + } + } + } +} + +/** Response marker for the `com.atproto.space.deleteRecord` procedure. + +Implements `jacquard_common::xrpc::XrpcResp`; successful bodies decode as `Self::Output`, which is `DeleteRecordOutput` for this endpoint.*/ +pub struct DeleteRecordResponse; +impl jacquard_common::xrpc::XrpcResp for DeleteRecordResponse { + const NSID: &'static str = "com.atproto.space.deleteRecord"; + const ENCODING: &'static str = "application/json"; + type Output = DeleteRecordOutput; + type Err = DeleteRecordError; +} + +impl jacquard_common::xrpc::XrpcRequest for DeleteRecord { + const NSID: &'static str = "com.atproto.space.deleteRecord"; + const METHOD: jacquard_common::xrpc::XrpcMethod = + jacquard_common::xrpc::XrpcMethod::Procedure("application/json"); + type Response = DeleteRecordResponse; +} + +/** Endpoint marker for the `com.atproto.space.deleteRecord` procedure. + +Path: `/xrpc/com.atproto.space.deleteRecord`. The request payload type is `DeleteRecord`; send that request with `jacquard::Client` or use this marker through lower-level `XrpcEndpoint` APIs.*/ +pub struct DeleteRecordRequest; +impl jacquard_common::xrpc::XrpcEndpoint for DeleteRecordRequest { + const PATH: &'static str = "/xrpc/com.atproto.space.deleteRecord"; + const METHOD: jacquard_common::xrpc::XrpcMethod = + jacquard_common::xrpc::XrpcMethod::Procedure("application/json"); + type Request = DeleteRecord; + type Response = DeleteRecordResponse; +} + +pub mod delete_record_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 Collection; + type Repo; + type Rkey; + type Space; + } + /// Empty state - all required fields are unset + pub struct Empty(()); + impl sealed::Sealed for Empty {} + impl State for Empty { + type Collection = Unset; + type Repo = Unset; + type Rkey = Unset; + type Space = Unset; + } + ///State transition - sets the `collection` field to Set + pub struct SetCollection(PhantomData St>); + impl sealed::Sealed for SetCollection {} + impl State for SetCollection { + type Collection = Set; + type Repo = St::Repo; + type Rkey = St::Rkey; + type Space = St::Space; + } + ///State transition - sets the `repo` field to Set + pub struct SetRepo(PhantomData St>); + impl sealed::Sealed for SetRepo {} + impl State for SetRepo { + type Collection = St::Collection; + type Repo = Set; + type Rkey = St::Rkey; + type Space = St::Space; + } + ///State transition - sets the `rkey` field to Set + pub struct SetRkey(PhantomData St>); + impl sealed::Sealed for SetRkey {} + impl State for SetRkey { + type Collection = St::Collection; + type Repo = St::Repo; + type Rkey = Set; + type Space = St::Space; + } + ///State transition - sets the `space` field to Set + pub struct SetSpace(PhantomData St>); + impl sealed::Sealed for SetSpace {} + impl State for SetSpace { + type Collection = St::Collection; + type Repo = St::Repo; + type Rkey = St::Rkey; + type Space = Set; + } + /// Marker types for field names + #[allow(non_camel_case_types)] + pub mod members { + ///Marker type for the `collection` field + pub struct collection(()); + ///Marker type for the `repo` field + pub struct repo(()); + ///Marker type for the `rkey` field + pub struct rkey(()); + ///Marker type for the `space` field + pub struct space(()); + } +} + +/// Builder for constructing an instance of this type. +pub struct DeleteRecordBuilder { + _state: PhantomData St>, + _fields: ( + Option>, + Option>, + Option>>, + Option>, + ), + _type: PhantomData S>, +} + +impl DeleteRecord { + /// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed + pub fn new() -> DeleteRecordBuilder { + DeleteRecordBuilder::new() + } +} + +impl DeleteRecord { + /// Create a new builder for this type + pub fn builder() -> DeleteRecordBuilder { + DeleteRecordBuilder::builder() + } +} + +impl DeleteRecordBuilder { + /// Create a new builder with all fields unset, using the default string type, if needed + pub fn new() -> Self { + DeleteRecordBuilder { + _state: PhantomData, + _fields: (None, None, None, None), + _type: PhantomData, + } + } +} + +impl DeleteRecordBuilder { + /// Create a new builder with all fields unset + pub fn builder() -> Self { + DeleteRecordBuilder { + _state: PhantomData, + _fields: (None, None, None, None), + _type: PhantomData, + } + } +} + +impl DeleteRecordBuilder +where + St: delete_record_state::State, + St::Collection: delete_record_state::IsUnset, +{ + /// Set the `collection` field (required) + pub fn collection( + mut self, + value: impl Into>, + ) -> DeleteRecordBuilder, S> { + self._fields.0 = Option::Some(value.into()); + DeleteRecordBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl DeleteRecordBuilder +where + St: delete_record_state::State, + St::Repo: delete_record_state::IsUnset, +{ + /// Set the `repo` field (required) + pub fn repo( + mut self, + value: impl Into>, + ) -> DeleteRecordBuilder, S> { + self._fields.1 = Option::Some(value.into()); + DeleteRecordBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl DeleteRecordBuilder +where + St: delete_record_state::State, + St::Rkey: delete_record_state::IsUnset, +{ + /// Set the `rkey` field (required) + pub fn rkey( + mut self, + value: impl Into>>, + ) -> DeleteRecordBuilder, S> { + self._fields.2 = Option::Some(value.into()); + DeleteRecordBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl DeleteRecordBuilder +where + St: delete_record_state::State, + St::Space: delete_record_state::IsUnset, +{ + /// Set the `space` field (required) + pub fn space( + mut self, + value: impl Into>, + ) -> DeleteRecordBuilder, S> { + self._fields.3 = Option::Some(value.into()); + DeleteRecordBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl DeleteRecordBuilder +where + St: delete_record_state::State, + St::Collection: delete_record_state::IsSet, + St::Repo: delete_record_state::IsSet, + St::Rkey: delete_record_state::IsSet, + St::Space: delete_record_state::IsSet, +{ + /// Build the final struct. + pub fn build(self) -> DeleteRecord { + DeleteRecord { + collection: self._fields.0.unwrap(), + repo: self._fields.1.unwrap(), + rkey: self._fields.2.unwrap(), + space: self._fields.3.unwrap(), + extra_data: Default::default(), + } + } + /// Build the final struct with custom extra_data. + pub fn build_with_data(self, extra_data: BTreeMap>) -> DeleteRecord { + DeleteRecord { + collection: self._fields.0.unwrap(), + repo: self._fields.1.unwrap(), + rkey: self._fields.2.unwrap(), + space: self._fields.3.unwrap(), + extra_data: Some(extra_data), + } + } +} diff --git a/crates/jacquard-api/src/com_atproto/space/get_blob.rs b/crates/jacquard-api/src/com_atproto/space/get_blob.rs new file mode 100644 index 000000000..49d903e50 --- /dev/null +++ b/crates/jacquard-api/src/com_atproto/space/get_blob.rs @@ -0,0 +1,340 @@ +// @generated by jacquard-lexicon. DO NOT EDIT. +// +// Lexicon: com.atproto.space.getBlob +// +// 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::deps::bytes::Bytes; +use jacquard_common::deps::smol_str::SmolStr; +use jacquard_common::types::aturi::AtSpaceUri; +use jacquard_common::types::string::{Cid, Did}; +use jacquard_common::types::value::Data; +use jacquard_common::{BosStr, CowStr, DefaultStr, FromStaticStr}; +use jacquard_derive::{IntoStatic, open_union}; +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct GetBlob { + pub cid: Cid, + pub repo: Did, + pub space: AtSpaceUri, +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde(rename_all = "camelCase")] +pub struct GetBlobOutput { + pub body: Bytes, +} + +#[derive( + Serialize, Deserialize, Debug, Clone, PartialEq, Eq, thiserror::Error, miette::Diagnostic, +)] +#[serde(tag = "error", content = "message")] +pub enum GetBlobError { + #[serde(rename = "BlobNotFound")] + BlobNotFound(Option), + #[serde(rename = "SpaceNotFound")] + SpaceNotFound(Option), + #[serde(rename = "RepoNotFound")] + RepoNotFound(Option), + #[serde(rename = "RepoTakendown")] + RepoTakendown(Option), + #[serde(rename = "RepoSuspended")] + RepoSuspended(Option), + #[serde(rename = "RepoDeactivated")] + RepoDeactivated(Option), + /// Catch-all for unknown error codes. + #[serde(untagged)] + Other { + error: SmolStr, + message: Option, + }, +} + +impl core::fmt::Display for GetBlobError { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + match self { + Self::BlobNotFound(msg) => { + write!(f, "BlobNotFound")?; + if let Some(msg) = msg { + write!(f, ": {}", msg)?; + } + Ok(()) + } + Self::SpaceNotFound(msg) => { + write!(f, "SpaceNotFound")?; + if let Some(msg) = msg { + write!(f, ": {}", msg)?; + } + Ok(()) + } + Self::RepoNotFound(msg) => { + write!(f, "RepoNotFound")?; + if let Some(msg) = msg { + write!(f, ": {}", msg)?; + } + Ok(()) + } + Self::RepoTakendown(msg) => { + write!(f, "RepoTakendown")?; + if let Some(msg) = msg { + write!(f, ": {}", msg)?; + } + Ok(()) + } + Self::RepoSuspended(msg) => { + write!(f, "RepoSuspended")?; + if let Some(msg) = msg { + write!(f, ": {}", msg)?; + } + Ok(()) + } + Self::RepoDeactivated(msg) => { + write!(f, "RepoDeactivated")?; + if let Some(msg) = msg { + write!(f, ": {}", msg)?; + } + Ok(()) + } + Self::Other { error, message } => { + write!(f, "{}", error)?; + if let Some(msg) = message { + write!(f, ": {}", msg)?; + } + Ok(()) + } + } + } +} + +/** Response marker for the `com.atproto.space.getBlob` query. + +Implements `jacquard_common::xrpc::XrpcResp`; successful bodies decode as `Self::Output`, which is `GetBlobOutput` for this endpoint.*/ +pub struct GetBlobResponse; +impl jacquard_common::xrpc::XrpcResp for GetBlobResponse { + const NSID: &'static str = "com.atproto.space.getBlob"; + const ENCODING: &'static str = "*/*"; + type Output = GetBlobOutput; + type Err = GetBlobError; + fn encode_output( + output: &Self::Output, + ) -> Result, jacquard_common::xrpc::EncodeError> + where + Self::Output: Serialize, + { + Ok(output.body.to_vec()) + } + fn decode_output<'de, S>( + body: &'de [u8], + ) -> Result, jacquard_common::error::DecodeError> + where + S: BosStr + Deserialize<'de>, + Self::Output: Deserialize<'de>, + { + Ok(GetBlobOutput { + body: jacquard_common::deps::bytes::Bytes::copy_from_slice(body), + }) + } +} + +impl jacquard_common::xrpc::XrpcRequest for GetBlob { + const NSID: &'static str = "com.atproto.space.getBlob"; + const METHOD: jacquard_common::xrpc::XrpcMethod = jacquard_common::xrpc::XrpcMethod::Query; + type Response = GetBlobResponse; +} + +/** Endpoint marker for the `com.atproto.space.getBlob` query. + +Path: `/xrpc/com.atproto.space.getBlob`. The request payload type is `GetBlob`; send that request with `jacquard::Client` or use this marker through lower-level `XrpcEndpoint` APIs.*/ +pub struct GetBlobRequest; +impl jacquard_common::xrpc::XrpcEndpoint for GetBlobRequest { + const PATH: &'static str = "/xrpc/com.atproto.space.getBlob"; + const METHOD: jacquard_common::xrpc::XrpcMethod = jacquard_common::xrpc::XrpcMethod::Query; + type Request = GetBlob; + type Response = GetBlobResponse; +} + +pub mod get_blob_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 Cid; + type Repo; + type Space; + } + /// Empty state - all required fields are unset + pub struct Empty(()); + impl sealed::Sealed for Empty {} + impl State for Empty { + type Cid = Unset; + type Repo = Unset; + type Space = Unset; + } + ///State transition - sets the `cid` field to Set + pub struct SetCid(PhantomData St>); + impl sealed::Sealed for SetCid {} + impl State for SetCid { + type Cid = Set; + type Repo = St::Repo; + type Space = St::Space; + } + ///State transition - sets the `repo` field to Set + pub struct SetRepo(PhantomData St>); + impl sealed::Sealed for SetRepo {} + impl State for SetRepo { + type Cid = St::Cid; + type Repo = Set; + type Space = St::Space; + } + ///State transition - sets the `space` field to Set + pub struct SetSpace(PhantomData St>); + impl sealed::Sealed for SetSpace {} + impl State for SetSpace { + type Cid = St::Cid; + type Repo = St::Repo; + type Space = Set; + } + /// Marker types for field names + #[allow(non_camel_case_types)] + pub mod members { + ///Marker type for the `cid` field + pub struct cid(()); + ///Marker type for the `repo` field + pub struct repo(()); + ///Marker type for the `space` field + pub struct space(()); + } +} + +/// Builder for constructing an instance of this type. +pub struct GetBlobBuilder { + _state: PhantomData St>, + _fields: (Option>, Option>, Option>), + _type: PhantomData S>, +} + +impl GetBlob { + /// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed + pub fn new() -> GetBlobBuilder { + GetBlobBuilder::new() + } +} + +impl GetBlob { + /// Create a new builder for this type + pub fn builder() -> GetBlobBuilder { + GetBlobBuilder::builder() + } +} + +impl GetBlobBuilder { + /// Create a new builder with all fields unset, using the default string type, if needed + pub fn new() -> Self { + GetBlobBuilder { + _state: PhantomData, + _fields: (None, None, None), + _type: PhantomData, + } + } +} + +impl GetBlobBuilder { + /// Create a new builder with all fields unset + pub fn builder() -> Self { + GetBlobBuilder { + _state: PhantomData, + _fields: (None, None, None), + _type: PhantomData, + } + } +} + +impl GetBlobBuilder +where + St: get_blob_state::State, + St::Cid: get_blob_state::IsUnset, +{ + /// Set the `cid` field (required) + pub fn cid( + mut self, + value: impl Into>, + ) -> GetBlobBuilder, S> { + self._fields.0 = Option::Some(value.into()); + GetBlobBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl GetBlobBuilder +where + St: get_blob_state::State, + St::Repo: get_blob_state::IsUnset, +{ + /// Set the `repo` field (required) + pub fn repo( + mut self, + value: impl Into>, + ) -> GetBlobBuilder, S> { + self._fields.1 = Option::Some(value.into()); + GetBlobBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl GetBlobBuilder +where + St: get_blob_state::State, + St::Space: get_blob_state::IsUnset, +{ + /// Set the `space` field (required) + pub fn space( + mut self, + value: impl Into>, + ) -> GetBlobBuilder, S> { + self._fields.2 = Option::Some(value.into()); + GetBlobBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl GetBlobBuilder +where + St: get_blob_state::State, + St::Cid: get_blob_state::IsSet, + St::Repo: get_blob_state::IsSet, + St::Space: get_blob_state::IsSet, +{ + /// Build the final struct. + pub fn build(self) -> GetBlob { + GetBlob { + cid: self._fields.0.unwrap(), + repo: self._fields.1.unwrap(), + space: self._fields.2.unwrap(), + } + } +} diff --git a/crates/jacquard-api/src/com_atproto/space/get_delegation_token.rs b/crates/jacquard-api/src/com_atproto/space/get_delegation_token.rs new file mode 100644 index 000000000..a14a1d58b --- /dev/null +++ b/crates/jacquard-api/src/com_atproto/space/get_delegation_token.rs @@ -0,0 +1,175 @@ +// @generated by jacquard-lexicon. DO NOT EDIT. +// +// Lexicon: com.atproto.space.getDelegationToken +// +// 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::deps::smol_str::SmolStr; +use jacquard_common::types::aturi::AtSpaceUri; +use jacquard_common::types::value::Data; +use jacquard_common::{BosStr, CowStr, DefaultStr, FromStaticStr}; +use jacquard_derive::IntoStatic; +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct GetDelegationToken { + pub space: AtSpaceUri, +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic, Default)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct GetDelegationTokenOutput { + ///A signed JWT delegation token. + pub token: S, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +/** Response marker for the `com.atproto.space.getDelegationToken` query. + +Implements `jacquard_common::xrpc::XrpcResp`; successful bodies decode as `Self::Output`, which is `GetDelegationTokenOutput` for this endpoint.*/ +pub struct GetDelegationTokenResponse; +impl jacquard_common::xrpc::XrpcResp for GetDelegationTokenResponse { + const NSID: &'static str = "com.atproto.space.getDelegationToken"; + const ENCODING: &'static str = "application/json"; + type Output = GetDelegationTokenOutput; + type Err = jacquard_common::xrpc::GenericError; +} + +impl jacquard_common::xrpc::XrpcRequest for GetDelegationToken { + const NSID: &'static str = "com.atproto.space.getDelegationToken"; + const METHOD: jacquard_common::xrpc::XrpcMethod = jacquard_common::xrpc::XrpcMethod::Query; + type Response = GetDelegationTokenResponse; +} + +/** Endpoint marker for the `com.atproto.space.getDelegationToken` query. + +Path: `/xrpc/com.atproto.space.getDelegationToken`. The request payload type is `GetDelegationToken`; send that request with `jacquard::Client` or use this marker through lower-level `XrpcEndpoint` APIs.*/ +pub struct GetDelegationTokenRequest; +impl jacquard_common::xrpc::XrpcEndpoint for GetDelegationTokenRequest { + const PATH: &'static str = "/xrpc/com.atproto.space.getDelegationToken"; + const METHOD: jacquard_common::xrpc::XrpcMethod = jacquard_common::xrpc::XrpcMethod::Query; + type Request = GetDelegationToken; + type Response = GetDelegationTokenResponse; +} + +pub mod get_delegation_token_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 Space; + } + /// Empty state - all required fields are unset + pub struct Empty(()); + impl sealed::Sealed for Empty {} + impl State for Empty { + type Space = Unset; + } + ///State transition - sets the `space` field to Set + pub struct SetSpace(PhantomData St>); + impl sealed::Sealed for SetSpace {} + impl State for SetSpace { + type Space = Set; + } + /// Marker types for field names + #[allow(non_camel_case_types)] + pub mod members { + ///Marker type for the `space` field + pub struct space(()); + } +} + +/// Builder for constructing an instance of this type. +pub struct GetDelegationTokenBuilder +{ + _state: PhantomData St>, + _fields: (Option>,), + _type: PhantomData S>, +} + +impl GetDelegationToken { + /// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed + pub fn new() -> GetDelegationTokenBuilder { + GetDelegationTokenBuilder::new() + } +} + +impl GetDelegationToken { + /// Create a new builder for this type + pub fn builder() -> GetDelegationTokenBuilder { + GetDelegationTokenBuilder::builder() + } +} + +impl GetDelegationTokenBuilder { + /// Create a new builder with all fields unset, using the default string type, if needed + pub fn new() -> Self { + GetDelegationTokenBuilder { + _state: PhantomData, + _fields: (None,), + _type: PhantomData, + } + } +} + +impl GetDelegationTokenBuilder { + /// Create a new builder with all fields unset + pub fn builder() -> Self { + GetDelegationTokenBuilder { + _state: PhantomData, + _fields: (None,), + _type: PhantomData, + } + } +} + +impl GetDelegationTokenBuilder +where + St: get_delegation_token_state::State, + St::Space: get_delegation_token_state::IsUnset, +{ + /// Set the `space` field (required) + pub fn space( + mut self, + value: impl Into>, + ) -> GetDelegationTokenBuilder, S> { + self._fields.0 = Option::Some(value.into()); + GetDelegationTokenBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl GetDelegationTokenBuilder +where + St: get_delegation_token_state::State, + St::Space: get_delegation_token_state::IsSet, +{ + /// Build the final struct. + pub fn build(self) -> GetDelegationToken { + GetDelegationToken { + space: self._fields.0.unwrap(), + } + } +} diff --git a/crates/jacquard-api/src/com_atproto/space/get_latest_commit.rs b/crates/jacquard-api/src/com_atproto/space/get_latest_commit.rs new file mode 100644 index 000000000..eba797222 --- /dev/null +++ b/crates/jacquard-api/src/com_atproto/space/get_latest_commit.rs @@ -0,0 +1,282 @@ +// @generated by jacquard-lexicon. DO NOT EDIT. +// +// Lexicon: com.atproto.space.getLatestCommit +// +// 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; + +use crate::com_atproto::space::SignedCommit; +#[allow(unused_imports)] +use core::marker::PhantomData; +use jacquard_common::deps::smol_str::SmolStr; +use jacquard_common::types::aturi::AtSpaceUri; +use jacquard_common::types::string::Did; +use jacquard_common::types::value::Data; +use jacquard_common::{BosStr, CowStr, DefaultStr, FromStaticStr}; +use jacquard_derive::{IntoStatic, open_union}; +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct GetLatestCommit { + pub repo: Did, + pub space: AtSpaceUri, +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct GetLatestCommitOutput { + ///The account's current signed commit. + pub commit: SignedCommit, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +#[derive( + Serialize, Deserialize, Debug, Clone, PartialEq, Eq, thiserror::Error, miette::Diagnostic, +)] +#[serde(tag = "error", content = "message")] +pub enum GetLatestCommitError { + #[serde(rename = "SpaceNotFound")] + SpaceNotFound(Option), + #[serde(rename = "RepoNotFound")] + RepoNotFound(Option), + #[serde(rename = "RepoTakendown")] + RepoTakendown(Option), + #[serde(rename = "RepoSuspended")] + RepoSuspended(Option), + #[serde(rename = "RepoDeactivated")] + RepoDeactivated(Option), + /// Catch-all for unknown error codes. + #[serde(untagged)] + Other { + error: SmolStr, + message: Option, + }, +} + +impl core::fmt::Display for GetLatestCommitError { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + match self { + Self::SpaceNotFound(msg) => { + write!(f, "SpaceNotFound")?; + if let Some(msg) = msg { + write!(f, ": {}", msg)?; + } + Ok(()) + } + Self::RepoNotFound(msg) => { + write!(f, "RepoNotFound")?; + if let Some(msg) = msg { + write!(f, ": {}", msg)?; + } + Ok(()) + } + Self::RepoTakendown(msg) => { + write!(f, "RepoTakendown")?; + if let Some(msg) = msg { + write!(f, ": {}", msg)?; + } + Ok(()) + } + Self::RepoSuspended(msg) => { + write!(f, "RepoSuspended")?; + if let Some(msg) = msg { + write!(f, ": {}", msg)?; + } + Ok(()) + } + Self::RepoDeactivated(msg) => { + write!(f, "RepoDeactivated")?; + if let Some(msg) = msg { + write!(f, ": {}", msg)?; + } + Ok(()) + } + Self::Other { error, message } => { + write!(f, "{}", error)?; + if let Some(msg) = message { + write!(f, ": {}", msg)?; + } + Ok(()) + } + } + } +} + +/** Response marker for the `com.atproto.space.getLatestCommit` query. + +Implements `jacquard_common::xrpc::XrpcResp`; successful bodies decode as `Self::Output`, which is `GetLatestCommitOutput` for this endpoint.*/ +pub struct GetLatestCommitResponse; +impl jacquard_common::xrpc::XrpcResp for GetLatestCommitResponse { + const NSID: &'static str = "com.atproto.space.getLatestCommit"; + const ENCODING: &'static str = "application/json"; + type Output = GetLatestCommitOutput; + type Err = GetLatestCommitError; +} + +impl jacquard_common::xrpc::XrpcRequest for GetLatestCommit { + const NSID: &'static str = "com.atproto.space.getLatestCommit"; + const METHOD: jacquard_common::xrpc::XrpcMethod = jacquard_common::xrpc::XrpcMethod::Query; + type Response = GetLatestCommitResponse; +} + +/** Endpoint marker for the `com.atproto.space.getLatestCommit` query. + +Path: `/xrpc/com.atproto.space.getLatestCommit`. The request payload type is `GetLatestCommit`; send that request with `jacquard::Client` or use this marker through lower-level `XrpcEndpoint` APIs.*/ +pub struct GetLatestCommitRequest; +impl jacquard_common::xrpc::XrpcEndpoint for GetLatestCommitRequest { + const PATH: &'static str = "/xrpc/com.atproto.space.getLatestCommit"; + const METHOD: jacquard_common::xrpc::XrpcMethod = jacquard_common::xrpc::XrpcMethod::Query; + type Request = GetLatestCommit; + type Response = GetLatestCommitResponse; +} + +pub mod get_latest_commit_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 Repo; + type Space; + } + /// Empty state - all required fields are unset + pub struct Empty(()); + impl sealed::Sealed for Empty {} + impl State for Empty { + type Repo = Unset; + type Space = Unset; + } + ///State transition - sets the `repo` field to Set + pub struct SetRepo(PhantomData St>); + impl sealed::Sealed for SetRepo {} + impl State for SetRepo { + type Repo = Set; + type Space = St::Space; + } + ///State transition - sets the `space` field to Set + pub struct SetSpace(PhantomData St>); + impl sealed::Sealed for SetSpace {} + impl State for SetSpace { + type Repo = St::Repo; + type Space = Set; + } + /// Marker types for field names + #[allow(non_camel_case_types)] + pub mod members { + ///Marker type for the `repo` field + pub struct repo(()); + ///Marker type for the `space` field + pub struct space(()); + } +} + +/// Builder for constructing an instance of this type. +pub struct GetLatestCommitBuilder { + _state: PhantomData St>, + _fields: (Option>, Option>), + _type: PhantomData S>, +} + +impl GetLatestCommit { + /// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed + pub fn new() -> GetLatestCommitBuilder { + GetLatestCommitBuilder::new() + } +} + +impl GetLatestCommit { + /// Create a new builder for this type + pub fn builder() -> GetLatestCommitBuilder { + GetLatestCommitBuilder::builder() + } +} + +impl GetLatestCommitBuilder { + /// Create a new builder with all fields unset, using the default string type, if needed + pub fn new() -> Self { + GetLatestCommitBuilder { + _state: PhantomData, + _fields: (None, None), + _type: PhantomData, + } + } +} + +impl GetLatestCommitBuilder { + /// Create a new builder with all fields unset + pub fn builder() -> Self { + GetLatestCommitBuilder { + _state: PhantomData, + _fields: (None, None), + _type: PhantomData, + } + } +} + +impl GetLatestCommitBuilder +where + St: get_latest_commit_state::State, + St::Repo: get_latest_commit_state::IsUnset, +{ + /// Set the `repo` field (required) + pub fn repo( + mut self, + value: impl Into>, + ) -> GetLatestCommitBuilder, S> { + self._fields.0 = Option::Some(value.into()); + GetLatestCommitBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl GetLatestCommitBuilder +where + St: get_latest_commit_state::State, + St::Space: get_latest_commit_state::IsUnset, +{ + /// Set the `space` field (required) + pub fn space( + mut self, + value: impl Into>, + ) -> GetLatestCommitBuilder, S> { + self._fields.1 = Option::Some(value.into()); + GetLatestCommitBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl GetLatestCommitBuilder +where + St: get_latest_commit_state::State, + St::Repo: get_latest_commit_state::IsSet, + St::Space: get_latest_commit_state::IsSet, +{ + /// Build the final struct. + pub fn build(self) -> GetLatestCommit { + GetLatestCommit { + repo: self._fields.0.unwrap(), + space: self._fields.1.unwrap(), + } + } +} diff --git a/crates/jacquard-api/src/com_atproto/space/get_record.rs b/crates/jacquard-api/src/com_atproto/space/get_record.rs new file mode 100644 index 000000000..41d4b9de9 --- /dev/null +++ b/crates/jacquard-api/src/com_atproto/space/get_record.rs @@ -0,0 +1,370 @@ +// @generated by jacquard-lexicon. DO NOT EDIT. +// +// Lexicon: com.atproto.space.getRecord +// +// 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::deps::smol_str::SmolStr; +use jacquard_common::types::aturi::AtSpaceUri; +use jacquard_common::types::string::{AtUri, Cid, Did, Nsid, RecordKey, Rkey}; +use jacquard_common::types::value::Data; +use jacquard_common::{BosStr, CowStr, DefaultStr, FromStaticStr}; +use jacquard_derive::{IntoStatic, open_union}; +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct GetRecord { + pub collection: Nsid, + pub repo: Did, + pub rkey: RecordKey>, + pub space: AtSpaceUri, +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct GetRecordOutput { + pub cid: Cid, + pub uri: AtUri, + pub value: Data, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +#[derive( + Serialize, Deserialize, Debug, Clone, PartialEq, Eq, thiserror::Error, miette::Diagnostic, +)] +#[serde(tag = "error", content = "message")] +pub enum GetRecordError { + #[serde(rename = "RecordNotFound")] + RecordNotFound(Option), + #[serde(rename = "SpaceNotFound")] + SpaceNotFound(Option), + #[serde(rename = "RepoNotFound")] + RepoNotFound(Option), + #[serde(rename = "RepoTakendown")] + RepoTakendown(Option), + #[serde(rename = "RepoSuspended")] + RepoSuspended(Option), + #[serde(rename = "RepoDeactivated")] + RepoDeactivated(Option), + /// Catch-all for unknown error codes. + #[serde(untagged)] + Other { + error: SmolStr, + message: Option, + }, +} + +impl core::fmt::Display for GetRecordError { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + match self { + Self::RecordNotFound(msg) => { + write!(f, "RecordNotFound")?; + if let Some(msg) = msg { + write!(f, ": {}", msg)?; + } + Ok(()) + } + Self::SpaceNotFound(msg) => { + write!(f, "SpaceNotFound")?; + if let Some(msg) = msg { + write!(f, ": {}", msg)?; + } + Ok(()) + } + Self::RepoNotFound(msg) => { + write!(f, "RepoNotFound")?; + if let Some(msg) = msg { + write!(f, ": {}", msg)?; + } + Ok(()) + } + Self::RepoTakendown(msg) => { + write!(f, "RepoTakendown")?; + if let Some(msg) = msg { + write!(f, ": {}", msg)?; + } + Ok(()) + } + Self::RepoSuspended(msg) => { + write!(f, "RepoSuspended")?; + if let Some(msg) = msg { + write!(f, ": {}", msg)?; + } + Ok(()) + } + Self::RepoDeactivated(msg) => { + write!(f, "RepoDeactivated")?; + if let Some(msg) = msg { + write!(f, ": {}", msg)?; + } + Ok(()) + } + Self::Other { error, message } => { + write!(f, "{}", error)?; + if let Some(msg) = message { + write!(f, ": {}", msg)?; + } + Ok(()) + } + } + } +} + +/** Response marker for the `com.atproto.space.getRecord` query. + +Implements `jacquard_common::xrpc::XrpcResp`; successful bodies decode as `Self::Output`, which is `GetRecordOutput` for this endpoint.*/ +pub struct GetRecordResponse; +impl jacquard_common::xrpc::XrpcResp for GetRecordResponse { + const NSID: &'static str = "com.atproto.space.getRecord"; + const ENCODING: &'static str = "application/json"; + type Output = GetRecordOutput; + type Err = GetRecordError; +} + +impl jacquard_common::xrpc::XrpcRequest for GetRecord { + const NSID: &'static str = "com.atproto.space.getRecord"; + const METHOD: jacquard_common::xrpc::XrpcMethod = jacquard_common::xrpc::XrpcMethod::Query; + type Response = GetRecordResponse; +} + +/** Endpoint marker for the `com.atproto.space.getRecord` query. + +Path: `/xrpc/com.atproto.space.getRecord`. The request payload type is `GetRecord`; send that request with `jacquard::Client` or use this marker through lower-level `XrpcEndpoint` APIs.*/ +pub struct GetRecordRequest; +impl jacquard_common::xrpc::XrpcEndpoint for GetRecordRequest { + const PATH: &'static str = "/xrpc/com.atproto.space.getRecord"; + const METHOD: jacquard_common::xrpc::XrpcMethod = jacquard_common::xrpc::XrpcMethod::Query; + type Request = GetRecord; + type Response = GetRecordResponse; +} + +pub mod get_record_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 Collection; + type Repo; + type Rkey; + type Space; + } + /// Empty state - all required fields are unset + pub struct Empty(()); + impl sealed::Sealed for Empty {} + impl State for Empty { + type Collection = Unset; + type Repo = Unset; + type Rkey = Unset; + type Space = Unset; + } + ///State transition - sets the `collection` field to Set + pub struct SetCollection(PhantomData St>); + impl sealed::Sealed for SetCollection {} + impl State for SetCollection { + type Collection = Set; + type Repo = St::Repo; + type Rkey = St::Rkey; + type Space = St::Space; + } + ///State transition - sets the `repo` field to Set + pub struct SetRepo(PhantomData St>); + impl sealed::Sealed for SetRepo {} + impl State for SetRepo { + type Collection = St::Collection; + type Repo = Set; + type Rkey = St::Rkey; + type Space = St::Space; + } + ///State transition - sets the `rkey` field to Set + pub struct SetRkey(PhantomData St>); + impl sealed::Sealed for SetRkey {} + impl State for SetRkey { + type Collection = St::Collection; + type Repo = St::Repo; + type Rkey = Set; + type Space = St::Space; + } + ///State transition - sets the `space` field to Set + pub struct SetSpace(PhantomData St>); + impl sealed::Sealed for SetSpace {} + impl State for SetSpace { + type Collection = St::Collection; + type Repo = St::Repo; + type Rkey = St::Rkey; + type Space = Set; + } + /// Marker types for field names + #[allow(non_camel_case_types)] + pub mod members { + ///Marker type for the `collection` field + pub struct collection(()); + ///Marker type for the `repo` field + pub struct repo(()); + ///Marker type for the `rkey` field + pub struct rkey(()); + ///Marker type for the `space` field + pub struct space(()); + } +} + +/// Builder for constructing an instance of this type. +pub struct GetRecordBuilder { + _state: PhantomData St>, + _fields: ( + Option>, + Option>, + Option>>, + Option>, + ), + _type: PhantomData S>, +} + +impl GetRecord { + /// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed + pub fn new() -> GetRecordBuilder { + GetRecordBuilder::new() + } +} + +impl GetRecord { + /// Create a new builder for this type + pub fn builder() -> GetRecordBuilder { + GetRecordBuilder::builder() + } +} + +impl GetRecordBuilder { + /// Create a new builder with all fields unset, using the default string type, if needed + pub fn new() -> Self { + GetRecordBuilder { + _state: PhantomData, + _fields: (None, None, None, None), + _type: PhantomData, + } + } +} + +impl GetRecordBuilder { + /// Create a new builder with all fields unset + pub fn builder() -> Self { + GetRecordBuilder { + _state: PhantomData, + _fields: (None, None, None, None), + _type: PhantomData, + } + } +} + +impl GetRecordBuilder +where + St: get_record_state::State, + St::Collection: get_record_state::IsUnset, +{ + /// Set the `collection` field (required) + pub fn collection( + mut self, + value: impl Into>, + ) -> GetRecordBuilder, S> { + self._fields.0 = Option::Some(value.into()); + GetRecordBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl GetRecordBuilder +where + St: get_record_state::State, + St::Repo: get_record_state::IsUnset, +{ + /// Set the `repo` field (required) + pub fn repo( + mut self, + value: impl Into>, + ) -> GetRecordBuilder, S> { + self._fields.1 = Option::Some(value.into()); + GetRecordBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl GetRecordBuilder +where + St: get_record_state::State, + St::Rkey: get_record_state::IsUnset, +{ + /// Set the `rkey` field (required) + pub fn rkey( + mut self, + value: impl Into>>, + ) -> GetRecordBuilder, S> { + self._fields.2 = Option::Some(value.into()); + GetRecordBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl GetRecordBuilder +where + St: get_record_state::State, + St::Space: get_record_state::IsUnset, +{ + /// Set the `space` field (required) + pub fn space( + mut self, + value: impl Into>, + ) -> GetRecordBuilder, S> { + self._fields.3 = Option::Some(value.into()); + GetRecordBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl GetRecordBuilder +where + St: get_record_state::State, + St::Collection: get_record_state::IsSet, + St::Repo: get_record_state::IsSet, + St::Rkey: get_record_state::IsSet, + St::Space: get_record_state::IsSet, +{ + /// Build the final struct. + pub fn build(self) -> GetRecord { + GetRecord { + collection: self._fields.0.unwrap(), + repo: self._fields.1.unwrap(), + rkey: self._fields.2.unwrap(), + space: self._fields.3.unwrap(), + } + } +} diff --git a/crates/jacquard-api/src/com_atproto/space/get_repo.rs b/crates/jacquard-api/src/com_atproto/space/get_repo.rs new file mode 100644 index 000000000..504ca08a7 --- /dev/null +++ b/crates/jacquard-api/src/com_atproto/space/get_repo.rs @@ -0,0 +1,317 @@ +// @generated by jacquard-lexicon. DO NOT EDIT. +// +// Lexicon: com.atproto.space.getRepo +// +// 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::deps::bytes::Bytes; +use jacquard_common::deps::smol_str::SmolStr; +use jacquard_common::types::aturi::AtSpaceUri; +use jacquard_common::types::string::Did; +use jacquard_common::types::value::Data; +use jacquard_common::{BosStr, CowStr, DefaultStr, FromStaticStr}; +use jacquard_derive::{IntoStatic, open_union}; +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct GetRepo { + /// Defaults to `false`. + #[serde(default = "_default_exclude_values")] + #[serde(skip_serializing_if = "Option::is_none")] + pub exclude_values: Option, + pub repo: Did, + pub space: AtSpaceUri, +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde(rename_all = "camelCase")] +pub struct GetRepoOutput { + pub body: Bytes, +} + +#[derive( + Serialize, Deserialize, Debug, Clone, PartialEq, Eq, thiserror::Error, miette::Diagnostic, +)] +#[serde(tag = "error", content = "message")] +pub enum GetRepoError { + #[serde(rename = "SpaceNotFound")] + SpaceNotFound(Option), + #[serde(rename = "RepoNotFound")] + RepoNotFound(Option), + #[serde(rename = "RepoTakendown")] + RepoTakendown(Option), + #[serde(rename = "RepoSuspended")] + RepoSuspended(Option), + #[serde(rename = "RepoDeactivated")] + RepoDeactivated(Option), + /// Catch-all for unknown error codes. + #[serde(untagged)] + Other { + error: SmolStr, + message: Option, + }, +} + +impl core::fmt::Display for GetRepoError { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + match self { + Self::SpaceNotFound(msg) => { + write!(f, "SpaceNotFound")?; + if let Some(msg) = msg { + write!(f, ": {}", msg)?; + } + Ok(()) + } + Self::RepoNotFound(msg) => { + write!(f, "RepoNotFound")?; + if let Some(msg) = msg { + write!(f, ": {}", msg)?; + } + Ok(()) + } + Self::RepoTakendown(msg) => { + write!(f, "RepoTakendown")?; + if let Some(msg) = msg { + write!(f, ": {}", msg)?; + } + Ok(()) + } + Self::RepoSuspended(msg) => { + write!(f, "RepoSuspended")?; + if let Some(msg) = msg { + write!(f, ": {}", msg)?; + } + Ok(()) + } + Self::RepoDeactivated(msg) => { + write!(f, "RepoDeactivated")?; + if let Some(msg) = msg { + write!(f, ": {}", msg)?; + } + Ok(()) + } + Self::Other { error, message } => { + write!(f, "{}", error)?; + if let Some(msg) = message { + write!(f, ": {}", msg)?; + } + Ok(()) + } + } + } +} + +/** Response marker for the `com.atproto.space.getRepo` query. + +Implements `jacquard_common::xrpc::XrpcResp`; successful bodies decode as `Self::Output`, which is `GetRepoOutput` for this endpoint.*/ +pub struct GetRepoResponse; +impl jacquard_common::xrpc::XrpcResp for GetRepoResponse { + const NSID: &'static str = "com.atproto.space.getRepo"; + const ENCODING: &'static str = "application/vnd.ipld.car"; + type Output = GetRepoOutput; + type Err = GetRepoError; + fn encode_output( + output: &Self::Output, + ) -> Result, jacquard_common::xrpc::EncodeError> + where + Self::Output: Serialize, + { + Ok(output.body.to_vec()) + } + fn decode_output<'de, S>( + body: &'de [u8], + ) -> Result, jacquard_common::error::DecodeError> + where + S: BosStr + Deserialize<'de>, + Self::Output: Deserialize<'de>, + { + Ok(GetRepoOutput { + body: jacquard_common::deps::bytes::Bytes::copy_from_slice(body), + }) + } +} + +impl jacquard_common::xrpc::XrpcRequest for GetRepo { + const NSID: &'static str = "com.atproto.space.getRepo"; + const METHOD: jacquard_common::xrpc::XrpcMethod = jacquard_common::xrpc::XrpcMethod::Query; + type Response = GetRepoResponse; +} + +/** Endpoint marker for the `com.atproto.space.getRepo` query. + +Path: `/xrpc/com.atproto.space.getRepo`. The request payload type is `GetRepo`; send that request with `jacquard::Client` or use this marker through lower-level `XrpcEndpoint` APIs.*/ +pub struct GetRepoRequest; +impl jacquard_common::xrpc::XrpcEndpoint for GetRepoRequest { + const PATH: &'static str = "/xrpc/com.atproto.space.getRepo"; + const METHOD: jacquard_common::xrpc::XrpcMethod = jacquard_common::xrpc::XrpcMethod::Query; + type Request = GetRepo; + type Response = GetRepoResponse; +} + +fn _default_exclude_values() -> Option { + Some(false) +} + +pub mod get_repo_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 Repo; + type Space; + } + /// Empty state - all required fields are unset + pub struct Empty(()); + impl sealed::Sealed for Empty {} + impl State for Empty { + type Repo = Unset; + type Space = Unset; + } + ///State transition - sets the `repo` field to Set + pub struct SetRepo(PhantomData St>); + impl sealed::Sealed for SetRepo {} + impl State for SetRepo { + type Repo = Set; + type Space = St::Space; + } + ///State transition - sets the `space` field to Set + pub struct SetSpace(PhantomData St>); + impl sealed::Sealed for SetSpace {} + impl State for SetSpace { + type Repo = St::Repo; + type Space = Set; + } + /// Marker types for field names + #[allow(non_camel_case_types)] + pub mod members { + ///Marker type for the `repo` field + pub struct repo(()); + ///Marker type for the `space` field + pub struct space(()); + } +} + +/// Builder for constructing an instance of this type. +pub struct GetRepoBuilder { + _state: PhantomData St>, + _fields: (Option, Option>, Option>), + _type: PhantomData S>, +} + +impl GetRepo { + /// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed + pub fn new() -> GetRepoBuilder { + GetRepoBuilder::new() + } +} + +impl GetRepo { + /// Create a new builder for this type + pub fn builder() -> GetRepoBuilder { + GetRepoBuilder::builder() + } +} + +impl GetRepoBuilder { + /// Create a new builder with all fields unset, using the default string type, if needed + pub fn new() -> Self { + GetRepoBuilder { + _state: PhantomData, + _fields: (None, None, None), + _type: PhantomData, + } + } +} + +impl GetRepoBuilder { + /// Create a new builder with all fields unset + pub fn builder() -> Self { + GetRepoBuilder { + _state: PhantomData, + _fields: (None, None, None), + _type: PhantomData, + } + } +} + +impl GetRepoBuilder { + /// Set the `excludeValues` field (optional) + pub fn exclude_values(mut self, value: impl Into>) -> Self { + self._fields.0 = value.into(); + self + } + /// Set the `excludeValues` field to an Option value (optional) + pub fn maybe_exclude_values(mut self, value: Option) -> Self { + self._fields.0 = value; + self + } +} + +impl GetRepoBuilder +where + St: get_repo_state::State, + St::Repo: get_repo_state::IsUnset, +{ + /// Set the `repo` field (required) + pub fn repo( + mut self, + value: impl Into>, + ) -> GetRepoBuilder, S> { + self._fields.1 = Option::Some(value.into()); + GetRepoBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl GetRepoBuilder +where + St: get_repo_state::State, + St::Space: get_repo_state::IsUnset, +{ + /// Set the `space` field (required) + pub fn space( + mut self, + value: impl Into>, + ) -> GetRepoBuilder, S> { + self._fields.2 = Option::Some(value.into()); + GetRepoBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl GetRepoBuilder +where + St: get_repo_state::State, + St::Repo: get_repo_state::IsSet, + St::Space: get_repo_state::IsSet, +{ + /// Build the final struct. + pub fn build(self) -> GetRepo { + GetRepo { + exclude_values: self._fields.0, + repo: self._fields.1.unwrap(), + space: self._fields.2.unwrap(), + } + } +} diff --git a/crates/jacquard-api/src/com_atproto/space/get_space_credential.rs b/crates/jacquard-api/src/com_atproto/space/get_space_credential.rs new file mode 100644 index 000000000..300145983 --- /dev/null +++ b/crates/jacquard-api/src/com_atproto/space/get_space_credential.rs @@ -0,0 +1,335 @@ +// @generated by jacquard-lexicon. DO NOT EDIT. +// +// Lexicon: com.atproto.space.getSpaceCredential +// +// 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::deps::smol_str::SmolStr; +use jacquard_common::types::aturi::AtSpaceUri; +use jacquard_common::types::value::Data; +use jacquard_common::{BosStr, CowStr, DefaultStr, FromStaticStr}; +use jacquard_derive::{IntoStatic, open_union}; +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct GetSpaceCredential { + ///Optional client attestation JWT establishing the app's identity. Required only when the space gates on app identity. + #[serde(skip_serializing_if = "Option::is_none")] + pub client_attestation: Option, + ///JWK thumbprint (RFC 7638) of the key to bind the credential to. The credential is presented under the DPoP scheme with a proof signed by that key. The key needs no registration and may be ephemeral. + pub dpop_jkt: S, + ///Reference to the space. + pub space: AtSpaceUri, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic, Default)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct GetSpaceCredentialOutput { + ///A signed JWT space credential, bound to the requested DPoP key through its cnf.jkt claim. + pub credential: S, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +#[derive( + Serialize, Deserialize, Debug, Clone, PartialEq, Eq, thiserror::Error, miette::Diagnostic, +)] +#[serde(tag = "error", content = "message")] +pub enum GetSpaceCredentialError { + #[serde(rename = "SpaceNotFound")] + SpaceNotFound(Option), + #[serde(rename = "SpaceDeleted")] + SpaceDeleted(Option), + /// Refused on the basis of the requesting user. + #[serde(rename = "UserNotAuthorized")] + UserNotAuthorized(Option), + /// Refused on the basis of the requesting app. + #[serde(rename = "AppNotAuthorized")] + AppNotAuthorized(Option), + /// Refused without attributing the refusal to the user or the app. Authorities that do not wish to disclose which perimeter failed may return this in place of UserNotAuthorized or AppNotAuthorized. + #[serde(rename = "NotAuthorized")] + NotAuthorized(Option), + #[serde(rename = "InvalidDelegationToken")] + InvalidDelegationToken(Option), + #[serde(rename = "InvalidClientAttestation")] + InvalidClientAttestation(Option), + /// Catch-all for unknown error codes. + #[serde(untagged)] + Other { + error: SmolStr, + message: Option, + }, +} + +impl core::fmt::Display for GetSpaceCredentialError { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + match self { + Self::SpaceNotFound(msg) => { + write!(f, "SpaceNotFound")?; + if let Some(msg) = msg { + write!(f, ": {}", msg)?; + } + Ok(()) + } + Self::SpaceDeleted(msg) => { + write!(f, "SpaceDeleted")?; + if let Some(msg) = msg { + write!(f, ": {}", msg)?; + } + Ok(()) + } + Self::UserNotAuthorized(msg) => { + write!(f, "UserNotAuthorized")?; + if let Some(msg) = msg { + write!(f, ": {}", msg)?; + } + Ok(()) + } + Self::AppNotAuthorized(msg) => { + write!(f, "AppNotAuthorized")?; + if let Some(msg) = msg { + write!(f, ": {}", msg)?; + } + Ok(()) + } + Self::NotAuthorized(msg) => { + write!(f, "NotAuthorized")?; + if let Some(msg) = msg { + write!(f, ": {}", msg)?; + } + Ok(()) + } + Self::InvalidDelegationToken(msg) => { + write!(f, "InvalidDelegationToken")?; + if let Some(msg) = msg { + write!(f, ": {}", msg)?; + } + Ok(()) + } + Self::InvalidClientAttestation(msg) => { + write!(f, "InvalidClientAttestation")?; + if let Some(msg) = msg { + write!(f, ": {}", msg)?; + } + Ok(()) + } + Self::Other { error, message } => { + write!(f, "{}", error)?; + if let Some(msg) = message { + write!(f, ": {}", msg)?; + } + Ok(()) + } + } + } +} + +/** Response marker for the `com.atproto.space.getSpaceCredential` procedure. + +Implements `jacquard_common::xrpc::XrpcResp`; successful bodies decode as `Self::Output`, which is `GetSpaceCredentialOutput` for this endpoint.*/ +pub struct GetSpaceCredentialResponse; +impl jacquard_common::xrpc::XrpcResp for GetSpaceCredentialResponse { + const NSID: &'static str = "com.atproto.space.getSpaceCredential"; + const ENCODING: &'static str = "application/json"; + type Output = GetSpaceCredentialOutput; + type Err = GetSpaceCredentialError; +} + +impl jacquard_common::xrpc::XrpcRequest for GetSpaceCredential { + const NSID: &'static str = "com.atproto.space.getSpaceCredential"; + const METHOD: jacquard_common::xrpc::XrpcMethod = + jacquard_common::xrpc::XrpcMethod::Procedure("application/json"); + type Response = GetSpaceCredentialResponse; +} + +/** Endpoint marker for the `com.atproto.space.getSpaceCredential` procedure. + +Path: `/xrpc/com.atproto.space.getSpaceCredential`. The request payload type is `GetSpaceCredential`; send that request with `jacquard::Client` or use this marker through lower-level `XrpcEndpoint` APIs.*/ +pub struct GetSpaceCredentialRequest; +impl jacquard_common::xrpc::XrpcEndpoint for GetSpaceCredentialRequest { + const PATH: &'static str = "/xrpc/com.atproto.space.getSpaceCredential"; + const METHOD: jacquard_common::xrpc::XrpcMethod = + jacquard_common::xrpc::XrpcMethod::Procedure("application/json"); + type Request = GetSpaceCredential; + type Response = GetSpaceCredentialResponse; +} + +pub mod get_space_credential_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 DpopJkt; + type Space; + } + /// Empty state - all required fields are unset + pub struct Empty(()); + impl sealed::Sealed for Empty {} + impl State for Empty { + type DpopJkt = Unset; + type Space = Unset; + } + ///State transition - sets the `dpop_jkt` field to Set + pub struct SetDpopJkt(PhantomData St>); + impl sealed::Sealed for SetDpopJkt {} + impl State for SetDpopJkt { + type DpopJkt = Set; + type Space = St::Space; + } + ///State transition - sets the `space` field to Set + pub struct SetSpace(PhantomData St>); + impl sealed::Sealed for SetSpace {} + impl State for SetSpace { + type DpopJkt = St::DpopJkt; + type Space = Set; + } + /// Marker types for field names + #[allow(non_camel_case_types)] + pub mod members { + ///Marker type for the `dpop_jkt` field + pub struct dpop_jkt(()); + ///Marker type for the `space` field + pub struct space(()); + } +} + +/// Builder for constructing an instance of this type. +pub struct GetSpaceCredentialBuilder +{ + _state: PhantomData St>, + _fields: (Option, Option, Option>), + _type: PhantomData S>, +} + +impl GetSpaceCredential { + /// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed + pub fn new() -> GetSpaceCredentialBuilder { + GetSpaceCredentialBuilder::new() + } +} + +impl GetSpaceCredential { + /// Create a new builder for this type + pub fn builder() -> GetSpaceCredentialBuilder { + GetSpaceCredentialBuilder::builder() + } +} + +impl GetSpaceCredentialBuilder { + /// Create a new builder with all fields unset, using the default string type, if needed + pub fn new() -> Self { + GetSpaceCredentialBuilder { + _state: PhantomData, + _fields: (None, None, None), + _type: PhantomData, + } + } +} + +impl GetSpaceCredentialBuilder { + /// Create a new builder with all fields unset + pub fn builder() -> Self { + GetSpaceCredentialBuilder { + _state: PhantomData, + _fields: (None, None, None), + _type: PhantomData, + } + } +} + +impl GetSpaceCredentialBuilder { + /// Set the `clientAttestation` field (optional) + pub fn client_attestation(mut self, value: impl Into>) -> Self { + self._fields.0 = value.into(); + self + } + /// Set the `clientAttestation` field to an Option value (optional) + pub fn maybe_client_attestation(mut self, value: Option) -> Self { + self._fields.0 = value; + self + } +} + +impl GetSpaceCredentialBuilder +where + St: get_space_credential_state::State, + St::DpopJkt: get_space_credential_state::IsUnset, +{ + /// Set the `dpopJkt` field (required) + pub fn dpop_jkt( + mut self, + value: impl Into, + ) -> GetSpaceCredentialBuilder, S> { + self._fields.1 = Option::Some(value.into()); + GetSpaceCredentialBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl GetSpaceCredentialBuilder +where + St: get_space_credential_state::State, + St::Space: get_space_credential_state::IsUnset, +{ + /// Set the `space` field (required) + pub fn space( + mut self, + value: impl Into>, + ) -> GetSpaceCredentialBuilder, S> { + self._fields.2 = Option::Some(value.into()); + GetSpaceCredentialBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl GetSpaceCredentialBuilder +where + St: get_space_credential_state::State, + St::DpopJkt: get_space_credential_state::IsSet, + St::Space: get_space_credential_state::IsSet, +{ + /// Build the final struct. + pub fn build(self) -> GetSpaceCredential { + GetSpaceCredential { + client_attestation: self._fields.0, + dpop_jkt: self._fields.1.unwrap(), + space: 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>) -> GetSpaceCredential { + GetSpaceCredential { + client_attestation: self._fields.0, + dpop_jkt: self._fields.1.unwrap(), + space: self._fields.2.unwrap(), + extra_data: Some(extra_data), + } + } +} diff --git a/crates/jacquard-api/src/com_atproto/space/list_blobs.rs b/crates/jacquard-api/src/com_atproto/space/list_blobs.rs new file mode 100644 index 000000000..421b5421f --- /dev/null +++ b/crates/jacquard-api/src/com_atproto/space/list_blobs.rs @@ -0,0 +1,342 @@ +// @generated by jacquard-lexicon. DO NOT EDIT. +// +// Lexicon: com.atproto.space.listBlobs +// +// 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::deps::smol_str::SmolStr; +use jacquard_common::types::aturi::AtSpaceUri; +use jacquard_common::types::string::{Cid, Did, Tid}; +use jacquard_common::types::value::Data; +use jacquard_common::{BosStr, CowStr, DefaultStr, FromStaticStr}; +use jacquard_derive::{IntoStatic, open_union}; +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct ListBlobs { + #[serde(skip_serializing_if = "Option::is_none")] + pub cursor: Option, + /// Defaults to `500`. Min: 1. Max: 1000. + #[serde(default = "_default_limit")] + #[serde(skip_serializing_if = "Option::is_none")] + pub limit: Option, + pub repo: Did, + #[serde(skip_serializing_if = "Option::is_none")] + pub since: Option, + pub space: AtSpaceUri, +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct ListBlobsOutput { + pub cids: Vec>, + #[serde(skip_serializing_if = "Option::is_none")] + pub cursor: Option, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +#[derive( + Serialize, Deserialize, Debug, Clone, PartialEq, Eq, thiserror::Error, miette::Diagnostic, +)] +#[serde(tag = "error", content = "message")] +pub enum ListBlobsError { + #[serde(rename = "SpaceNotFound")] + SpaceNotFound(Option), + #[serde(rename = "RepoNotFound")] + RepoNotFound(Option), + #[serde(rename = "RepoTakendown")] + RepoTakendown(Option), + #[serde(rename = "RepoSuspended")] + RepoSuspended(Option), + #[serde(rename = "RepoDeactivated")] + RepoDeactivated(Option), + /// Catch-all for unknown error codes. + #[serde(untagged)] + Other { + error: SmolStr, + message: Option, + }, +} + +impl core::fmt::Display for ListBlobsError { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + match self { + Self::SpaceNotFound(msg) => { + write!(f, "SpaceNotFound")?; + if let Some(msg) = msg { + write!(f, ": {}", msg)?; + } + Ok(()) + } + Self::RepoNotFound(msg) => { + write!(f, "RepoNotFound")?; + if let Some(msg) = msg { + write!(f, ": {}", msg)?; + } + Ok(()) + } + Self::RepoTakendown(msg) => { + write!(f, "RepoTakendown")?; + if let Some(msg) = msg { + write!(f, ": {}", msg)?; + } + Ok(()) + } + Self::RepoSuspended(msg) => { + write!(f, "RepoSuspended")?; + if let Some(msg) = msg { + write!(f, ": {}", msg)?; + } + Ok(()) + } + Self::RepoDeactivated(msg) => { + write!(f, "RepoDeactivated")?; + if let Some(msg) = msg { + write!(f, ": {}", msg)?; + } + Ok(()) + } + Self::Other { error, message } => { + write!(f, "{}", error)?; + if let Some(msg) = message { + write!(f, ": {}", msg)?; + } + Ok(()) + } + } + } +} + +/** Response marker for the `com.atproto.space.listBlobs` query. + +Implements `jacquard_common::xrpc::XrpcResp`; successful bodies decode as `Self::Output`, which is `ListBlobsOutput` for this endpoint.*/ +pub struct ListBlobsResponse; +impl jacquard_common::xrpc::XrpcResp for ListBlobsResponse { + const NSID: &'static str = "com.atproto.space.listBlobs"; + const ENCODING: &'static str = "application/json"; + type Output = ListBlobsOutput; + type Err = ListBlobsError; +} + +impl jacquard_common::xrpc::XrpcRequest for ListBlobs { + const NSID: &'static str = "com.atproto.space.listBlobs"; + const METHOD: jacquard_common::xrpc::XrpcMethod = jacquard_common::xrpc::XrpcMethod::Query; + type Response = ListBlobsResponse; +} + +/** Endpoint marker for the `com.atproto.space.listBlobs` query. + +Path: `/xrpc/com.atproto.space.listBlobs`. The request payload type is `ListBlobs`; send that request with `jacquard::Client` or use this marker through lower-level `XrpcEndpoint` APIs.*/ +pub struct ListBlobsRequest; +impl jacquard_common::xrpc::XrpcEndpoint for ListBlobsRequest { + const PATH: &'static str = "/xrpc/com.atproto.space.listBlobs"; + const METHOD: jacquard_common::xrpc::XrpcMethod = jacquard_common::xrpc::XrpcMethod::Query; + type Request = ListBlobs; + type Response = ListBlobsResponse; +} + +fn _default_limit() -> Option { + Some(500i64) +} + +pub mod list_blobs_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 Repo; + type Space; + } + /// Empty state - all required fields are unset + pub struct Empty(()); + impl sealed::Sealed for Empty {} + impl State for Empty { + type Repo = Unset; + type Space = Unset; + } + ///State transition - sets the `repo` field to Set + pub struct SetRepo(PhantomData St>); + impl sealed::Sealed for SetRepo {} + impl State for SetRepo { + type Repo = Set; + type Space = St::Space; + } + ///State transition - sets the `space` field to Set + pub struct SetSpace(PhantomData St>); + impl sealed::Sealed for SetSpace {} + impl State for SetSpace { + type Repo = St::Repo; + type Space = Set; + } + /// Marker types for field names + #[allow(non_camel_case_types)] + pub mod members { + ///Marker type for the `repo` field + pub struct repo(()); + ///Marker type for the `space` field + pub struct space(()); + } +} + +/// Builder for constructing an instance of this type. +pub struct ListBlobsBuilder { + _state: PhantomData St>, + _fields: ( + Option, + Option, + Option>, + Option, + Option>, + ), + _type: PhantomData S>, +} + +impl ListBlobs { + /// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed + pub fn new() -> ListBlobsBuilder { + ListBlobsBuilder::new() + } +} + +impl ListBlobs { + /// Create a new builder for this type + pub fn builder() -> ListBlobsBuilder { + ListBlobsBuilder::builder() + } +} + +impl ListBlobsBuilder { + /// Create a new builder with all fields unset, using the default string type, if needed + pub fn new() -> Self { + ListBlobsBuilder { + _state: PhantomData, + _fields: (None, None, None, None, None), + _type: PhantomData, + } + } +} + +impl ListBlobsBuilder { + /// Create a new builder with all fields unset + pub fn builder() -> Self { + ListBlobsBuilder { + _state: PhantomData, + _fields: (None, None, None, None, None), + _type: PhantomData, + } + } +} + +impl ListBlobsBuilder { + /// Set the `cursor` field (optional) + pub fn cursor(mut self, value: impl Into>) -> Self { + self._fields.0 = value.into(); + self + } + /// Set the `cursor` field to an Option value (optional) + pub fn maybe_cursor(mut self, value: Option) -> Self { + self._fields.0 = value; + self + } +} + +impl ListBlobsBuilder { + /// Set the `limit` field (optional) + pub fn limit(mut self, value: impl Into>) -> Self { + self._fields.1 = value.into(); + self + } + /// Set the `limit` field to an Option value (optional) + pub fn maybe_limit(mut self, value: Option) -> Self { + self._fields.1 = value; + self + } +} + +impl ListBlobsBuilder +where + St: list_blobs_state::State, + St::Repo: list_blobs_state::IsUnset, +{ + /// Set the `repo` field (required) + pub fn repo( + mut self, + value: impl Into>, + ) -> ListBlobsBuilder, S> { + self._fields.2 = Option::Some(value.into()); + ListBlobsBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl ListBlobsBuilder { + /// Set the `since` field (optional) + pub fn since(mut self, value: impl Into>) -> Self { + self._fields.3 = value.into(); + self + } + /// Set the `since` field to an Option value (optional) + pub fn maybe_since(mut self, value: Option) -> Self { + self._fields.3 = value; + self + } +} + +impl ListBlobsBuilder +where + St: list_blobs_state::State, + St::Space: list_blobs_state::IsUnset, +{ + /// Set the `space` field (required) + pub fn space( + mut self, + value: impl Into>, + ) -> ListBlobsBuilder, S> { + self._fields.4 = Option::Some(value.into()); + ListBlobsBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl ListBlobsBuilder +where + St: list_blobs_state::State, + St::Repo: list_blobs_state::IsSet, + St::Space: list_blobs_state::IsSet, +{ + /// Build the final struct. + pub fn build(self) -> ListBlobs { + ListBlobs { + cursor: self._fields.0, + limit: self._fields.1, + repo: self._fields.2.unwrap(), + since: self._fields.3, + space: self._fields.4.unwrap(), + } + } +} diff --git a/crates/jacquard-api/src/com_atproto/space/list_records.rs b/crates/jacquard-api/src/com_atproto/space/list_records.rs new file mode 100644 index 000000000..f9689c5a0 --- /dev/null +++ b/crates/jacquard-api/src/com_atproto/space/list_records.rs @@ -0,0 +1,762 @@ +// @generated by jacquard-lexicon. DO NOT EDIT. +// +// Lexicon: com.atproto.space.listRecords +// +// 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::aturi::AtSpaceUri; +use jacquard_common::types::string::{Cid, Did, Nsid, RecordKey, Rkey}; +use jacquard_common::types::value::Data; +use jacquard_derive::{IntoStatic, open_union}; +use jacquard_lexicon::lexicon::LexiconDoc; +use jacquard_lexicon::schema::LexiconSchema; + +use crate::com_atproto::space::list_records; +#[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", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct ListRecords { + #[serde(skip_serializing_if = "Option::is_none")] + pub collection: Option>, + #[serde(skip_serializing_if = "Option::is_none")] + pub cursor: Option, + /// Defaults to `false`. + #[serde(default = "_default_exclude_values")] + #[serde(skip_serializing_if = "Option::is_none")] + pub exclude_values: Option, + /// Defaults to `50`. Min: 1. Max: 1000. + #[serde(default = "_default_limit")] + #[serde(skip_serializing_if = "Option::is_none")] + pub limit: Option, + pub repo: Did, + #[serde(skip_serializing_if = "Option::is_none")] + pub reverse: Option, + pub space: AtSpaceUri, +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct ListRecordsOutput { + #[serde(skip_serializing_if = "Option::is_none")] + pub cursor: Option, + pub records: Vec>, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +#[derive( + Serialize, Deserialize, Debug, Clone, PartialEq, Eq, thiserror::Error, miette::Diagnostic, +)] +#[serde(tag = "error", content = "message")] +pub enum ListRecordsError { + #[serde(rename = "SpaceNotFound")] + SpaceNotFound(Option), + #[serde(rename = "RepoNotFound")] + RepoNotFound(Option), + #[serde(rename = "RepoTakendown")] + RepoTakendown(Option), + #[serde(rename = "RepoSuspended")] + RepoSuspended(Option), + #[serde(rename = "RepoDeactivated")] + RepoDeactivated(Option), + /// Catch-all for unknown error codes. + #[serde(untagged)] + Other { + error: SmolStr, + message: Option, + }, +} + +impl core::fmt::Display for ListRecordsError { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + match self { + Self::SpaceNotFound(msg) => { + write!(f, "SpaceNotFound")?; + if let Some(msg) = msg { + write!(f, ": {}", msg)?; + } + Ok(()) + } + Self::RepoNotFound(msg) => { + write!(f, "RepoNotFound")?; + if let Some(msg) = msg { + write!(f, ": {}", msg)?; + } + Ok(()) + } + Self::RepoTakendown(msg) => { + write!(f, "RepoTakendown")?; + if let Some(msg) = msg { + write!(f, ": {}", msg)?; + } + Ok(()) + } + Self::RepoSuspended(msg) => { + write!(f, "RepoSuspended")?; + if let Some(msg) = msg { + write!(f, ": {}", msg)?; + } + Ok(()) + } + Self::RepoDeactivated(msg) => { + write!(f, "RepoDeactivated")?; + if let Some(msg) = msg { + write!(f, ": {}", msg)?; + } + Ok(()) + } + Self::Other { error, message } => { + write!(f, "{}", error)?; + if let Some(msg) = message { + write!(f, ": {}", msg)?; + } + Ok(()) + } + } + } +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct Record { + pub cid: Cid, + pub collection: Nsid, + pub rkey: RecordKey>, + ///The record's value. Inlined by default; omitted when excludeValues is set. + #[serde(skip_serializing_if = "Option::is_none")] + pub value: Option>, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +/** Response marker for the `com.atproto.space.listRecords` query. + +Implements `jacquard_common::xrpc::XrpcResp`; successful bodies decode as `Self::Output`, which is `ListRecordsOutput` for this endpoint.*/ +pub struct ListRecordsResponse; +impl jacquard_common::xrpc::XrpcResp for ListRecordsResponse { + const NSID: &'static str = "com.atproto.space.listRecords"; + const ENCODING: &'static str = "application/json"; + type Output = ListRecordsOutput; + type Err = ListRecordsError; +} + +impl jacquard_common::xrpc::XrpcRequest for ListRecords { + const NSID: &'static str = "com.atproto.space.listRecords"; + const METHOD: jacquard_common::xrpc::XrpcMethod = jacquard_common::xrpc::XrpcMethod::Query; + type Response = ListRecordsResponse; +} + +/** Endpoint marker for the `com.atproto.space.listRecords` query. + +Path: `/xrpc/com.atproto.space.listRecords`. The request payload type is `ListRecords`; send that request with `jacquard::Client` or use this marker through lower-level `XrpcEndpoint` APIs.*/ +pub struct ListRecordsRequest; +impl jacquard_common::xrpc::XrpcEndpoint for ListRecordsRequest { + const PATH: &'static str = "/xrpc/com.atproto.space.listRecords"; + const METHOD: jacquard_common::xrpc::XrpcMethod = jacquard_common::xrpc::XrpcMethod::Query; + type Request = ListRecords; + type Response = ListRecordsResponse; +} + +impl LexiconSchema for Record { + fn nsid() -> &'static str { + "com.atproto.space.listRecords" + } + fn def_name() -> &'static str { + "record" + } + fn lexicon_doc() -> LexiconDoc<'static> { + lexicon_doc_com_atproto_space_listRecords() + } + fn validate(&self) -> Result<(), ConstraintError> { + Ok(()) + } +} + +fn _default_exclude_values() -> Option { + Some(false) +} + +fn _default_limit() -> Option { + Some(50i64) +} + +pub mod list_records_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 Repo; + type Space; + } + /// Empty state - all required fields are unset + pub struct Empty(()); + impl sealed::Sealed for Empty {} + impl State for Empty { + type Repo = Unset; + type Space = Unset; + } + ///State transition - sets the `repo` field to Set + pub struct SetRepo(PhantomData St>); + impl sealed::Sealed for SetRepo {} + impl State for SetRepo { + type Repo = Set; + type Space = St::Space; + } + ///State transition - sets the `space` field to Set + pub struct SetSpace(PhantomData St>); + impl sealed::Sealed for SetSpace {} + impl State for SetSpace { + type Repo = St::Repo; + type Space = Set; + } + /// Marker types for field names + #[allow(non_camel_case_types)] + pub mod members { + ///Marker type for the `repo` field + pub struct repo(()); + ///Marker type for the `space` field + pub struct space(()); + } +} + +/// Builder for constructing an instance of this type. +pub struct ListRecordsBuilder { + _state: PhantomData St>, + _fields: ( + Option>, + Option, + Option, + Option, + Option>, + Option, + Option>, + ), + _type: PhantomData S>, +} + +impl ListRecords { + /// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed + pub fn new() -> ListRecordsBuilder { + ListRecordsBuilder::new() + } +} + +impl ListRecords { + /// Create a new builder for this type + pub fn builder() -> ListRecordsBuilder { + ListRecordsBuilder::builder() + } +} + +impl ListRecordsBuilder { + /// Create a new builder with all fields unset, using the default string type, if needed + pub fn new() -> Self { + ListRecordsBuilder { + _state: PhantomData, + _fields: (None, None, None, None, None, None, None), + _type: PhantomData, + } + } +} + +impl ListRecordsBuilder { + /// Create a new builder with all fields unset + pub fn builder() -> Self { + ListRecordsBuilder { + _state: PhantomData, + _fields: (None, None, None, None, None, None, None), + _type: PhantomData, + } + } +} + +impl ListRecordsBuilder { + /// Set the `collection` field (optional) + pub fn collection(mut self, value: impl Into>>) -> Self { + self._fields.0 = value.into(); + self + } + /// Set the `collection` field to an Option value (optional) + pub fn maybe_collection(mut self, value: Option>) -> Self { + self._fields.0 = value; + self + } +} + +impl ListRecordsBuilder { + /// Set the `cursor` field (optional) + pub fn cursor(mut self, value: impl Into>) -> Self { + self._fields.1 = value.into(); + self + } + /// Set the `cursor` field to an Option value (optional) + pub fn maybe_cursor(mut self, value: Option) -> Self { + self._fields.1 = value; + self + } +} + +impl ListRecordsBuilder { + /// Set the `excludeValues` field (optional) + pub fn exclude_values(mut self, value: impl Into>) -> Self { + self._fields.2 = value.into(); + self + } + /// Set the `excludeValues` field to an Option value (optional) + pub fn maybe_exclude_values(mut self, value: Option) -> Self { + self._fields.2 = value; + self + } +} + +impl ListRecordsBuilder { + /// Set the `limit` field (optional) + pub fn limit(mut self, value: impl Into>) -> Self { + self._fields.3 = value.into(); + self + } + /// Set the `limit` field to an Option value (optional) + pub fn maybe_limit(mut self, value: Option) -> Self { + self._fields.3 = value; + self + } +} + +impl ListRecordsBuilder +where + St: list_records_state::State, + St::Repo: list_records_state::IsUnset, +{ + /// Set the `repo` field (required) + pub fn repo( + mut self, + value: impl Into>, + ) -> ListRecordsBuilder, S> { + self._fields.4 = Option::Some(value.into()); + ListRecordsBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl ListRecordsBuilder { + /// Set the `reverse` field (optional) + pub fn reverse(mut self, value: impl Into>) -> Self { + self._fields.5 = value.into(); + self + } + /// Set the `reverse` field to an Option value (optional) + pub fn maybe_reverse(mut self, value: Option) -> Self { + self._fields.5 = value; + self + } +} + +impl ListRecordsBuilder +where + St: list_records_state::State, + St::Space: list_records_state::IsUnset, +{ + /// Set the `space` field (required) + pub fn space( + mut self, + value: impl Into>, + ) -> ListRecordsBuilder, S> { + self._fields.6 = Option::Some(value.into()); + ListRecordsBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl ListRecordsBuilder +where + St: list_records_state::State, + St::Repo: list_records_state::IsSet, + St::Space: list_records_state::IsSet, +{ + /// Build the final struct. + pub fn build(self) -> ListRecords { + ListRecords { + collection: self._fields.0, + cursor: self._fields.1, + exclude_values: self._fields.2, + limit: self._fields.3, + repo: self._fields.4.unwrap(), + reverse: self._fields.5, + space: self._fields.6.unwrap(), + } + } +} + +pub mod record_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 Cid; + type Collection; + type Rkey; + } + /// Empty state - all required fields are unset + pub struct Empty(()); + impl sealed::Sealed for Empty {} + impl State for Empty { + type Cid = Unset; + type Collection = Unset; + type Rkey = Unset; + } + ///State transition - sets the `cid` field to Set + pub struct SetCid(PhantomData St>); + impl sealed::Sealed for SetCid {} + impl State for SetCid { + type Cid = Set; + type Collection = St::Collection; + type Rkey = St::Rkey; + } + ///State transition - sets the `collection` field to Set + pub struct SetCollection(PhantomData St>); + impl sealed::Sealed for SetCollection {} + impl State for SetCollection { + type Cid = St::Cid; + type Collection = Set; + type Rkey = St::Rkey; + } + ///State transition - sets the `rkey` field to Set + pub struct SetRkey(PhantomData St>); + impl sealed::Sealed for SetRkey {} + impl State for SetRkey { + type Cid = St::Cid; + type Collection = St::Collection; + type Rkey = Set; + } + /// Marker types for field names + #[allow(non_camel_case_types)] + pub mod members { + ///Marker type for the `cid` field + pub struct cid(()); + ///Marker type for the `collection` field + pub struct collection(()); + ///Marker type for the `rkey` field + pub struct rkey(()); + } +} + +/// Builder for constructing an instance of this type. +pub struct RecordBuilder { + _state: PhantomData St>, + _fields: ( + Option>, + Option>, + Option>>, + Option>, + ), + _type: PhantomData S>, +} + +impl Record { + /// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed + pub fn new() -> RecordBuilder { + RecordBuilder::new() + } +} + +impl Record { + /// Create a new builder for this type + pub fn builder() -> RecordBuilder { + RecordBuilder::builder() + } +} + +impl RecordBuilder { + /// Create a new builder with all fields unset, using the default string type, if needed + pub fn new() -> Self { + RecordBuilder { + _state: PhantomData, + _fields: (None, None, None, None), + _type: PhantomData, + } + } +} + +impl RecordBuilder { + /// Create a new builder with all fields unset + pub fn builder() -> Self { + RecordBuilder { + _state: PhantomData, + _fields: (None, None, None, None), + _type: PhantomData, + } + } +} + +impl RecordBuilder +where + St: record_state::State, + St::Cid: record_state::IsUnset, +{ + /// Set the `cid` field (required) + pub fn cid(mut self, value: impl Into>) -> RecordBuilder, S> { + self._fields.0 = Option::Some(value.into()); + RecordBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl RecordBuilder +where + St: record_state::State, + St::Collection: record_state::IsUnset, +{ + /// Set the `collection` field (required) + pub fn collection( + mut self, + value: impl Into>, + ) -> RecordBuilder, S> { + self._fields.1 = Option::Some(value.into()); + RecordBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl RecordBuilder +where + St: record_state::State, + St::Rkey: record_state::IsUnset, +{ + /// Set the `rkey` field (required) + pub fn rkey( + mut self, + value: impl Into>>, + ) -> RecordBuilder, S> { + self._fields.2 = Option::Some(value.into()); + RecordBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl RecordBuilder { + /// Set the `value` field (optional) + pub fn value(mut self, value: impl Into>>) -> Self { + self._fields.3 = value.into(); + self + } + /// Set the `value` field to an Option value (optional) + pub fn maybe_value(mut self, value: Option>) -> Self { + self._fields.3 = value; + self + } +} + +impl RecordBuilder +where + St: record_state::State, + St::Cid: record_state::IsSet, + St::Collection: record_state::IsSet, + St::Rkey: record_state::IsSet, +{ + /// Build the final struct. + pub fn build(self) -> Record { + Record { + cid: self._fields.0.unwrap(), + collection: self._fields.1.unwrap(), + rkey: self._fields.2.unwrap(), + value: self._fields.3, + extra_data: Default::default(), + } + } + /// Build the final struct with custom extra_data. + pub fn build_with_data(self, extra_data: BTreeMap>) -> Record { + Record { + cid: self._fields.0.unwrap(), + collection: self._fields.1.unwrap(), + rkey: self._fields.2.unwrap(), + value: self._fields.3, + extra_data: Some(extra_data), + } + } +} + +fn lexicon_doc_com_atproto_space_listRecords() -> 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("com.atproto.space.listRecords"), + defs: { + let mut map = BTreeMap::new(); + map.insert( + SmolStr::new_static("main"), + LexUserType::XrpcQuery(LexXrpcQuery { + parameters: Some( + LexXrpcQueryParameter::Params(LexXrpcParameters { + required: Some( + vec![ + SmolStr::new_static("space"), SmolStr::new_static("repo") + ], + ), + properties: { + #[allow(unused_mut)] + let mut map = BTreeMap::new(); + map.insert( + SmolStr::new_static("collection"), + LexXrpcParametersProperty::String(LexString { + description: Some( + CowStr::new_static( + "The NSID of the record collection. If omitted, lists records across all collections.", + ), + ), + format: Some(LexStringFormat::Nsid), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("cursor"), + LexXrpcParametersProperty::String(LexString { + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("excludeValues"), + LexXrpcParametersProperty::Boolean(LexBoolean { + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("limit"), + LexXrpcParametersProperty::Integer(LexInteger { + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("repo"), + LexXrpcParametersProperty::String(LexString { + description: Some( + CowStr::new_static( + "The DID of the account whose repo to list.", + ), + ), + format: Some(LexStringFormat::Did), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("reverse"), + LexXrpcParametersProperty::Boolean(LexBoolean { + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("space"), + LexXrpcParametersProperty::String(LexString { + description: Some( + CowStr::new_static("Reference to the space."), + ), + format: Some(LexStringFormat::SpaceRef), + ..Default::default() + }), + ); + map + }, + ..Default::default() + }), + ), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("record"), + LexUserType::Object(LexObject { + required: Some(vec![ + SmolStr::new_static("collection"), + SmolStr::new_static("rkey"), + SmolStr::new_static("cid"), + ]), + properties: { + #[allow(unused_mut)] + let mut map = BTreeMap::new(); + map.insert( + SmolStr::new_static("cid"), + LexObjectProperty::String(LexString { + format: Some(LexStringFormat::Cid), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("collection"), + LexObjectProperty::String(LexString { + format: Some(LexStringFormat::Nsid), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("rkey"), + LexObjectProperty::String(LexString { + format: Some(LexStringFormat::RecordKey), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("value"), + LexObjectProperty::Unknown(LexUnknown { + ..Default::default() + }), + ); + map + }, + ..Default::default() + }), + ); + map + }, + ..Default::default() + } +} diff --git a/crates/jacquard-api/src/com_atproto/space/list_repo_ops.rs b/crates/jacquard-api/src/com_atproto/space/list_repo_ops.rs new file mode 100644 index 000000000..c27eefff3 --- /dev/null +++ b/crates/jacquard-api/src/com_atproto/space/list_repo_ops.rs @@ -0,0 +1,809 @@ +// @generated by jacquard-lexicon. DO NOT EDIT. +// +// Lexicon: com.atproto.space.listRepoOps +// +// 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::aturi::AtSpaceUri; +use jacquard_common::types::string::{Cid, Did, Nsid, RecordKey, Rkey, Tid}; +use jacquard_common::types::value::Data; +use jacquard_derive::{IntoStatic, open_union}; +use jacquard_lexicon::lexicon::LexiconDoc; +use jacquard_lexicon::schema::LexiconSchema; + +use crate::com_atproto::space::SignedCommit; +use crate::com_atproto::space::list_repo_ops; +#[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", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct ListRepoOps { + #[serde(skip_serializing_if = "Option::is_none")] + pub cursor: Option, + /// Defaults to `false`. + #[serde(default = "_default_exclude_values")] + #[serde(skip_serializing_if = "Option::is_none")] + pub exclude_values: Option, + /// Defaults to `100`. Min: 1. Max: 1000. + #[serde(default = "_default_limit")] + #[serde(skip_serializing_if = "Option::is_none")] + pub limit: Option, + pub repo: Did, + #[serde(skip_serializing_if = "Option::is_none")] + pub since: Option, + pub space: AtSpaceUri, +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct ListRepoOpsOutput { + ///The account's current signed commit. Included when the response reaches the head of the oplog; omitted on backfill responses. + #[serde(skip_serializing_if = "Option::is_none")] + pub commit: Option>, + ///Pass as `cursor` to fetch the next page. Absent once the response reaches the head of the oplog. + #[serde(skip_serializing_if = "Option::is_none")] + pub cursor: Option, + pub ops: Vec>, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +#[derive( + Serialize, Deserialize, Debug, Clone, PartialEq, Eq, thiserror::Error, miette::Diagnostic, +)] +#[serde(tag = "error", content = "message")] +pub enum ListRepoOpsError { + #[serde(rename = "SpaceNotFound")] + SpaceNotFound(Option), + #[serde(rename = "RepoNotFound")] + RepoNotFound(Option), + #[serde(rename = "RepoTakendown")] + RepoTakendown(Option), + #[serde(rename = "RepoSuspended")] + RepoSuspended(Option), + #[serde(rename = "RepoDeactivated")] + RepoDeactivated(Option), + /// Catch-all for unknown error codes. + #[serde(untagged)] + Other { + error: SmolStr, + message: Option, + }, +} + +impl core::fmt::Display for ListRepoOpsError { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + match self { + Self::SpaceNotFound(msg) => { + write!(f, "SpaceNotFound")?; + if let Some(msg) = msg { + write!(f, ": {}", msg)?; + } + Ok(()) + } + Self::RepoNotFound(msg) => { + write!(f, "RepoNotFound")?; + if let Some(msg) = msg { + write!(f, ": {}", msg)?; + } + Ok(()) + } + Self::RepoTakendown(msg) => { + write!(f, "RepoTakendown")?; + if let Some(msg) = msg { + write!(f, ": {}", msg)?; + } + Ok(()) + } + Self::RepoSuspended(msg) => { + write!(f, "RepoSuspended")?; + if let Some(msg) = msg { + write!(f, ": {}", msg)?; + } + Ok(()) + } + Self::RepoDeactivated(msg) => { + write!(f, "RepoDeactivated")?; + if let Some(msg) = msg { + write!(f, ": {}", msg)?; + } + Ok(()) + } + Self::Other { error, message } => { + write!(f, "{}", error)?; + if let Some(msg) = message { + write!(f, ": {}", msg)?; + } + Ok(()) + } + } + } +} + +/// A single operation in a permissioned repo's oplog. cid is null for deletes; prev is null for creates. Operations sharing the same rev belong to the same batch. value carries the record's current value for creates and updates, unless excludeValues was set or the value is stale (superseded by a later operation). + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct OpEntry { + #[serde(skip_serializing_if = "Option::is_none")] + pub cid: Option>, + pub collection: Nsid, + #[serde(skip_serializing_if = "Option::is_none")] + pub prev: Option>, + pub rev: Tid, + pub rkey: RecordKey>, + ///The record's current value, inlined for create and update operations. Omitted when excludeValues is set, for deletes, or when the value has been superseded by a later operation. + #[serde(skip_serializing_if = "Option::is_none")] + pub value: Option>, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +/** Response marker for the `com.atproto.space.listRepoOps` query. + +Implements `jacquard_common::xrpc::XrpcResp`; successful bodies decode as `Self::Output`, which is `ListRepoOpsOutput` for this endpoint.*/ +pub struct ListRepoOpsResponse; +impl jacquard_common::xrpc::XrpcResp for ListRepoOpsResponse { + const NSID: &'static str = "com.atproto.space.listRepoOps"; + const ENCODING: &'static str = "application/json"; + type Output = ListRepoOpsOutput; + type Err = ListRepoOpsError; +} + +impl jacquard_common::xrpc::XrpcRequest for ListRepoOps { + const NSID: &'static str = "com.atproto.space.listRepoOps"; + const METHOD: jacquard_common::xrpc::XrpcMethod = jacquard_common::xrpc::XrpcMethod::Query; + type Response = ListRepoOpsResponse; +} + +/** Endpoint marker for the `com.atproto.space.listRepoOps` query. + +Path: `/xrpc/com.atproto.space.listRepoOps`. The request payload type is `ListRepoOps`; send that request with `jacquard::Client` or use this marker through lower-level `XrpcEndpoint` APIs.*/ +pub struct ListRepoOpsRequest; +impl jacquard_common::xrpc::XrpcEndpoint for ListRepoOpsRequest { + const PATH: &'static str = "/xrpc/com.atproto.space.listRepoOps"; + const METHOD: jacquard_common::xrpc::XrpcMethod = jacquard_common::xrpc::XrpcMethod::Query; + type Request = ListRepoOps; + type Response = ListRepoOpsResponse; +} + +impl LexiconSchema for OpEntry { + fn nsid() -> &'static str { + "com.atproto.space.listRepoOps" + } + fn def_name() -> &'static str { + "opEntry" + } + fn lexicon_doc() -> LexiconDoc<'static> { + lexicon_doc_com_atproto_space_listRepoOps() + } + fn validate(&self) -> Result<(), ConstraintError> { + Ok(()) + } +} + +fn _default_exclude_values() -> Option { + Some(false) +} + +fn _default_limit() -> Option { + Some(100i64) +} + +pub mod list_repo_ops_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 Repo; + type Space; + } + /// Empty state - all required fields are unset + pub struct Empty(()); + impl sealed::Sealed for Empty {} + impl State for Empty { + type Repo = Unset; + type Space = Unset; + } + ///State transition - sets the `repo` field to Set + pub struct SetRepo(PhantomData St>); + impl sealed::Sealed for SetRepo {} + impl State for SetRepo { + type Repo = Set; + type Space = St::Space; + } + ///State transition - sets the `space` field to Set + pub struct SetSpace(PhantomData St>); + impl sealed::Sealed for SetSpace {} + impl State for SetSpace { + type Repo = St::Repo; + type Space = Set; + } + /// Marker types for field names + #[allow(non_camel_case_types)] + pub mod members { + ///Marker type for the `repo` field + pub struct repo(()); + ///Marker type for the `space` field + pub struct space(()); + } +} + +/// Builder for constructing an instance of this type. +pub struct ListRepoOpsBuilder { + _state: PhantomData St>, + _fields: ( + Option, + Option, + Option, + Option>, + Option, + Option>, + ), + _type: PhantomData S>, +} + +impl ListRepoOps { + /// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed + pub fn new() -> ListRepoOpsBuilder { + ListRepoOpsBuilder::new() + } +} + +impl ListRepoOps { + /// Create a new builder for this type + pub fn builder() -> ListRepoOpsBuilder { + ListRepoOpsBuilder::builder() + } +} + +impl ListRepoOpsBuilder { + /// Create a new builder with all fields unset, using the default string type, if needed + pub fn new() -> Self { + ListRepoOpsBuilder { + _state: PhantomData, + _fields: (None, None, None, None, None, None), + _type: PhantomData, + } + } +} + +impl ListRepoOpsBuilder { + /// Create a new builder with all fields unset + pub fn builder() -> Self { + ListRepoOpsBuilder { + _state: PhantomData, + _fields: (None, None, None, None, None, None), + _type: PhantomData, + } + } +} + +impl ListRepoOpsBuilder { + /// Set the `cursor` field (optional) + pub fn cursor(mut self, value: impl Into>) -> Self { + self._fields.0 = value.into(); + self + } + /// Set the `cursor` field to an Option value (optional) + pub fn maybe_cursor(mut self, value: Option) -> Self { + self._fields.0 = value; + self + } +} + +impl ListRepoOpsBuilder { + /// Set the `excludeValues` field (optional) + pub fn exclude_values(mut self, value: impl Into>) -> Self { + self._fields.1 = value.into(); + self + } + /// Set the `excludeValues` field to an Option value (optional) + pub fn maybe_exclude_values(mut self, value: Option) -> Self { + self._fields.1 = value; + self + } +} + +impl ListRepoOpsBuilder { + /// Set the `limit` field (optional) + pub fn limit(mut self, value: impl Into>) -> Self { + self._fields.2 = value.into(); + self + } + /// Set the `limit` field to an Option value (optional) + pub fn maybe_limit(mut self, value: Option) -> Self { + self._fields.2 = value; + self + } +} + +impl ListRepoOpsBuilder +where + St: list_repo_ops_state::State, + St::Repo: list_repo_ops_state::IsUnset, +{ + /// Set the `repo` field (required) + pub fn repo( + mut self, + value: impl Into>, + ) -> ListRepoOpsBuilder, S> { + self._fields.3 = Option::Some(value.into()); + ListRepoOpsBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl ListRepoOpsBuilder { + /// Set the `since` field (optional) + pub fn since(mut self, value: impl Into>) -> Self { + self._fields.4 = value.into(); + self + } + /// Set the `since` field to an Option value (optional) + pub fn maybe_since(mut self, value: Option) -> Self { + self._fields.4 = value; + self + } +} + +impl ListRepoOpsBuilder +where + St: list_repo_ops_state::State, + St::Space: list_repo_ops_state::IsUnset, +{ + /// Set the `space` field (required) + pub fn space( + mut self, + value: impl Into>, + ) -> ListRepoOpsBuilder, S> { + self._fields.5 = Option::Some(value.into()); + ListRepoOpsBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl ListRepoOpsBuilder +where + St: list_repo_ops_state::State, + St::Repo: list_repo_ops_state::IsSet, + St::Space: list_repo_ops_state::IsSet, +{ + /// Build the final struct. + pub fn build(self) -> ListRepoOps { + ListRepoOps { + cursor: self._fields.0, + exclude_values: self._fields.1, + limit: self._fields.2, + repo: self._fields.3.unwrap(), + since: self._fields.4, + space: self._fields.5.unwrap(), + } + } +} + +pub mod op_entry_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 Collection; + type Rev; + type Rkey; + } + /// Empty state - all required fields are unset + pub struct Empty(()); + impl sealed::Sealed for Empty {} + impl State for Empty { + type Collection = Unset; + type Rev = Unset; + type Rkey = Unset; + } + ///State transition - sets the `collection` field to Set + pub struct SetCollection(PhantomData St>); + impl sealed::Sealed for SetCollection {} + impl State for SetCollection { + type Collection = Set; + type Rev = St::Rev; + type Rkey = St::Rkey; + } + ///State transition - sets the `rev` field to Set + pub struct SetRev(PhantomData St>); + impl sealed::Sealed for SetRev {} + impl State for SetRev { + type Collection = St::Collection; + type Rev = Set; + type Rkey = St::Rkey; + } + ///State transition - sets the `rkey` field to Set + pub struct SetRkey(PhantomData St>); + impl sealed::Sealed for SetRkey {} + impl State for SetRkey { + type Collection = St::Collection; + type Rev = St::Rev; + type Rkey = Set; + } + /// Marker types for field names + #[allow(non_camel_case_types)] + pub mod members { + ///Marker type for the `collection` field + pub struct collection(()); + ///Marker type for the `rev` field + pub struct rev(()); + ///Marker type for the `rkey` field + pub struct rkey(()); + } +} + +/// Builder for constructing an instance of this type. +pub struct OpEntryBuilder { + _state: PhantomData St>, + _fields: ( + Option>, + Option>, + Option>, + Option, + Option>>, + Option>, + ), + _type: PhantomData S>, +} + +impl OpEntry { + /// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed + pub fn new() -> OpEntryBuilder { + OpEntryBuilder::new() + } +} + +impl OpEntry { + /// Create a new builder for this type + pub fn builder() -> OpEntryBuilder { + OpEntryBuilder::builder() + } +} + +impl OpEntryBuilder { + /// Create a new builder with all fields unset, using the default string type, if needed + pub fn new() -> Self { + OpEntryBuilder { + _state: PhantomData, + _fields: (None, None, None, None, None, None), + _type: PhantomData, + } + } +} + +impl OpEntryBuilder { + /// Create a new builder with all fields unset + pub fn builder() -> Self { + OpEntryBuilder { + _state: PhantomData, + _fields: (None, None, None, None, None, None), + _type: PhantomData, + } + } +} + +impl OpEntryBuilder { + /// Set the `cid` field (optional) + pub fn cid(mut self, value: impl Into>>) -> Self { + self._fields.0 = value.into(); + self + } + /// Set the `cid` field to an Option value (optional) + pub fn maybe_cid(mut self, value: Option>) -> Self { + self._fields.0 = value; + self + } +} + +impl OpEntryBuilder +where + St: op_entry_state::State, + St::Collection: op_entry_state::IsUnset, +{ + /// Set the `collection` field (required) + pub fn collection( + mut self, + value: impl Into>, + ) -> OpEntryBuilder, S> { + self._fields.1 = Option::Some(value.into()); + OpEntryBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl OpEntryBuilder { + /// Set the `prev` field (optional) + pub fn prev(mut self, value: impl Into>>) -> Self { + self._fields.2 = value.into(); + self + } + /// Set the `prev` field to an Option value (optional) + pub fn maybe_prev(mut self, value: Option>) -> Self { + self._fields.2 = value; + self + } +} + +impl OpEntryBuilder +where + St: op_entry_state::State, + St::Rev: op_entry_state::IsUnset, +{ + /// Set the `rev` field (required) + pub fn rev(mut self, value: impl Into) -> OpEntryBuilder, S> { + self._fields.3 = Option::Some(value.into()); + OpEntryBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl OpEntryBuilder +where + St: op_entry_state::State, + St::Rkey: op_entry_state::IsUnset, +{ + /// Set the `rkey` field (required) + pub fn rkey( + mut self, + value: impl Into>>, + ) -> OpEntryBuilder, S> { + self._fields.4 = Option::Some(value.into()); + OpEntryBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl OpEntryBuilder { + /// Set the `value` field (optional) + pub fn value(mut self, value: impl Into>>) -> Self { + self._fields.5 = value.into(); + self + } + /// Set the `value` field to an Option value (optional) + pub fn maybe_value(mut self, value: Option>) -> Self { + self._fields.5 = value; + self + } +} + +impl OpEntryBuilder +where + St: op_entry_state::State, + St::Collection: op_entry_state::IsSet, + St::Rev: op_entry_state::IsSet, + St::Rkey: op_entry_state::IsSet, +{ + /// Build the final struct. + pub fn build(self) -> OpEntry { + OpEntry { + cid: self._fields.0, + collection: self._fields.1.unwrap(), + prev: self._fields.2, + rev: self._fields.3.unwrap(), + rkey: self._fields.4.unwrap(), + value: self._fields.5, + extra_data: Default::default(), + } + } + /// Build the final struct with custom extra_data. + pub fn build_with_data(self, extra_data: BTreeMap>) -> OpEntry { + OpEntry { + cid: self._fields.0, + collection: self._fields.1.unwrap(), + prev: self._fields.2, + rev: self._fields.3.unwrap(), + rkey: self._fields.4.unwrap(), + value: self._fields.5, + extra_data: Some(extra_data), + } + } +} + +fn lexicon_doc_com_atproto_space_listRepoOps() -> 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("com.atproto.space.listRepoOps"), + defs: { + let mut map = BTreeMap::new(); + map.insert( + SmolStr::new_static("main"), + LexUserType::XrpcQuery(LexXrpcQuery { + parameters: Some( + LexXrpcQueryParameter::Params(LexXrpcParameters { + required: Some( + vec![ + SmolStr::new_static("space"), SmolStr::new_static("repo") + ], + ), + properties: { + #[allow(unused_mut)] + let mut map = BTreeMap::new(); + map.insert( + SmolStr::new_static("cursor"), + LexXrpcParametersProperty::String(LexString { + description: Some( + CowStr::new_static( + "Opaque pagination cursor from a previous response. Takes precedence over `since` when both are supplied.", + ), + ), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("excludeValues"), + LexXrpcParametersProperty::Boolean(LexBoolean { + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("limit"), + LexXrpcParametersProperty::Integer(LexInteger { + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("repo"), + LexXrpcParametersProperty::String(LexString { + description: Some( + CowStr::new_static( + "The DID of the account whose oplog to retrieve.", + ), + ), + format: Some(LexStringFormat::Did), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("since"), + LexXrpcParametersProperty::String(LexString { + description: Some( + CowStr::new_static( + "Return operations after this revision. The caller's own sync position; use `cursor` to continue a paginated response.", + ), + ), + format: Some(LexStringFormat::Tid), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("space"), + LexXrpcParametersProperty::String(LexString { + description: Some( + CowStr::new_static("Reference to the space."), + ), + format: Some(LexStringFormat::SpaceRef), + ..Default::default() + }), + ); + map + }, + ..Default::default() + }), + ), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("opEntry"), + LexUserType::Object(LexObject { + description: Some( + CowStr::new_static( + "A single operation in a permissioned repo's oplog. cid is null for deletes; prev is null for creates. Operations sharing the same rev belong to the same batch. value carries the record's current value for creates and updates, unless excludeValues was set or the value is stale (superseded by a later operation).", + ), + ), + required: Some( + vec![ + SmolStr::new_static("rev"), + SmolStr::new_static("collection"), + SmolStr::new_static("rkey"), SmolStr::new_static("cid"), + SmolStr::new_static("prev") + ], + ), + properties: { + #[allow(unused_mut)] + let mut map = BTreeMap::new(); + map.insert( + SmolStr::new_static("cid"), + LexObjectProperty::String(LexString { + format: Some(LexStringFormat::Cid), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("collection"), + LexObjectProperty::String(LexString { + format: Some(LexStringFormat::Nsid), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("prev"), + LexObjectProperty::String(LexString { + format: Some(LexStringFormat::Cid), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("rev"), + LexObjectProperty::String(LexString { + format: Some(LexStringFormat::Tid), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("rkey"), + LexObjectProperty::String(LexString { + format: Some(LexStringFormat::RecordKey), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("value"), + LexObjectProperty::Unknown(LexUnknown { + ..Default::default() + }), + ); + map + }, + ..Default::default() + }), + ); + map + }, + ..Default::default() + } +} diff --git a/crates/jacquard-api/src/com_atproto/space/list_repos.rs b/crates/jacquard-api/src/com_atproto/space/list_repos.rs new file mode 100644 index 000000000..372e78288 --- /dev/null +++ b/crates/jacquard-api/src/com_atproto/space/list_repos.rs @@ -0,0 +1,566 @@ +// @generated by jacquard-lexicon. DO NOT EDIT. +// +// Lexicon: com.atproto.space.listRepos +// +// 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::deps::bytes::Bytes; +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::aturi::AtSpaceUri; +use jacquard_common::types::string::{Did, Tid}; +use jacquard_common::types::value::Data; +use jacquard_derive::{IntoStatic, open_union}; +use jacquard_lexicon::lexicon::LexiconDoc; +use jacquard_lexicon::schema::LexiconSchema; + +use crate::com_atproto::space::list_repos; +#[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", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct ListRepos { + #[serde(skip_serializing_if = "Option::is_none")] + pub cursor: Option, + /// Defaults to `100`. Min: 1. Max: 1000. + #[serde(default = "_default_limit")] + #[serde(skip_serializing_if = "Option::is_none")] + pub limit: Option, + pub space: AtSpaceUri, +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct ListReposOutput { + #[serde(skip_serializing_if = "Option::is_none")] + pub cursor: Option, + pub repos: Vec>, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +#[derive( + Serialize, Deserialize, Debug, Clone, PartialEq, Eq, thiserror::Error, miette::Diagnostic, +)] +#[serde(tag = "error", content = "message")] +pub enum ListReposError { + #[serde(rename = "SpaceNotFound")] + SpaceNotFound(Option), + /// Catch-all for unknown error codes. + #[serde(untagged)] + Other { + error: SmolStr, + message: Option, + }, +} + +impl core::fmt::Display for ListReposError { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + match self { + Self::SpaceNotFound(msg) => { + write!(f, "SpaceNotFound")?; + if let Some(msg) = msg { + write!(f, ": {}", msg)?; + } + Ok(()) + } + Self::Other { error, message } => { + write!(f, "{}", error)?; + if let Some(msg) = message { + write!(f, ": {}", msg)?; + } + Ok(()) + } + } + } +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct Repo { + ///The DID of a repo that holds data in the space. + pub did: Did, + ///The repo's current commit hash (sha256 of the LtHash state), as last reported to the authority. + #[serde(with = "jacquard_common::serde_bytes_helper")] + pub hash: Bytes, + ///The repo's current revision (TID), as last reported to the authority. May lag the repo host, which is the source of truth. + pub rev: Tid, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +/** Response marker for the `com.atproto.space.listRepos` query. + +Implements `jacquard_common::xrpc::XrpcResp`; successful bodies decode as `Self::Output`, which is `ListReposOutput` for this endpoint.*/ +pub struct ListReposResponse; +impl jacquard_common::xrpc::XrpcResp for ListReposResponse { + const NSID: &'static str = "com.atproto.space.listRepos"; + const ENCODING: &'static str = "application/json"; + type Output = ListReposOutput; + type Err = ListReposError; +} + +impl jacquard_common::xrpc::XrpcRequest for ListRepos { + const NSID: &'static str = "com.atproto.space.listRepos"; + const METHOD: jacquard_common::xrpc::XrpcMethod = jacquard_common::xrpc::XrpcMethod::Query; + type Response = ListReposResponse; +} + +/** Endpoint marker for the `com.atproto.space.listRepos` query. + +Path: `/xrpc/com.atproto.space.listRepos`. The request payload type is `ListRepos`; send that request with `jacquard::Client` or use this marker through lower-level `XrpcEndpoint` APIs.*/ +pub struct ListReposRequest; +impl jacquard_common::xrpc::XrpcEndpoint for ListReposRequest { + const PATH: &'static str = "/xrpc/com.atproto.space.listRepos"; + const METHOD: jacquard_common::xrpc::XrpcMethod = jacquard_common::xrpc::XrpcMethod::Query; + type Request = ListRepos; + type Response = ListReposResponse; +} + +impl LexiconSchema for Repo { + fn nsid() -> &'static str { + "com.atproto.space.listRepos" + } + fn def_name() -> &'static str { + "repo" + } + fn lexicon_doc() -> LexiconDoc<'static> { + lexicon_doc_com_atproto_space_listRepos() + } + fn validate(&self) -> Result<(), ConstraintError> { + Ok(()) + } +} + +fn _default_limit() -> Option { + Some(100i64) +} + +pub mod list_repos_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 Space; + } + /// Empty state - all required fields are unset + pub struct Empty(()); + impl sealed::Sealed for Empty {} + impl State for Empty { + type Space = Unset; + } + ///State transition - sets the `space` field to Set + pub struct SetSpace(PhantomData St>); + impl sealed::Sealed for SetSpace {} + impl State for SetSpace { + type Space = Set; + } + /// Marker types for field names + #[allow(non_camel_case_types)] + pub mod members { + ///Marker type for the `space` field + pub struct space(()); + } +} + +/// Builder for constructing an instance of this type. +pub struct ListReposBuilder { + _state: PhantomData St>, + _fields: (Option, Option, Option>), + _type: PhantomData S>, +} + +impl ListRepos { + /// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed + pub fn new() -> ListReposBuilder { + ListReposBuilder::new() + } +} + +impl ListRepos { + /// Create a new builder for this type + pub fn builder() -> ListReposBuilder { + ListReposBuilder::builder() + } +} + +impl ListReposBuilder { + /// Create a new builder with all fields unset, using the default string type, if needed + pub fn new() -> Self { + ListReposBuilder { + _state: PhantomData, + _fields: (None, None, None), + _type: PhantomData, + } + } +} + +impl ListReposBuilder { + /// Create a new builder with all fields unset + pub fn builder() -> Self { + ListReposBuilder { + _state: PhantomData, + _fields: (None, None, None), + _type: PhantomData, + } + } +} + +impl ListReposBuilder { + /// Set the `cursor` field (optional) + pub fn cursor(mut self, value: impl Into>) -> Self { + self._fields.0 = value.into(); + self + } + /// Set the `cursor` field to an Option value (optional) + pub fn maybe_cursor(mut self, value: Option) -> Self { + self._fields.0 = value; + self + } +} + +impl ListReposBuilder { + /// Set the `limit` field (optional) + pub fn limit(mut self, value: impl Into>) -> Self { + self._fields.1 = value.into(); + self + } + /// Set the `limit` field to an Option value (optional) + pub fn maybe_limit(mut self, value: Option) -> Self { + self._fields.1 = value; + self + } +} + +impl ListReposBuilder +where + St: list_repos_state::State, + St::Space: list_repos_state::IsUnset, +{ + /// Set the `space` field (required) + pub fn space( + mut self, + value: impl Into>, + ) -> ListReposBuilder, S> { + self._fields.2 = Option::Some(value.into()); + ListReposBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl ListReposBuilder +where + St: list_repos_state::State, + St::Space: list_repos_state::IsSet, +{ + /// Build the final struct. + pub fn build(self) -> ListRepos { + ListRepos { + cursor: self._fields.0, + limit: self._fields.1, + space: self._fields.2.unwrap(), + } + } +} + +pub mod repo_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 Did; + type Hash; + type Rev; + } + /// Empty state - all required fields are unset + pub struct Empty(()); + impl sealed::Sealed for Empty {} + impl State for Empty { + type Did = Unset; + type Hash = Unset; + type Rev = Unset; + } + ///State transition - sets the `did` field to Set + pub struct SetDid(PhantomData St>); + impl sealed::Sealed for SetDid {} + impl State for SetDid { + type Did = Set; + type Hash = St::Hash; + type Rev = St::Rev; + } + ///State transition - sets the `hash` field to Set + pub struct SetHash(PhantomData St>); + impl sealed::Sealed for SetHash {} + impl State for SetHash { + type Did = St::Did; + type Hash = Set; + type Rev = St::Rev; + } + ///State transition - sets the `rev` field to Set + pub struct SetRev(PhantomData St>); + impl sealed::Sealed for SetRev {} + impl State for SetRev { + type Did = St::Did; + type Hash = St::Hash; + type Rev = Set; + } + /// Marker types for field names + #[allow(non_camel_case_types)] + pub mod members { + ///Marker type for the `did` field + pub struct did(()); + ///Marker type for the `hash` field + pub struct hash(()); + ///Marker type for the `rev` field + pub struct rev(()); + } +} + +/// Builder for constructing an instance of this type. +pub struct RepoBuilder { + _state: PhantomData St>, + _fields: (Option>, Option, Option), + _type: PhantomData S>, +} + +impl Repo { + /// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed + pub fn new() -> RepoBuilder { + RepoBuilder::new() + } +} + +impl Repo { + /// Create a new builder for this type + pub fn builder() -> RepoBuilder { + RepoBuilder::builder() + } +} + +impl RepoBuilder { + /// Create a new builder with all fields unset, using the default string type, if needed + pub fn new() -> Self { + RepoBuilder { + _state: PhantomData, + _fields: (None, None, None), + _type: PhantomData, + } + } +} + +impl RepoBuilder { + /// Create a new builder with all fields unset + pub fn builder() -> Self { + RepoBuilder { + _state: PhantomData, + _fields: (None, None, None), + _type: PhantomData, + } + } +} + +impl RepoBuilder +where + St: repo_state::State, + St::Did: repo_state::IsUnset, +{ + /// Set the `did` field (required) + pub fn did(mut self, value: impl Into>) -> RepoBuilder, S> { + self._fields.0 = Option::Some(value.into()); + RepoBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl RepoBuilder +where + St: repo_state::State, + St::Hash: repo_state::IsUnset, +{ + /// Set the `hash` field (required) + pub fn hash(mut self, value: impl Into) -> RepoBuilder, S> { + self._fields.1 = Option::Some(value.into()); + RepoBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl RepoBuilder +where + St: repo_state::State, + St::Rev: repo_state::IsUnset, +{ + /// Set the `rev` field (required) + pub fn rev(mut self, value: impl Into) -> RepoBuilder, S> { + self._fields.2 = Option::Some(value.into()); + RepoBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl RepoBuilder +where + St: repo_state::State, + St::Did: repo_state::IsSet, + St::Hash: repo_state::IsSet, + St::Rev: repo_state::IsSet, +{ + /// Build the final struct. + pub fn build(self) -> Repo { + Repo { + did: self._fields.0.unwrap(), + hash: self._fields.1.unwrap(), + rev: 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>) -> Repo { + Repo { + did: self._fields.0.unwrap(), + hash: self._fields.1.unwrap(), + rev: self._fields.2.unwrap(), + extra_data: Some(extra_data), + } + } +} + +fn lexicon_doc_com_atproto_space_listRepos() -> 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("com.atproto.space.listRepos"), + defs: { + let mut map = BTreeMap::new(); + map.insert( + SmolStr::new_static("main"), + LexUserType::XrpcQuery(LexXrpcQuery { + parameters: Some(LexXrpcQueryParameter::Params(LexXrpcParameters { + required: Some(vec![SmolStr::new_static("space")]), + properties: { + #[allow(unused_mut)] + let mut map = BTreeMap::new(); + map.insert( + SmolStr::new_static("cursor"), + LexXrpcParametersProperty::String(LexString { + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("limit"), + LexXrpcParametersProperty::Integer(LexInteger { + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("space"), + LexXrpcParametersProperty::String(LexString { + description: Some(CowStr::new_static( + "Reference to the space.", + )), + format: Some(LexStringFormat::SpaceRef), + ..Default::default() + }), + ); + map + }, + ..Default::default() + })), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("repo"), + LexUserType::Object(LexObject { + required: Some( + vec![ + SmolStr::new_static("did"), SmolStr::new_static("rev"), + SmolStr::new_static("hash") + ], + ), + properties: { + #[allow(unused_mut)] + let mut map = BTreeMap::new(); + map.insert( + SmolStr::new_static("did"), + LexObjectProperty::String(LexString { + description: Some( + CowStr::new_static( + "The DID of a repo that holds data in the space.", + ), + ), + format: Some(LexStringFormat::Did), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("hash"), + LexObjectProperty::Bytes(LexBytes { ..Default::default() }), + ); + map.insert( + SmolStr::new_static("rev"), + LexObjectProperty::String(LexString { + description: Some( + CowStr::new_static( + "The repo's current revision (TID), as last reported to the authority. May lag the repo host, which is the source of truth.", + ), + ), + format: Some(LexStringFormat::Tid), + ..Default::default() + }), + ); + map + }, + ..Default::default() + }), + ); + map + }, + ..Default::default() + } +} diff --git a/crates/jacquard-api/src/com_atproto/space/list_spaces.rs b/crates/jacquard-api/src/com_atproto/space/list_spaces.rs new file mode 100644 index 000000000..21da74135 --- /dev/null +++ b/crates/jacquard-api/src/com_atproto/space/list_spaces.rs @@ -0,0 +1,444 @@ +// @generated by jacquard-lexicon. DO NOT EDIT. +// +// Lexicon: com.atproto.space.listSpaces +// +// 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::aturi::AtSpaceUri; +use jacquard_common::types::string::{Did, Nsid}; +use jacquard_common::types::value::Data; +use jacquard_derive::IntoStatic; +use jacquard_lexicon::lexicon::LexiconDoc; +use jacquard_lexicon::schema::LexiconSchema; + +use crate::com_atproto::space::list_spaces; +#[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", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct ListSpaces { + #[serde(skip_serializing_if = "Option::is_none")] + pub cursor: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub did: Option>, + /// Defaults to `50`. Min: 1. Max: 100. + #[serde(default = "_default_limit")] + #[serde(skip_serializing_if = "Option::is_none")] + pub limit: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub r#type: Option>, +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct ListSpacesOutput { + #[serde(skip_serializing_if = "Option::is_none")] + pub cursor: Option, + pub spaces: Vec>, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct SpaceView { + ///URI of the space. + pub uri: AtSpaceUri, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +/** Response marker for the `com.atproto.space.listSpaces` query. + +Implements `jacquard_common::xrpc::XrpcResp`; successful bodies decode as `Self::Output`, which is `ListSpacesOutput` for this endpoint.*/ +pub struct ListSpacesResponse; +impl jacquard_common::xrpc::XrpcResp for ListSpacesResponse { + const NSID: &'static str = "com.atproto.space.listSpaces"; + const ENCODING: &'static str = "application/json"; + type Output = ListSpacesOutput; + type Err = jacquard_common::xrpc::GenericError; +} + +impl jacquard_common::xrpc::XrpcRequest for ListSpaces { + const NSID: &'static str = "com.atproto.space.listSpaces"; + const METHOD: jacquard_common::xrpc::XrpcMethod = jacquard_common::xrpc::XrpcMethod::Query; + type Response = ListSpacesResponse; +} + +/** Endpoint marker for the `com.atproto.space.listSpaces` query. + +Path: `/xrpc/com.atproto.space.listSpaces`. The request payload type is `ListSpaces`; send that request with `jacquard::Client` or use this marker through lower-level `XrpcEndpoint` APIs.*/ +pub struct ListSpacesRequest; +impl jacquard_common::xrpc::XrpcEndpoint for ListSpacesRequest { + const PATH: &'static str = "/xrpc/com.atproto.space.listSpaces"; + const METHOD: jacquard_common::xrpc::XrpcMethod = jacquard_common::xrpc::XrpcMethod::Query; + type Request = ListSpaces; + type Response = ListSpacesResponse; +} + +impl LexiconSchema for SpaceView { + fn nsid() -> &'static str { + "com.atproto.space.listSpaces" + } + fn def_name() -> &'static str { + "spaceView" + } + fn lexicon_doc() -> LexiconDoc<'static> { + lexicon_doc_com_atproto_space_listSpaces() + } + fn validate(&self) -> Result<(), ConstraintError> { + Ok(()) + } +} + +fn _default_limit() -> Option { + Some(50i64) +} + +pub mod list_spaces_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 {} + /// Empty state - all required fields are unset + pub struct Empty(()); + impl sealed::Sealed for Empty {} + impl State for Empty {} + /// Marker types for field names + #[allow(non_camel_case_types)] + pub mod members {} +} + +/// Builder for constructing an instance of this type. +pub struct ListSpacesBuilder { + _state: PhantomData St>, + _fields: (Option, Option>, Option, Option>), + _type: PhantomData S>, +} + +impl ListSpaces { + /// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed + pub fn new() -> ListSpacesBuilder { + ListSpacesBuilder::new() + } +} + +impl ListSpaces { + /// Create a new builder for this type + pub fn builder() -> ListSpacesBuilder { + ListSpacesBuilder::builder() + } +} + +impl ListSpacesBuilder { + /// Create a new builder with all fields unset, using the default string type, if needed + pub fn new() -> Self { + ListSpacesBuilder { + _state: PhantomData, + _fields: (None, None, None, None), + _type: PhantomData, + } + } +} + +impl ListSpacesBuilder { + /// Create a new builder with all fields unset + pub fn builder() -> Self { + ListSpacesBuilder { + _state: PhantomData, + _fields: (None, None, None, None), + _type: PhantomData, + } + } +} + +impl ListSpacesBuilder { + /// Set the `cursor` field (optional) + pub fn cursor(mut self, value: impl Into>) -> Self { + self._fields.0 = value.into(); + self + } + /// Set the `cursor` field to an Option value (optional) + pub fn maybe_cursor(mut self, value: Option) -> Self { + self._fields.0 = value; + self + } +} + +impl ListSpacesBuilder { + /// Set the `did` field (optional) + pub fn did(mut self, value: impl Into>>) -> Self { + self._fields.1 = value.into(); + self + } + /// Set the `did` field to an Option value (optional) + pub fn maybe_did(mut self, value: Option>) -> Self { + self._fields.1 = value; + self + } +} + +impl ListSpacesBuilder { + /// Set the `limit` field (optional) + pub fn limit(mut self, value: impl Into>) -> Self { + self._fields.2 = value.into(); + self + } + /// Set the `limit` field to an Option value (optional) + pub fn maybe_limit(mut self, value: Option) -> Self { + self._fields.2 = value; + self + } +} + +impl ListSpacesBuilder { + /// Set the `type` field (optional) + pub fn r#type(mut self, value: impl Into>>) -> Self { + self._fields.3 = value.into(); + self + } + /// Set the `type` field to an Option value (optional) + pub fn maybe_type(mut self, value: Option>) -> Self { + self._fields.3 = value; + self + } +} + +impl ListSpacesBuilder +where + St: list_spaces_state::State, +{ + /// Build the final struct. + pub fn build(self) -> ListSpaces { + ListSpaces { + cursor: self._fields.0, + did: self._fields.1, + limit: self._fields.2, + r#type: self._fields.3, + } + } +} + +pub mod space_view_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 Uri; + } + /// Empty state - all required fields are unset + pub struct Empty(()); + impl sealed::Sealed for Empty {} + impl State for Empty { + type Uri = Unset; + } + ///State transition - sets the `uri` field to Set + pub struct SetUri(PhantomData St>); + impl sealed::Sealed for SetUri {} + impl State for SetUri { + type Uri = Set; + } + /// Marker types for field names + #[allow(non_camel_case_types)] + pub mod members { + ///Marker type for the `uri` field + pub struct uri(()); + } +} + +/// Builder for constructing an instance of this type. +pub struct SpaceViewBuilder { + _state: PhantomData St>, + _fields: (Option>,), + _type: PhantomData S>, +} + +impl SpaceView { + /// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed + pub fn new() -> SpaceViewBuilder { + SpaceViewBuilder::new() + } +} + +impl SpaceView { + /// Create a new builder for this type + pub fn builder() -> SpaceViewBuilder { + SpaceViewBuilder::builder() + } +} + +impl SpaceViewBuilder { + /// Create a new builder with all fields unset, using the default string type, if needed + pub fn new() -> Self { + SpaceViewBuilder { + _state: PhantomData, + _fields: (None,), + _type: PhantomData, + } + } +} + +impl SpaceViewBuilder { + /// Create a new builder with all fields unset + pub fn builder() -> Self { + SpaceViewBuilder { + _state: PhantomData, + _fields: (None,), + _type: PhantomData, + } + } +} + +impl SpaceViewBuilder +where + St: space_view_state::State, + St::Uri: space_view_state::IsUnset, +{ + /// Set the `uri` field (required) + pub fn uri( + mut self, + value: impl Into>, + ) -> SpaceViewBuilder, S> { + self._fields.0 = Option::Some(value.into()); + SpaceViewBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl SpaceViewBuilder +where + St: space_view_state::State, + St::Uri: space_view_state::IsSet, +{ + /// Build the final struct. + pub fn build(self) -> SpaceView { + SpaceView { + uri: self._fields.0.unwrap(), + extra_data: Default::default(), + } + } + /// Build the final struct with custom extra_data. + pub fn build_with_data(self, extra_data: BTreeMap>) -> SpaceView { + SpaceView { + uri: self._fields.0.unwrap(), + extra_data: Some(extra_data), + } + } +} + +fn lexicon_doc_com_atproto_space_listSpaces() -> 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("com.atproto.space.listSpaces"), + defs: { + let mut map = BTreeMap::new(); + map.insert( + SmolStr::new_static("main"), + LexUserType::XrpcQuery(LexXrpcQuery { + parameters: Some(LexXrpcQueryParameter::Params(LexXrpcParameters { + properties: { + #[allow(unused_mut)] + let mut map = BTreeMap::new(); + map.insert( + SmolStr::new_static("cursor"), + LexXrpcParametersProperty::String(LexString { + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("did"), + LexXrpcParametersProperty::String(LexString { + description: Some(CowStr::new_static( + "Filter to spaces under this authority DID.", + )), + format: Some(LexStringFormat::Did), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("limit"), + LexXrpcParametersProperty::Integer(LexInteger { + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("type"), + LexXrpcParametersProperty::String(LexString { + description: Some(CowStr::new_static( + "Filter to spaces of this type.", + )), + format: Some(LexStringFormat::Nsid), + ..Default::default() + }), + ); + map + }, + ..Default::default() + })), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("spaceView"), + LexUserType::Object(LexObject { + required: Some(vec![SmolStr::new_static("uri")]), + properties: { + #[allow(unused_mut)] + let mut map = BTreeMap::new(); + map.insert( + SmolStr::new_static("uri"), + LexObjectProperty::String(LexString { + description: Some(CowStr::new_static("URI of the space.")), + format: Some(LexStringFormat::SpaceRef), + ..Default::default() + }), + ); + map + }, + ..Default::default() + }), + ); + map + }, + ..Default::default() + } +} diff --git a/crates/jacquard-api/src/com_atproto/space/notify_space_deleted.rs b/crates/jacquard-api/src/com_atproto/space/notify_space_deleted.rs new file mode 100644 index 000000000..34a10141d --- /dev/null +++ b/crates/jacquard-api/src/com_atproto/space/notify_space_deleted.rs @@ -0,0 +1,176 @@ +// @generated by jacquard-lexicon. DO NOT EDIT. +// +// Lexicon: com.atproto.space.notifySpaceDeleted +// +// 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::deps::smol_str::SmolStr; +use jacquard_common::types::aturi::AtSpaceUri; +use jacquard_common::types::value::Data; +use jacquard_common::{BosStr, DefaultStr, FromStaticStr}; +use jacquard_derive::IntoStatic; +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct NotifySpaceDeleted { + ///Reference to the deleted space. + pub space: AtSpaceUri, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +/** Response marker for the `com.atproto.space.notifySpaceDeleted` procedure. + +Implements `jacquard_common::xrpc::XrpcResp`; successful bodies decode as `Self::Output`, which is `()` for this endpoint.*/ +pub struct NotifySpaceDeletedResponse; +impl jacquard_common::xrpc::XrpcResp for NotifySpaceDeletedResponse { + const NSID: &'static str = "com.atproto.space.notifySpaceDeleted"; + const ENCODING: &'static str = "application/json"; + type Output = (); + type Err = jacquard_common::xrpc::GenericError; +} + +impl jacquard_common::xrpc::XrpcRequest for NotifySpaceDeleted { + const NSID: &'static str = "com.atproto.space.notifySpaceDeleted"; + const METHOD: jacquard_common::xrpc::XrpcMethod = + jacquard_common::xrpc::XrpcMethod::Procedure("application/json"); + type Response = NotifySpaceDeletedResponse; +} + +/** Endpoint marker for the `com.atproto.space.notifySpaceDeleted` procedure. + +Path: `/xrpc/com.atproto.space.notifySpaceDeleted`. The request payload type is `NotifySpaceDeleted`; send that request with `jacquard::Client` or use this marker through lower-level `XrpcEndpoint` APIs.*/ +pub struct NotifySpaceDeletedRequest; +impl jacquard_common::xrpc::XrpcEndpoint for NotifySpaceDeletedRequest { + const PATH: &'static str = "/xrpc/com.atproto.space.notifySpaceDeleted"; + const METHOD: jacquard_common::xrpc::XrpcMethod = + jacquard_common::xrpc::XrpcMethod::Procedure("application/json"); + type Request = NotifySpaceDeleted; + type Response = NotifySpaceDeletedResponse; +} + +pub mod notify_space_deleted_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 Space; + } + /// Empty state - all required fields are unset + pub struct Empty(()); + impl sealed::Sealed for Empty {} + impl State for Empty { + type Space = Unset; + } + ///State transition - sets the `space` field to Set + pub struct SetSpace(PhantomData St>); + impl sealed::Sealed for SetSpace {} + impl State for SetSpace { + type Space = Set; + } + /// Marker types for field names + #[allow(non_camel_case_types)] + pub mod members { + ///Marker type for the `space` field + pub struct space(()); + } +} + +/// Builder for constructing an instance of this type. +pub struct NotifySpaceDeletedBuilder +{ + _state: PhantomData St>, + _fields: (Option>,), + _type: PhantomData S>, +} + +impl NotifySpaceDeleted { + /// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed + pub fn new() -> NotifySpaceDeletedBuilder { + NotifySpaceDeletedBuilder::new() + } +} + +impl NotifySpaceDeleted { + /// Create a new builder for this type + pub fn builder() -> NotifySpaceDeletedBuilder { + NotifySpaceDeletedBuilder::builder() + } +} + +impl NotifySpaceDeletedBuilder { + /// Create a new builder with all fields unset, using the default string type, if needed + pub fn new() -> Self { + NotifySpaceDeletedBuilder { + _state: PhantomData, + _fields: (None,), + _type: PhantomData, + } + } +} + +impl NotifySpaceDeletedBuilder { + /// Create a new builder with all fields unset + pub fn builder() -> Self { + NotifySpaceDeletedBuilder { + _state: PhantomData, + _fields: (None,), + _type: PhantomData, + } + } +} + +impl NotifySpaceDeletedBuilder +where + St: notify_space_deleted_state::State, + St::Space: notify_space_deleted_state::IsUnset, +{ + /// Set the `space` field (required) + pub fn space( + mut self, + value: impl Into>, + ) -> NotifySpaceDeletedBuilder, S> { + self._fields.0 = Option::Some(value.into()); + NotifySpaceDeletedBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl NotifySpaceDeletedBuilder +where + St: notify_space_deleted_state::State, + St::Space: notify_space_deleted_state::IsSet, +{ + /// Build the final struct. + pub fn build(self) -> NotifySpaceDeleted { + NotifySpaceDeleted { + space: self._fields.0.unwrap(), + extra_data: Default::default(), + } + } + /// Build the final struct with custom extra_data. + pub fn build_with_data(self, extra_data: BTreeMap>) -> NotifySpaceDeleted { + NotifySpaceDeleted { + space: self._fields.0.unwrap(), + extra_data: Some(extra_data), + } + } +} diff --git a/crates/jacquard-api/src/com_atproto/space/notify_write.rs b/crates/jacquard-api/src/com_atproto/space/notify_write.rs new file mode 100644 index 000000000..b5095f5ad --- /dev/null +++ b/crates/jacquard-api/src/com_atproto/space/notify_write.rs @@ -0,0 +1,297 @@ +// @generated by jacquard-lexicon. DO NOT EDIT. +// +// Lexicon: com.atproto.space.notifyWrite +// +// 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::deps::bytes::Bytes; +use jacquard_common::deps::smol_str::SmolStr; +use jacquard_common::types::aturi::AtSpaceUri; +use jacquard_common::types::string::{Did, Tid}; +use jacquard_common::types::value::Data; +use jacquard_common::{BosStr, DefaultStr, FromStaticStr}; +use jacquard_derive::IntoStatic; +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct NotifyWrite { + ///The repo's current commit hash (sha256 of the LtHash state) after the write. Lets the space host maintain each repo's hash for listRepos. + #[serde(with = "jacquard_common::serde_bytes_helper")] + pub hash: Bytes, + ///The DID of the account whose repo advanced. + pub repo: Did, + ///The revision of the write. + pub rev: Tid, + ///Reference to the space. + pub space: AtSpaceUri, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +/** Response marker for the `com.atproto.space.notifyWrite` procedure. + +Implements `jacquard_common::xrpc::XrpcResp`; successful bodies decode as `Self::Output`, which is `()` for this endpoint.*/ +pub struct NotifyWriteResponse; +impl jacquard_common::xrpc::XrpcResp for NotifyWriteResponse { + const NSID: &'static str = "com.atproto.space.notifyWrite"; + const ENCODING: &'static str = "application/json"; + type Output = (); + type Err = jacquard_common::xrpc::GenericError; +} + +impl jacquard_common::xrpc::XrpcRequest for NotifyWrite { + const NSID: &'static str = "com.atproto.space.notifyWrite"; + const METHOD: jacquard_common::xrpc::XrpcMethod = + jacquard_common::xrpc::XrpcMethod::Procedure("application/json"); + type Response = NotifyWriteResponse; +} + +/** Endpoint marker for the `com.atproto.space.notifyWrite` procedure. + +Path: `/xrpc/com.atproto.space.notifyWrite`. The request payload type is `NotifyWrite`; send that request with `jacquard::Client` or use this marker through lower-level `XrpcEndpoint` APIs.*/ +pub struct NotifyWriteRequest; +impl jacquard_common::xrpc::XrpcEndpoint for NotifyWriteRequest { + const PATH: &'static str = "/xrpc/com.atproto.space.notifyWrite"; + const METHOD: jacquard_common::xrpc::XrpcMethod = + jacquard_common::xrpc::XrpcMethod::Procedure("application/json"); + type Request = NotifyWrite; + type Response = NotifyWriteResponse; +} + +pub mod notify_write_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 Hash; + type Repo; + type Rev; + type Space; + } + /// Empty state - all required fields are unset + pub struct Empty(()); + impl sealed::Sealed for Empty {} + impl State for Empty { + type Hash = Unset; + type Repo = Unset; + type Rev = Unset; + type Space = Unset; + } + ///State transition - sets the `hash` field to Set + pub struct SetHash(PhantomData St>); + impl sealed::Sealed for SetHash {} + impl State for SetHash { + type Hash = Set; + type Repo = St::Repo; + type Rev = St::Rev; + type Space = St::Space; + } + ///State transition - sets the `repo` field to Set + pub struct SetRepo(PhantomData St>); + impl sealed::Sealed for SetRepo {} + impl State for SetRepo { + type Hash = St::Hash; + type Repo = Set; + type Rev = St::Rev; + type Space = St::Space; + } + ///State transition - sets the `rev` field to Set + pub struct SetRev(PhantomData St>); + impl sealed::Sealed for SetRev {} + impl State for SetRev { + type Hash = St::Hash; + type Repo = St::Repo; + type Rev = Set; + type Space = St::Space; + } + ///State transition - sets the `space` field to Set + pub struct SetSpace(PhantomData St>); + impl sealed::Sealed for SetSpace {} + impl State for SetSpace { + type Hash = St::Hash; + type Repo = St::Repo; + type Rev = St::Rev; + type Space = Set; + } + /// Marker types for field names + #[allow(non_camel_case_types)] + pub mod members { + ///Marker type for the `hash` field + pub struct hash(()); + ///Marker type for the `repo` field + pub struct repo(()); + ///Marker type for the `rev` field + pub struct rev(()); + ///Marker type for the `space` field + pub struct space(()); + } +} + +/// Builder for constructing an instance of this type. +pub struct NotifyWriteBuilder { + _state: PhantomData St>, + _fields: ( + Option, + Option>, + Option, + Option>, + ), + _type: PhantomData S>, +} + +impl NotifyWrite { + /// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed + pub fn new() -> NotifyWriteBuilder { + NotifyWriteBuilder::new() + } +} + +impl NotifyWrite { + /// Create a new builder for this type + pub fn builder() -> NotifyWriteBuilder { + NotifyWriteBuilder::builder() + } +} + +impl NotifyWriteBuilder { + /// Create a new builder with all fields unset, using the default string type, if needed + pub fn new() -> Self { + NotifyWriteBuilder { + _state: PhantomData, + _fields: (None, None, None, None), + _type: PhantomData, + } + } +} + +impl NotifyWriteBuilder { + /// Create a new builder with all fields unset + pub fn builder() -> Self { + NotifyWriteBuilder { + _state: PhantomData, + _fields: (None, None, None, None), + _type: PhantomData, + } + } +} + +impl NotifyWriteBuilder +where + St: notify_write_state::State, + St::Hash: notify_write_state::IsUnset, +{ + /// Set the `hash` field (required) + pub fn hash( + mut self, + value: impl Into, + ) -> NotifyWriteBuilder, S> { + self._fields.0 = Option::Some(value.into()); + NotifyWriteBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl NotifyWriteBuilder +where + St: notify_write_state::State, + St::Repo: notify_write_state::IsUnset, +{ + /// Set the `repo` field (required) + pub fn repo( + mut self, + value: impl Into>, + ) -> NotifyWriteBuilder, S> { + self._fields.1 = Option::Some(value.into()); + NotifyWriteBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl NotifyWriteBuilder +where + St: notify_write_state::State, + St::Rev: notify_write_state::IsUnset, +{ + /// Set the `rev` field (required) + pub fn rev( + mut self, + value: impl Into, + ) -> NotifyWriteBuilder, S> { + self._fields.2 = Option::Some(value.into()); + NotifyWriteBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl NotifyWriteBuilder +where + St: notify_write_state::State, + St::Space: notify_write_state::IsUnset, +{ + /// Set the `space` field (required) + pub fn space( + mut self, + value: impl Into>, + ) -> NotifyWriteBuilder, S> { + self._fields.3 = Option::Some(value.into()); + NotifyWriteBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl NotifyWriteBuilder +where + St: notify_write_state::State, + St::Hash: notify_write_state::IsSet, + St::Repo: notify_write_state::IsSet, + St::Rev: notify_write_state::IsSet, + St::Space: notify_write_state::IsSet, +{ + /// Build the final struct. + pub fn build(self) -> NotifyWrite { + NotifyWrite { + hash: self._fields.0.unwrap(), + repo: self._fields.1.unwrap(), + rev: self._fields.2.unwrap(), + space: self._fields.3.unwrap(), + extra_data: Default::default(), + } + } + /// Build the final struct with custom extra_data. + pub fn build_with_data(self, extra_data: BTreeMap>) -> NotifyWrite { + NotifyWrite { + hash: self._fields.0.unwrap(), + repo: self._fields.1.unwrap(), + rev: self._fields.2.unwrap(), + space: self._fields.3.unwrap(), + extra_data: Some(extra_data), + } + } +} diff --git a/crates/jacquard-api/src/com_atproto/space/put_record.rs b/crates/jacquard-api/src/com_atproto/space/put_record.rs new file mode 100644 index 000000000..5ceea8354 --- /dev/null +++ b/crates/jacquard-api/src/com_atproto/space/put_record.rs @@ -0,0 +1,487 @@ +// @generated by jacquard-lexicon. DO NOT EDIT. +// +// Lexicon: com.atproto.space.putRecord +// +// 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::deps::smol_str::SmolStr; +use jacquard_common::types::aturi::AtSpaceUri; +use jacquard_common::types::string::{AtUri, Cid, Did, Nsid, RecordKey, Rkey}; +use jacquard_common::types::value::Data; +use jacquard_common::{BosStr, CowStr, DefaultStr, FromStaticStr}; +use jacquard_derive::{IntoStatic, open_union}; +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct PutRecord { + ///The NSID of the record collection. + pub collection: Nsid, + ///The record to write. + pub record: Data, + ///The DID of the repo to write to (the authenticated member). + pub repo: Did, + ///The Record Key. + pub rkey: RecordKey>, + ///Reference to the space. + pub space: AtSpaceUri, + ///Can be set to 'false' to skip Lexicon schema validation of record data, 'true' to require it, or leave unset to validate only for known Lexicons. + #[serde(skip_serializing_if = "Option::is_none")] + pub validate: Option, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct PutRecordOutput { + pub cid: Cid, + ///URI of the written record. + pub uri: AtUri, + #[serde(skip_serializing_if = "Option::is_none")] + pub validation_status: Option>, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub enum PutRecordOutputValidationStatus { + Valid, + Unknown, + Other(S), +} + +impl PutRecordOutputValidationStatus { + pub fn as_str(&self) -> &str { + match self { + Self::Valid => "valid", + Self::Unknown => "unknown", + 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() { + "valid" => Self::Valid, + "unknown" => Self::Unknown, + _ => Self::Other(s), + } + } +} + +impl core::fmt::Display for PutRecordOutputValidationStatus { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!(f, "{}", self.as_str()) + } +} + +impl AsRef for PutRecordOutputValidationStatus { + fn as_ref(&self) -> &str { + self.as_str() + } +} + +impl Serialize for PutRecordOutputValidationStatus { + 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 PutRecordOutputValidationStatus { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = S::deserialize(deserializer)?; + Ok(Self::from_value(s)) + } +} + +impl Default for PutRecordOutputValidationStatus { + fn default() -> Self { + Self::Other(Default::default()) + } +} + +impl jacquard_common::IntoStatic for PutRecordOutputValidationStatus +where + S: BosStr + jacquard_common::IntoStatic, + S::Output: BosStr, +{ + type Output = PutRecordOutputValidationStatus; + fn into_static(self) -> Self::Output { + match self { + PutRecordOutputValidationStatus::Valid => PutRecordOutputValidationStatus::Valid, + PutRecordOutputValidationStatus::Unknown => PutRecordOutputValidationStatus::Unknown, + PutRecordOutputValidationStatus::Other(v) => { + PutRecordOutputValidationStatus::Other(v.into_static()) + } + } + } +} + +#[derive( + Serialize, Deserialize, Debug, Clone, PartialEq, Eq, thiserror::Error, miette::Diagnostic, +)] +#[serde(tag = "error", content = "message")] +pub enum PutRecordError { + #[serde(rename = "SpaceNotFound")] + SpaceNotFound(Option), + /// Catch-all for unknown error codes. + #[serde(untagged)] + Other { + error: SmolStr, + message: Option, + }, +} + +impl core::fmt::Display for PutRecordError { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + match self { + Self::SpaceNotFound(msg) => { + write!(f, "SpaceNotFound")?; + if let Some(msg) = msg { + write!(f, ": {}", msg)?; + } + Ok(()) + } + Self::Other { error, message } => { + write!(f, "{}", error)?; + if let Some(msg) = message { + write!(f, ": {}", msg)?; + } + Ok(()) + } + } + } +} + +/** Response marker for the `com.atproto.space.putRecord` procedure. + +Implements `jacquard_common::xrpc::XrpcResp`; successful bodies decode as `Self::Output`, which is `PutRecordOutput` for this endpoint.*/ +pub struct PutRecordResponse; +impl jacquard_common::xrpc::XrpcResp for PutRecordResponse { + const NSID: &'static str = "com.atproto.space.putRecord"; + const ENCODING: &'static str = "application/json"; + type Output = PutRecordOutput; + type Err = PutRecordError; +} + +impl jacquard_common::xrpc::XrpcRequest for PutRecord { + const NSID: &'static str = "com.atproto.space.putRecord"; + const METHOD: jacquard_common::xrpc::XrpcMethod = + jacquard_common::xrpc::XrpcMethod::Procedure("application/json"); + type Response = PutRecordResponse; +} + +/** Endpoint marker for the `com.atproto.space.putRecord` procedure. + +Path: `/xrpc/com.atproto.space.putRecord`. The request payload type is `PutRecord`; send that request with `jacquard::Client` or use this marker through lower-level `XrpcEndpoint` APIs.*/ +pub struct PutRecordRequest; +impl jacquard_common::xrpc::XrpcEndpoint for PutRecordRequest { + const PATH: &'static str = "/xrpc/com.atproto.space.putRecord"; + const METHOD: jacquard_common::xrpc::XrpcMethod = + jacquard_common::xrpc::XrpcMethod::Procedure("application/json"); + type Request = PutRecord; + type Response = PutRecordResponse; +} + +pub mod put_record_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 Collection; + type Record; + type Repo; + type Rkey; + type Space; + } + /// Empty state - all required fields are unset + pub struct Empty(()); + impl sealed::Sealed for Empty {} + impl State for Empty { + type Collection = Unset; + type Record = Unset; + type Repo = Unset; + type Rkey = Unset; + type Space = Unset; + } + ///State transition - sets the `collection` field to Set + pub struct SetCollection(PhantomData St>); + impl sealed::Sealed for SetCollection {} + impl State for SetCollection { + type Collection = Set; + type Record = St::Record; + type Repo = St::Repo; + type Rkey = St::Rkey; + type Space = St::Space; + } + ///State transition - sets the `record` field to Set + pub struct SetRecord(PhantomData St>); + impl sealed::Sealed for SetRecord {} + impl State for SetRecord { + type Collection = St::Collection; + type Record = Set; + type Repo = St::Repo; + type Rkey = St::Rkey; + type Space = St::Space; + } + ///State transition - sets the `repo` field to Set + pub struct SetRepo(PhantomData St>); + impl sealed::Sealed for SetRepo {} + impl State for SetRepo { + type Collection = St::Collection; + type Record = St::Record; + type Repo = Set; + type Rkey = St::Rkey; + type Space = St::Space; + } + ///State transition - sets the `rkey` field to Set + pub struct SetRkey(PhantomData St>); + impl sealed::Sealed for SetRkey {} + impl State for SetRkey { + type Collection = St::Collection; + type Record = St::Record; + type Repo = St::Repo; + type Rkey = Set; + type Space = St::Space; + } + ///State transition - sets the `space` field to Set + pub struct SetSpace(PhantomData St>); + impl sealed::Sealed for SetSpace {} + impl State for SetSpace { + type Collection = St::Collection; + type Record = St::Record; + type Repo = St::Repo; + type Rkey = St::Rkey; + type Space = Set; + } + /// Marker types for field names + #[allow(non_camel_case_types)] + pub mod members { + ///Marker type for the `collection` field + pub struct collection(()); + ///Marker type for the `record` field + pub struct record(()); + ///Marker type for the `repo` field + pub struct repo(()); + ///Marker type for the `rkey` field + pub struct rkey(()); + ///Marker type for the `space` field + pub struct space(()); + } +} + +/// Builder for constructing an instance of this type. +pub struct PutRecordBuilder { + _state: PhantomData St>, + _fields: ( + Option>, + Option>, + Option>, + Option>>, + Option>, + Option, + ), + _type: PhantomData S>, +} + +impl PutRecord { + /// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed + pub fn new() -> PutRecordBuilder { + PutRecordBuilder::new() + } +} + +impl PutRecord { + /// Create a new builder for this type + pub fn builder() -> PutRecordBuilder { + PutRecordBuilder::builder() + } +} + +impl PutRecordBuilder { + /// Create a new builder with all fields unset, using the default string type, if needed + pub fn new() -> Self { + PutRecordBuilder { + _state: PhantomData, + _fields: (None, None, None, None, None, None), + _type: PhantomData, + } + } +} + +impl PutRecordBuilder { + /// Create a new builder with all fields unset + pub fn builder() -> Self { + PutRecordBuilder { + _state: PhantomData, + _fields: (None, None, None, None, None, None), + _type: PhantomData, + } + } +} + +impl PutRecordBuilder +where + St: put_record_state::State, + St::Collection: put_record_state::IsUnset, +{ + /// Set the `collection` field (required) + pub fn collection( + mut self, + value: impl Into>, + ) -> PutRecordBuilder, S> { + self._fields.0 = Option::Some(value.into()); + PutRecordBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl PutRecordBuilder +where + St: put_record_state::State, + St::Record: put_record_state::IsUnset, +{ + /// Set the `record` field (required) + pub fn record( + mut self, + value: impl Into>, + ) -> PutRecordBuilder, S> { + self._fields.1 = Option::Some(value.into()); + PutRecordBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl PutRecordBuilder +where + St: put_record_state::State, + St::Repo: put_record_state::IsUnset, +{ + /// Set the `repo` field (required) + pub fn repo( + mut self, + value: impl Into>, + ) -> PutRecordBuilder, S> { + self._fields.2 = Option::Some(value.into()); + PutRecordBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl PutRecordBuilder +where + St: put_record_state::State, + St::Rkey: put_record_state::IsUnset, +{ + /// Set the `rkey` field (required) + pub fn rkey( + mut self, + value: impl Into>>, + ) -> PutRecordBuilder, S> { + self._fields.3 = Option::Some(value.into()); + PutRecordBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl PutRecordBuilder +where + St: put_record_state::State, + St::Space: put_record_state::IsUnset, +{ + /// Set the `space` field (required) + pub fn space( + mut self, + value: impl Into>, + ) -> PutRecordBuilder, S> { + self._fields.4 = Option::Some(value.into()); + PutRecordBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl PutRecordBuilder { + /// Set the `validate` field (optional) + pub fn validate(mut self, value: impl Into>) -> Self { + self._fields.5 = value.into(); + self + } + /// Set the `validate` field to an Option value (optional) + pub fn maybe_validate(mut self, value: Option) -> Self { + self._fields.5 = value; + self + } +} + +impl PutRecordBuilder +where + St: put_record_state::State, + St::Collection: put_record_state::IsSet, + St::Record: put_record_state::IsSet, + St::Repo: put_record_state::IsSet, + St::Rkey: put_record_state::IsSet, + St::Space: put_record_state::IsSet, +{ + /// Build the final struct. + pub fn build(self) -> PutRecord { + PutRecord { + collection: self._fields.0.unwrap(), + record: self._fields.1.unwrap(), + repo: self._fields.2.unwrap(), + rkey: self._fields.3.unwrap(), + space: self._fields.4.unwrap(), + validate: self._fields.5, + extra_data: Default::default(), + } + } + /// Build the final struct with custom extra_data. + pub fn build_with_data(self, extra_data: BTreeMap>) -> PutRecord { + PutRecord { + collection: self._fields.0.unwrap(), + record: self._fields.1.unwrap(), + repo: self._fields.2.unwrap(), + rkey: self._fields.3.unwrap(), + space: self._fields.4.unwrap(), + validate: self._fields.5, + extra_data: Some(extra_data), + } + } +} diff --git a/crates/jacquard-api/src/com_atproto/space/register_notify.rs b/crates/jacquard-api/src/com_atproto/space/register_notify.rs new file mode 100644 index 000000000..b7ff0c360 --- /dev/null +++ b/crates/jacquard-api/src/com_atproto/space/register_notify.rs @@ -0,0 +1,270 @@ +// @generated by jacquard-lexicon. DO NOT EDIT. +// +// Lexicon: com.atproto.space.registerNotify +// +// 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::deps::smol_str::SmolStr; +use jacquard_common::types::aturi::AtSpaceUri; +use jacquard_common::types::string::Datetime; +use jacquard_common::types::value::Data; +use jacquard_common::{BosStr, CowStr, DefaultStr, FromStaticStr}; +use jacquard_derive::{IntoStatic, open_union}; +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct RegisterNotify { + ///Service identifier of the subscriber: a DID with an optional service fragment naming the entry in its DID document to deliver to (e.g. 'did:web:syncer.example.com#atproto_space_syncer'). notifyWrite calls are addressed to this identifier. + pub service: S, + ///Reference to the space. + pub space: AtSpaceUri, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct RegisterNotifyOutput { + ///When the registration expires. May be later than the expiry of the space credential the request was authenticated with; renew before this time to stay subscribed. + pub expires_at: Datetime, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +#[derive( + Serialize, Deserialize, Debug, Clone, PartialEq, Eq, thiserror::Error, miette::Diagnostic, +)] +#[serde(tag = "error", content = "message")] +pub enum RegisterNotifyError { + #[serde(rename = "SpaceNotFound")] + SpaceNotFound(Option), + /// The service identifier could not be resolved to a DID document with a matching service endpoint. + #[serde(rename = "ServiceNotResolvable")] + ServiceNotResolvable(Option), + /// Catch-all for unknown error codes. + #[serde(untagged)] + Other { + error: SmolStr, + message: Option, + }, +} + +impl core::fmt::Display for RegisterNotifyError { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + match self { + Self::SpaceNotFound(msg) => { + write!(f, "SpaceNotFound")?; + if let Some(msg) = msg { + write!(f, ": {}", msg)?; + } + Ok(()) + } + Self::ServiceNotResolvable(msg) => { + write!(f, "ServiceNotResolvable")?; + if let Some(msg) = msg { + write!(f, ": {}", msg)?; + } + Ok(()) + } + Self::Other { error, message } => { + write!(f, "{}", error)?; + if let Some(msg) = message { + write!(f, ": {}", msg)?; + } + Ok(()) + } + } + } +} + +/** Response marker for the `com.atproto.space.registerNotify` procedure. + +Implements `jacquard_common::xrpc::XrpcResp`; successful bodies decode as `Self::Output`, which is `RegisterNotifyOutput` for this endpoint.*/ +pub struct RegisterNotifyResponse; +impl jacquard_common::xrpc::XrpcResp for RegisterNotifyResponse { + const NSID: &'static str = "com.atproto.space.registerNotify"; + const ENCODING: &'static str = "application/json"; + type Output = RegisterNotifyOutput; + type Err = RegisterNotifyError; +} + +impl jacquard_common::xrpc::XrpcRequest for RegisterNotify { + const NSID: &'static str = "com.atproto.space.registerNotify"; + const METHOD: jacquard_common::xrpc::XrpcMethod = + jacquard_common::xrpc::XrpcMethod::Procedure("application/json"); + type Response = RegisterNotifyResponse; +} + +/** Endpoint marker for the `com.atproto.space.registerNotify` procedure. + +Path: `/xrpc/com.atproto.space.registerNotify`. The request payload type is `RegisterNotify`; send that request with `jacquard::Client` or use this marker through lower-level `XrpcEndpoint` APIs.*/ +pub struct RegisterNotifyRequest; +impl jacquard_common::xrpc::XrpcEndpoint for RegisterNotifyRequest { + const PATH: &'static str = "/xrpc/com.atproto.space.registerNotify"; + const METHOD: jacquard_common::xrpc::XrpcMethod = + jacquard_common::xrpc::XrpcMethod::Procedure("application/json"); + type Request = RegisterNotify; + type Response = RegisterNotifyResponse; +} + +pub mod register_notify_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 Service; + type Space; + } + /// Empty state - all required fields are unset + pub struct Empty(()); + impl sealed::Sealed for Empty {} + impl State for Empty { + type Service = Unset; + type Space = Unset; + } + ///State transition - sets the `service` field to Set + pub struct SetService(PhantomData St>); + impl sealed::Sealed for SetService {} + impl State for SetService { + type Service = Set; + type Space = St::Space; + } + ///State transition - sets the `space` field to Set + pub struct SetSpace(PhantomData St>); + impl sealed::Sealed for SetSpace {} + impl State for SetSpace { + type Service = St::Service; + type Space = Set; + } + /// Marker types for field names + #[allow(non_camel_case_types)] + pub mod members { + ///Marker type for the `service` field + pub struct service(()); + ///Marker type for the `space` field + pub struct space(()); + } +} + +/// Builder for constructing an instance of this type. +pub struct RegisterNotifyBuilder { + _state: PhantomData St>, + _fields: (Option, Option>), + _type: PhantomData S>, +} + +impl RegisterNotify { + /// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed + pub fn new() -> RegisterNotifyBuilder { + RegisterNotifyBuilder::new() + } +} + +impl RegisterNotify { + /// Create a new builder for this type + pub fn builder() -> RegisterNotifyBuilder { + RegisterNotifyBuilder::builder() + } +} + +impl RegisterNotifyBuilder { + /// Create a new builder with all fields unset, using the default string type, if needed + pub fn new() -> Self { + RegisterNotifyBuilder { + _state: PhantomData, + _fields: (None, None), + _type: PhantomData, + } + } +} + +impl RegisterNotifyBuilder { + /// Create a new builder with all fields unset + pub fn builder() -> Self { + RegisterNotifyBuilder { + _state: PhantomData, + _fields: (None, None), + _type: PhantomData, + } + } +} + +impl RegisterNotifyBuilder +where + St: register_notify_state::State, + St::Service: register_notify_state::IsUnset, +{ + /// Set the `service` field (required) + pub fn service( + mut self, + value: impl Into, + ) -> RegisterNotifyBuilder, S> { + self._fields.0 = Option::Some(value.into()); + RegisterNotifyBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl RegisterNotifyBuilder +where + St: register_notify_state::State, + St::Space: register_notify_state::IsUnset, +{ + /// Set the `space` field (required) + pub fn space( + mut self, + value: impl Into>, + ) -> RegisterNotifyBuilder, S> { + self._fields.1 = Option::Some(value.into()); + RegisterNotifyBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl RegisterNotifyBuilder +where + St: register_notify_state::State, + St::Service: register_notify_state::IsSet, + St::Space: register_notify_state::IsSet, +{ + /// Build the final struct. + pub fn build(self) -> RegisterNotify { + RegisterNotify { + service: self._fields.0.unwrap(), + space: self._fields.1.unwrap(), + extra_data: Default::default(), + } + } + /// Build the final struct with custom extra_data. + pub fn build_with_data(self, extra_data: BTreeMap>) -> RegisterNotify { + RegisterNotify { + service: self._fields.0.unwrap(), + space: self._fields.1.unwrap(), + extra_data: Some(extra_data), + } + } +} diff --git a/crates/jacquard-api/src/com_atproto/space/unregister_notify.rs b/crates/jacquard-api/src/com_atproto/space/unregister_notify.rs new file mode 100644 index 000000000..a5381c97c --- /dev/null +++ b/crates/jacquard-api/src/com_atproto/space/unregister_notify.rs @@ -0,0 +1,247 @@ +// @generated by jacquard-lexicon. DO NOT EDIT. +// +// Lexicon: com.atproto.space.unregisterNotify +// +// 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::deps::smol_str::SmolStr; +use jacquard_common::types::aturi::AtSpaceUri; +use jacquard_common::types::value::Data; +use jacquard_common::{BosStr, CowStr, DefaultStr, FromStaticStr}; +use jacquard_derive::{IntoStatic, open_union}; +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct UnregisterNotify { + ///Service identifier of the subscriber to remove, as passed to registerNotify. + pub service: S, + ///Reference to the space. + pub space: AtSpaceUri, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +#[derive( + Serialize, Deserialize, Debug, Clone, PartialEq, Eq, thiserror::Error, miette::Diagnostic, +)] +#[serde(tag = "error", content = "message")] +pub enum UnregisterNotifyError { + #[serde(rename = "SpaceNotFound")] + SpaceNotFound(Option), + /// Catch-all for unknown error codes. + #[serde(untagged)] + Other { + error: SmolStr, + message: Option, + }, +} + +impl core::fmt::Display for UnregisterNotifyError { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + match self { + Self::SpaceNotFound(msg) => { + write!(f, "SpaceNotFound")?; + if let Some(msg) = msg { + write!(f, ": {}", msg)?; + } + Ok(()) + } + Self::Other { error, message } => { + write!(f, "{}", error)?; + if let Some(msg) = message { + write!(f, ": {}", msg)?; + } + Ok(()) + } + } + } +} + +/** Response marker for the `com.atproto.space.unregisterNotify` procedure. + +Implements `jacquard_common::xrpc::XrpcResp`; successful bodies decode as `Self::Output`, which is `()` for this endpoint.*/ +pub struct UnregisterNotifyResponse; +impl jacquard_common::xrpc::XrpcResp for UnregisterNotifyResponse { + const NSID: &'static str = "com.atproto.space.unregisterNotify"; + const ENCODING: &'static str = "application/json"; + type Output = (); + type Err = UnregisterNotifyError; +} + +impl jacquard_common::xrpc::XrpcRequest for UnregisterNotify { + const NSID: &'static str = "com.atproto.space.unregisterNotify"; + const METHOD: jacquard_common::xrpc::XrpcMethod = + jacquard_common::xrpc::XrpcMethod::Procedure("application/json"); + type Response = UnregisterNotifyResponse; +} + +/** Endpoint marker for the `com.atproto.space.unregisterNotify` procedure. + +Path: `/xrpc/com.atproto.space.unregisterNotify`. The request payload type is `UnregisterNotify`; send that request with `jacquard::Client` or use this marker through lower-level `XrpcEndpoint` APIs.*/ +pub struct UnregisterNotifyRequest; +impl jacquard_common::xrpc::XrpcEndpoint for UnregisterNotifyRequest { + const PATH: &'static str = "/xrpc/com.atproto.space.unregisterNotify"; + const METHOD: jacquard_common::xrpc::XrpcMethod = + jacquard_common::xrpc::XrpcMethod::Procedure("application/json"); + type Request = UnregisterNotify; + type Response = UnregisterNotifyResponse; +} + +pub mod unregister_notify_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 Service; + type Space; + } + /// Empty state - all required fields are unset + pub struct Empty(()); + impl sealed::Sealed for Empty {} + impl State for Empty { + type Service = Unset; + type Space = Unset; + } + ///State transition - sets the `service` field to Set + pub struct SetService(PhantomData St>); + impl sealed::Sealed for SetService {} + impl State for SetService { + type Service = Set; + type Space = St::Space; + } + ///State transition - sets the `space` field to Set + pub struct SetSpace(PhantomData St>); + impl sealed::Sealed for SetSpace {} + impl State for SetSpace { + type Service = St::Service; + type Space = Set; + } + /// Marker types for field names + #[allow(non_camel_case_types)] + pub mod members { + ///Marker type for the `service` field + pub struct service(()); + ///Marker type for the `space` field + pub struct space(()); + } +} + +/// Builder for constructing an instance of this type. +pub struct UnregisterNotifyBuilder { + _state: PhantomData St>, + _fields: (Option, Option>), + _type: PhantomData S>, +} + +impl UnregisterNotify { + /// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed + pub fn new() -> UnregisterNotifyBuilder { + UnregisterNotifyBuilder::new() + } +} + +impl UnregisterNotify { + /// Create a new builder for this type + pub fn builder() -> UnregisterNotifyBuilder { + UnregisterNotifyBuilder::builder() + } +} + +impl UnregisterNotifyBuilder { + /// Create a new builder with all fields unset, using the default string type, if needed + pub fn new() -> Self { + UnregisterNotifyBuilder { + _state: PhantomData, + _fields: (None, None), + _type: PhantomData, + } + } +} + +impl UnregisterNotifyBuilder { + /// Create a new builder with all fields unset + pub fn builder() -> Self { + UnregisterNotifyBuilder { + _state: PhantomData, + _fields: (None, None), + _type: PhantomData, + } + } +} + +impl UnregisterNotifyBuilder +where + St: unregister_notify_state::State, + St::Service: unregister_notify_state::IsUnset, +{ + /// Set the `service` field (required) + pub fn service( + mut self, + value: impl Into, + ) -> UnregisterNotifyBuilder, S> { + self._fields.0 = Option::Some(value.into()); + UnregisterNotifyBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl UnregisterNotifyBuilder +where + St: unregister_notify_state::State, + St::Space: unregister_notify_state::IsUnset, +{ + /// Set the `space` field (required) + pub fn space( + mut self, + value: impl Into>, + ) -> UnregisterNotifyBuilder, S> { + self._fields.1 = Option::Some(value.into()); + UnregisterNotifyBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl UnregisterNotifyBuilder +where + St: unregister_notify_state::State, + St::Service: unregister_notify_state::IsSet, + St::Space: unregister_notify_state::IsSet, +{ + /// Build the final struct. + pub fn build(self) -> UnregisterNotify { + UnregisterNotify { + service: self._fields.0.unwrap(), + space: self._fields.1.unwrap(), + extra_data: Default::default(), + } + } + /// Build the final struct with custom extra_data. + pub fn build_with_data(self, extra_data: BTreeMap>) -> UnregisterNotify { + UnregisterNotify { + service: self._fields.0.unwrap(), + space: self._fields.1.unwrap(), + extra_data: Some(extra_data), + } + } +} diff --git a/crates/jacquard-api/src/com_crabdance/nandi/post.rs b/crates/jacquard-api/src/com_crabdance/nandi/post.rs index d6afa0410..2da05345e 100644 --- a/crates/jacquard-api/src/com_crabdance/nandi/post.rs +++ b/crates/jacquard-api/src/com_crabdance/nandi/post.rs @@ -154,6 +154,18 @@ impl LexiconSchema for Post { }); } } + if let Some(values) = &self.tags { + for value in values { + #[allow(unused_comparisons)] + if ::len(value.as_ref()) > 50usize { + return Err(ConstraintError::MaxLength { + path: ValidationPath::from_field("tags"), + max: 50usize, + actual: ::len(value.as_ref()), + }); + } + } + } { let value = &self.title; #[allow(unused_comparisons)] diff --git a/crates/jacquard-api/src/com_deckbelcher/deck/list.rs b/crates/jacquard-api/src/com_deckbelcher/deck/list.rs index ba136f3ce..98619104d 100644 --- a/crates/jacquard-api/src/com_deckbelcher/deck/list.rs +++ b/crates/jacquard-api/src/com_deckbelcher/deck/list.rs @@ -395,6 +395,30 @@ impl LexiconSchema for Card { }); } } + { + let value = &self.section; + #[allow(unused_comparisons)] + if ::len(value.as_ref()) > 640usize { + return Err(ConstraintError::MaxLength { + path: ValidationPath::from_field("section"), + max: 640usize, + actual: ::len(value.as_ref()), + }); + } + } + { + let value = &self.section; + { + let count = UnicodeSegmentation::graphemes(value.as_ref(), true).count(); + if count > 64usize { + return Err(ConstraintError::MaxGraphemes { + path: ValidationPath::from_field("section"), + max: 64usize, + actual: count, + }); + } + } + } if let Some(ref value) = self.tags { #[allow(unused_comparisons)] if value.len() > 128usize { @@ -405,6 +429,32 @@ impl LexiconSchema for Card { }); } } + if let Some(values) = &self.tags { + for value in values { + #[allow(unused_comparisons)] + if ::len(value.as_ref()) > 640usize { + return Err(ConstraintError::MaxLength { + path: ValidationPath::from_field("tags"), + max: 640usize, + actual: ::len(value.as_ref()), + }); + } + } + } + if let Some(values) = &self.tags { + for value in values { + { + let count = UnicodeSegmentation::graphemes(value.as_ref(), true).count(); + if count > 64usize { + return Err(ConstraintError::MaxGraphemes { + path: ValidationPath::from_field("tags"), + max: 64usize, + actual: count, + }); + } + } + } + } Ok(()) } } @@ -447,6 +497,28 @@ impl LexiconSchema for List { lexicon_doc_com_deckbelcher_deck_list() } fn validate(&self) -> Result<(), ConstraintError> { + if let Some(ref value) = self.format { + #[allow(unused_comparisons)] + if ::len(value.as_ref()) > 320usize { + return Err(ConstraintError::MaxLength { + path: ValidationPath::from_field("format"), + max: 320usize, + actual: ::len(value.as_ref()), + }); + } + } + if let Some(ref value) = self.format { + { + let count = UnicodeSegmentation::graphemes(value.as_ref(), true).count(); + if count > 32usize { + return Err(ConstraintError::MaxGraphemes { + path: ValidationPath::from_field("format"), + max: 32usize, + actual: count, + }); + } + } + } { let value = &self.name; #[allow(unused_comparisons)] diff --git a/crates/jacquard-api/src/com_shinolabs/pinksea/app_view_defs.rs b/crates/jacquard-api/src/com_shinolabs/pinksea/app_view_defs.rs index a6a0fbe68..f9732b98f 100644 --- a/crates/jacquard-api/src/com_shinolabs/pinksea/app_view_defs.rs +++ b/crates/jacquard-api/src/com_shinolabs/pinksea/app_view_defs.rs @@ -120,6 +120,18 @@ impl LexiconSchema for HydratedOekaki { }); } } + if let Some(values) = &self.tags { + for value in values { + #[allow(unused_comparisons)] + if ::len(value.as_ref()) > 640usize { + return Err(ConstraintError::MaxLength { + path: ValidationPath::from_field("tags"), + max: 640usize, + actual: ::len(value.as_ref()), + }); + } + } + } Ok(()) } } diff --git a/crates/jacquard-api/src/com_shinolabs/pinksea/oekaki.rs b/crates/jacquard-api/src/com_shinolabs/pinksea/oekaki.rs index aba02e196..5a60058ee 100644 --- a/crates/jacquard-api/src/com_shinolabs/pinksea/oekaki.rs +++ b/crates/jacquard-api/src/com_shinolabs/pinksea/oekaki.rs @@ -217,6 +217,18 @@ impl LexiconSchema for Oekaki { }); } } + if let Some(values) = &self.tags { + for value in values { + #[allow(unused_comparisons)] + if ::len(value.as_ref()) > 640usize { + return Err(ConstraintError::MaxLength { + path: ValidationPath::from_field("tags"), + max: 640usize, + actual: ::len(value.as_ref()), + }); + } + } + } Ok(()) } } diff --git a/crates/jacquard-api/src/com_suibari/atsumeat/sticker.rs b/crates/jacquard-api/src/com_suibari/atsumeat/sticker.rs index 083ce7627..f7c72e8a5 100644 --- a/crates/jacquard-api/src/com_suibari/atsumeat/sticker.rs +++ b/crates/jacquard-api/src/com_suibari/atsumeat/sticker.rs @@ -415,6 +415,32 @@ impl LexiconSchema for Sticker { }); } } + if let Some(values) = &self.tags { + for value in values { + #[allow(unused_comparisons)] + if ::len(value.as_ref()) > 640usize { + return Err(ConstraintError::MaxLength { + path: ValidationPath::from_field("tags"), + max: 640usize, + actual: ::len(value.as_ref()), + }); + } + } + } + if let Some(values) = &self.tags { + for value in values { + { + let count = UnicodeSegmentation::graphemes(value.as_ref(), true).count(); + if count > 64usize { + return Err(ConstraintError::MaxGraphemes { + path: ValidationPath::from_field("tags"), + max: 64usize, + actual: count, + }); + } + } + } + } Ok(()) } } diff --git a/crates/jacquard-api/src/community_lexicon/app/entry.rs b/crates/jacquard-api/src/community_lexicon/app/entry.rs index d0c76a3e3..9d5872956 100644 --- a/crates/jacquard-api/src/community_lexicon/app/entry.rs +++ b/crates/jacquard-api/src/community_lexicon/app/entry.rs @@ -256,6 +256,32 @@ impl LexiconSchema for Entry { }); } } + if let Some(values) = &self.tags { + for value in values { + #[allow(unused_comparisons)] + if ::len(value.as_ref()) > 64usize { + return Err(ConstraintError::MaxLength { + path: ValidationPath::from_field("tags"), + max: 64usize, + actual: ::len(value.as_ref()), + }); + } + } + } + if let Some(values) = &self.tags { + for value in values { + { + let count = UnicodeSegmentation::graphemes(value.as_ref(), true).count(); + if count > 32usize { + return Err(ConstraintError::MaxGraphemes { + path: ValidationPath::from_field("tags"), + max: 32usize, + actual: count, + }); + } + } + } + } Ok(()) } } diff --git a/crates/jacquard-api/src/community_lexicon/app/profile.rs b/crates/jacquard-api/src/community_lexicon/app/profile.rs index bfb6bc359..0fa77e32c 100644 --- a/crates/jacquard-api/src/community_lexicon/app/profile.rs +++ b/crates/jacquard-api/src/community_lexicon/app/profile.rs @@ -240,6 +240,32 @@ impl LexiconSchema for Profile { }); } } + if let Some(values) = &self.tags { + for value in values { + #[allow(unused_comparisons)] + if ::len(value.as_ref()) > 64usize { + return Err(ConstraintError::MaxLength { + path: ValidationPath::from_field("tags"), + max: 64usize, + actual: ::len(value.as_ref()), + }); + } + } + } + if let Some(values) = &self.tags { + for value in values { + { + let count = UnicodeSegmentation::graphemes(value.as_ref(), true).count(); + if count > 32usize { + return Err(ConstraintError::MaxGraphemes { + path: ValidationPath::from_field("tags"), + max: 32usize, + actual: count, + }); + } + } + } + } Ok(()) } } diff --git a/crates/jacquard-api/src/community_lexicon/app/profile_localization.rs b/crates/jacquard-api/src/community_lexicon/app/profile_localization.rs index bd2b14266..5cecf0128 100644 --- a/crates/jacquard-api/src/community_lexicon/app/profile_localization.rs +++ b/crates/jacquard-api/src/community_lexicon/app/profile_localization.rs @@ -204,6 +204,32 @@ impl LexiconSchema for ProfileLocalization { }); } } + if let Some(values) = &self.tags { + for value in values { + #[allow(unused_comparisons)] + if ::len(value.as_ref()) > 64usize { + return Err(ConstraintError::MaxLength { + path: ValidationPath::from_field("tags"), + max: 64usize, + actual: ::len(value.as_ref()), + }); + } + } + } + if let Some(values) = &self.tags { + for value in values { + { + let count = UnicodeSegmentation::graphemes(value.as_ref(), true).count(); + if count > 32usize { + return Err(ConstraintError::MaxGraphemes { + path: ValidationPath::from_field("tags"), + max: 32usize, + actual: count, + }); + } + } + } + } Ok(()) } } diff --git a/crates/jacquard-api/src/dev_atfs.rs b/crates/jacquard-api/src/dev_atfs.rs new file mode 100644 index 000000000..1891f1813 --- /dev/null +++ b/crates/jacquard-api/src/dev_atfs.rs @@ -0,0 +1,9 @@ +// @generated by jacquard-lexicon. DO NOT EDIT. +// +// This file was automatically generated from Lexicon schemas. +// Any manual changes will be overwritten on the next regeneration. + +//! Generated bindings for the `dev.atfs` Lexicon namespace/module. +pub mod file; +pub mod repo; +pub mod server; diff --git a/crates/jacquard-api/src/dev_atfs/file.rs b/crates/jacquard-api/src/dev_atfs/file.rs new file mode 100644 index 000000000..e1d968db5 --- /dev/null +++ b/crates/jacquard-api/src/dev_atfs/file.rs @@ -0,0 +1,386 @@ +// @generated by jacquard-lexicon. DO NOT EDIT. +// +// Lexicon: dev.atfs.file +// +// 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::cid::CidLink; +use jacquard_common::types::string::UriValue; +use jacquard_common::types::value::Data; +use jacquard_derive::IntoStatic; +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", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct File { + ///The blessed CID of the file's bytes (CIDv1, raw multicodec, sha-256 multihash) — the canonical identity. This is what dev.atfs.repo.uploadFile (and its com.atproto.repo.uploadBlob alias) returns, what equality/dedup use, what atfs's own HTTP surfaces serve at any size, and the only DASL-compatible form. Never a DAG root. + pub cid: CidLink, + ///The CID to fetch this file over the IPFS network: the UnixFS root for chunked (large) files, or exactly equal to `cid` when the file fits a single block. Always present, even when equal to `cid`, so consumers never need conditional logic — fetch `ipfsRoot`, then verify the bytes against `cid`. Chunker-dependent: this is *a* valid way to fetch the bytes, not a second identity — re-adding the same bytes elsewhere with different chunk settings would yield a different, equally valid root. + pub ipfs_root: CidLink, + ///The IANA media type of the file's bytes, exactly as recorded at upload time (see dev.atfs.repo.uploadFile). Defaults to application/octet-stream when the uploader supplied no Content-Type. + pub mime_type: S, + ///Advisory HTTPS origins (not full URLs — each is expected to answer both /ipfs/ and a dev.atfs.repo.getFile-style XRPC, with the rest supplied by the author's DID), ordered by preference with the uploader's own instance first. Never required for correctness: a full IPFS client can always fall back to DHT routing. + #[serde(skip_serializing_if = "Option::is_none")] + pub providers: Option>>, + ///Size of the file, in bytes. + pub size: i64, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +impl LexiconSchema for File { + fn nsid() -> &'static str { + "dev.atfs.file" + } + fn def_name() -> &'static str { + "main" + } + fn lexicon_doc() -> LexiconDoc<'static> { + lexicon_doc_dev_atfs_file() + } + fn validate(&self) -> Result<(), ConstraintError> { + if let Some(ref value) = self.providers { + #[allow(unused_comparisons)] + if value.len() < 1usize { + return Err(ConstraintError::MinLength { + path: ValidationPath::from_field("providers"), + min: 1usize, + actual: value.len(), + }); + } + } + Ok(()) + } +} + +pub mod file_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 Cid; + type IpfsRoot; + type MimeType; + type Size; + } + /// Empty state - all required fields are unset + pub struct Empty(()); + impl sealed::Sealed for Empty {} + impl State for Empty { + type Cid = Unset; + type IpfsRoot = Unset; + type MimeType = Unset; + type Size = Unset; + } + ///State transition - sets the `cid` field to Set + pub struct SetCid(PhantomData St>); + impl sealed::Sealed for SetCid {} + impl State for SetCid { + type Cid = Set; + type IpfsRoot = St::IpfsRoot; + type MimeType = St::MimeType; + type Size = St::Size; + } + ///State transition - sets the `ipfs_root` field to Set + pub struct SetIpfsRoot(PhantomData St>); + impl sealed::Sealed for SetIpfsRoot {} + impl State for SetIpfsRoot { + type Cid = St::Cid; + type IpfsRoot = Set; + type MimeType = St::MimeType; + type Size = St::Size; + } + ///State transition - sets the `mime_type` field to Set + pub struct SetMimeType(PhantomData St>); + impl sealed::Sealed for SetMimeType {} + impl State for SetMimeType { + type Cid = St::Cid; + type IpfsRoot = St::IpfsRoot; + type MimeType = Set; + type Size = St::Size; + } + ///State transition - sets the `size` field to Set + pub struct SetSize(PhantomData St>); + impl sealed::Sealed for SetSize {} + impl State for SetSize { + type Cid = St::Cid; + type IpfsRoot = St::IpfsRoot; + type MimeType = St::MimeType; + type Size = Set; + } + /// Marker types for field names + #[allow(non_camel_case_types)] + pub mod members { + ///Marker type for the `cid` field + pub struct cid(()); + ///Marker type for the `ipfs_root` field + pub struct ipfs_root(()); + ///Marker type for the `mime_type` field + pub struct mime_type(()); + ///Marker type for the `size` field + pub struct size(()); + } +} + +/// Builder for constructing an instance of this type. +pub struct FileBuilder { + _state: PhantomData St>, + _fields: ( + Option>, + Option>, + Option, + Option>>, + Option, + ), + _type: PhantomData S>, +} + +impl File { + /// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed + pub fn new() -> FileBuilder { + FileBuilder::new() + } +} + +impl File { + /// Create a new builder for this type + pub fn builder() -> FileBuilder { + FileBuilder::builder() + } +} + +impl FileBuilder { + /// Create a new builder with all fields unset, using the default string type, if needed + pub fn new() -> Self { + FileBuilder { + _state: PhantomData, + _fields: (None, None, None, None, None), + _type: PhantomData, + } + } +} + +impl FileBuilder { + /// Create a new builder with all fields unset + pub fn builder() -> Self { + FileBuilder { + _state: PhantomData, + _fields: (None, None, None, None, None), + _type: PhantomData, + } + } +} + +impl FileBuilder +where + St: file_state::State, + St::Cid: file_state::IsUnset, +{ + /// Set the `cid` field (required) + pub fn cid(mut self, value: impl Into>) -> FileBuilder, S> { + self._fields.0 = Option::Some(value.into()); + FileBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl FileBuilder +where + St: file_state::State, + St::IpfsRoot: file_state::IsUnset, +{ + /// Set the `ipfsRoot` field (required) + pub fn ipfs_root( + mut self, + value: impl Into>, + ) -> FileBuilder, S> { + self._fields.1 = Option::Some(value.into()); + FileBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl FileBuilder +where + St: file_state::State, + St::MimeType: file_state::IsUnset, +{ + /// Set the `mimeType` field (required) + pub fn mime_type(mut self, value: impl Into) -> FileBuilder, S> { + self._fields.2 = Option::Some(value.into()); + FileBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl FileBuilder { + /// Set the `providers` field (optional) + pub fn providers(mut self, value: impl Into>>>) -> Self { + self._fields.3 = value.into(); + self + } + /// Set the `providers` field to an Option value (optional) + pub fn maybe_providers(mut self, value: Option>>) -> Self { + self._fields.3 = value; + self + } +} + +impl FileBuilder +where + St: file_state::State, + St::Size: file_state::IsUnset, +{ + /// Set the `size` field (required) + pub fn size(mut self, value: impl Into) -> FileBuilder, S> { + self._fields.4 = Option::Some(value.into()); + FileBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl FileBuilder +where + St: file_state::State, + St::Cid: file_state::IsSet, + St::IpfsRoot: file_state::IsSet, + St::MimeType: file_state::IsSet, + St::Size: file_state::IsSet, +{ + /// Build the final struct. + pub fn build(self) -> File { + File { + cid: self._fields.0.unwrap(), + ipfs_root: self._fields.1.unwrap(), + mime_type: self._fields.2.unwrap(), + providers: self._fields.3, + size: self._fields.4.unwrap(), + extra_data: Default::default(), + } + } + /// Build the final struct with custom extra_data. + pub fn build_with_data(self, extra_data: BTreeMap>) -> File { + File { + cid: self._fields.0.unwrap(), + ipfs_root: self._fields.1.unwrap(), + mime_type: self._fields.2.unwrap(), + providers: self._fields.3, + size: self._fields.4.unwrap(), + extra_data: Some(extra_data), + } + } +} + +fn lexicon_doc_dev_atfs_file() -> 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("dev.atfs.file"), + defs: { + let mut map = BTreeMap::new(); + map.insert( + SmolStr::new_static("main"), + LexUserType::Object(LexObject { + required: Some( + vec![ + SmolStr::new_static("cid"), SmolStr::new_static("ipfsRoot"), + SmolStr::new_static("size"), SmolStr::new_static("mimeType") + ], + ), + properties: { + #[allow(unused_mut)] + let mut map = BTreeMap::new(); + map.insert( + SmolStr::new_static("cid"), + LexObjectProperty::CidLink(LexCidLink { + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("ipfsRoot"), + LexObjectProperty::CidLink(LexCidLink { + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("mimeType"), + LexObjectProperty::String(LexString { + description: Some( + CowStr::new_static( + "The IANA media type of the file's bytes, exactly as recorded at upload time (see dev.atfs.repo.uploadFile). Defaults to application/octet-stream when the uploader supplied no Content-Type.", + ), + ), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("providers"), + LexObjectProperty::Array(LexArray { + description: Some( + CowStr::new_static( + "Advisory HTTPS origins (not full URLs — each is expected to answer both /ipfs/ and a dev.atfs.repo.getFile-style XRPC, with the rest supplied by the author's DID), ordered by preference with the uploader's own instance first. Never required for correctness: a full IPFS client can always fall back to DHT routing.", + ), + ), + items: LexArrayItem::String(LexString { + format: Some(LexStringFormat::Uri), + ..Default::default() + }), + min_length: Some(1usize), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("size"), + LexObjectProperty::Integer(LexInteger { + ..Default::default() + }), + ); + map + }, + ..Default::default() + }), + ); + map + }, + ..Default::default() + } +} diff --git a/crates/jacquard-api/src/dev_atfs/repo.rs b/crates/jacquard-api/src/dev_atfs/repo.rs new file mode 100644 index 000000000..592018453 --- /dev/null +++ b/crates/jacquard-api/src/dev_atfs/repo.rs @@ -0,0 +1,11 @@ +// @generated by jacquard-lexicon. DO NOT EDIT. +// +// This file was automatically generated from Lexicon schemas. +// Any manual changes will be overwritten on the next regeneration. + +//! Generated bindings for the `dev.atfs.repo` Lexicon namespace/module. +pub mod delete_file; +pub mod get_file; +pub mod list_files; +pub mod pin_file; +pub mod upload_file; diff --git a/crates/jacquard-api/src/dev_atfs/repo/delete_file.rs b/crates/jacquard-api/src/dev_atfs/repo/delete_file.rs new file mode 100644 index 000000000..eb26f31af --- /dev/null +++ b/crates/jacquard-api/src/dev_atfs/repo/delete_file.rs @@ -0,0 +1,234 @@ +// @generated by jacquard-lexicon. DO NOT EDIT. +// +// Lexicon: dev.atfs.repo.deleteFile +// +// 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::deps::smol_str::SmolStr; +use jacquard_common::types::string::Cid; +use jacquard_common::types::value::Data; +use jacquard_common::{BosStr, CowStr, DefaultStr, FromStaticStr}; +use jacquard_derive::{IntoStatic, open_union}; +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct DeleteFile { + ///The blessed CID (see dev.atfs.file) of the file to release the caller's claim on. + pub cid: Cid, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct DeleteFileOutput { + ///Whether this call was the one that removed the last claim, triggering physical deletion of the stored bytes (and, for a large file, its UnixFS DAG artifacts). false means other accounts still hold claims on the cid, so it remains fully served. + pub content_deleted: bool, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +#[derive( + Serialize, Deserialize, Debug, Clone, PartialEq, Eq, thiserror::Error, miette::Diagnostic, +)] +#[serde(tag = "error", content = "message")] +pub enum DeleteFileError { + /// No file is stored under this cid, and no pinFile request of the caller's is waiting on it either. Existence isn't secret — the /ipfs/ gateway serves any stored cid to anyone — so this is reported distinctly from NotPinned rather than folded into it. + #[serde(rename = "BlobNotFound")] + BlobNotFound(Option), + /// The file exists, but the caller holds no claim on it — there is nothing for this call to release. + #[serde(rename = "NotPinned")] + NotPinned(Option), + /// Catch-all for unknown error codes. + #[serde(untagged)] + Other { + error: SmolStr, + message: Option, + }, +} + +impl core::fmt::Display for DeleteFileError { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + match self { + Self::BlobNotFound(msg) => { + write!(f, "BlobNotFound")?; + if let Some(msg) = msg { + write!(f, ": {}", msg)?; + } + Ok(()) + } + Self::NotPinned(msg) => { + write!(f, "NotPinned")?; + if let Some(msg) = msg { + write!(f, ": {}", msg)?; + } + Ok(()) + } + Self::Other { error, message } => { + write!(f, "{}", error)?; + if let Some(msg) = message { + write!(f, ": {}", msg)?; + } + Ok(()) + } + } + } +} + +/** Response marker for the `dev.atfs.repo.deleteFile` procedure. + +Implements `jacquard_common::xrpc::XrpcResp`; successful bodies decode as `Self::Output`, which is `DeleteFileOutput` for this endpoint.*/ +pub struct DeleteFileResponse; +impl jacquard_common::xrpc::XrpcResp for DeleteFileResponse { + const NSID: &'static str = "dev.atfs.repo.deleteFile"; + const ENCODING: &'static str = "application/json"; + type Output = DeleteFileOutput; + type Err = DeleteFileError; +} + +impl jacquard_common::xrpc::XrpcRequest for DeleteFile { + const NSID: &'static str = "dev.atfs.repo.deleteFile"; + const METHOD: jacquard_common::xrpc::XrpcMethod = + jacquard_common::xrpc::XrpcMethod::Procedure("application/json"); + type Response = DeleteFileResponse; +} + +/** Endpoint marker for the `dev.atfs.repo.deleteFile` procedure. + +Path: `/xrpc/dev.atfs.repo.deleteFile`. The request payload type is `DeleteFile`; send that request with `jacquard::Client` or use this marker through lower-level `XrpcEndpoint` APIs.*/ +pub struct DeleteFileRequest; +impl jacquard_common::xrpc::XrpcEndpoint for DeleteFileRequest { + const PATH: &'static str = "/xrpc/dev.atfs.repo.deleteFile"; + const METHOD: jacquard_common::xrpc::XrpcMethod = + jacquard_common::xrpc::XrpcMethod::Procedure("application/json"); + type Request = DeleteFile; + type Response = DeleteFileResponse; +} + +pub mod delete_file_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 Cid; + } + /// Empty state - all required fields are unset + pub struct Empty(()); + impl sealed::Sealed for Empty {} + impl State for Empty { + type Cid = Unset; + } + ///State transition - sets the `cid` field to Set + pub struct SetCid(PhantomData St>); + impl sealed::Sealed for SetCid {} + impl State for SetCid { + type Cid = Set; + } + /// Marker types for field names + #[allow(non_camel_case_types)] + pub mod members { + ///Marker type for the `cid` field + pub struct cid(()); + } +} + +/// Builder for constructing an instance of this type. +pub struct DeleteFileBuilder { + _state: PhantomData St>, + _fields: (Option>,), + _type: PhantomData S>, +} + +impl DeleteFile { + /// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed + pub fn new() -> DeleteFileBuilder { + DeleteFileBuilder::new() + } +} + +impl DeleteFile { + /// Create a new builder for this type + pub fn builder() -> DeleteFileBuilder { + DeleteFileBuilder::builder() + } +} + +impl DeleteFileBuilder { + /// Create a new builder with all fields unset, using the default string type, if needed + pub fn new() -> Self { + DeleteFileBuilder { + _state: PhantomData, + _fields: (None,), + _type: PhantomData, + } + } +} + +impl DeleteFileBuilder { + /// Create a new builder with all fields unset + pub fn builder() -> Self { + DeleteFileBuilder { + _state: PhantomData, + _fields: (None,), + _type: PhantomData, + } + } +} + +impl DeleteFileBuilder +where + St: delete_file_state::State, + St::Cid: delete_file_state::IsUnset, +{ + /// Set the `cid` field (required) + pub fn cid( + mut self, + value: impl Into>, + ) -> DeleteFileBuilder, S> { + self._fields.0 = Option::Some(value.into()); + DeleteFileBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl DeleteFileBuilder +where + St: delete_file_state::State, + St::Cid: delete_file_state::IsSet, +{ + /// Build the final struct. + pub fn build(self) -> DeleteFile { + DeleteFile { + cid: self._fields.0.unwrap(), + extra_data: Default::default(), + } + } + /// Build the final struct with custom extra_data. + pub fn build_with_data(self, extra_data: BTreeMap>) -> DeleteFile { + DeleteFile { + cid: self._fields.0.unwrap(), + extra_data: Some(extra_data), + } + } +} diff --git a/crates/jacquard-api/src/dev_atfs/repo/get_file.rs b/crates/jacquard-api/src/dev_atfs/repo/get_file.rs new file mode 100644 index 000000000..4a32bd793 --- /dev/null +++ b/crates/jacquard-api/src/dev_atfs/repo/get_file.rs @@ -0,0 +1,241 @@ +// @generated by jacquard-lexicon. DO NOT EDIT. +// +// Lexicon: dev.atfs.repo.getFile +// +// 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::deps::bytes::Bytes; +use jacquard_common::deps::smol_str::SmolStr; +use jacquard_common::types::string::{Cid, Did}; +use jacquard_common::types::value::Data; +use jacquard_common::{BosStr, CowStr, DefaultStr, FromStaticStr}; +use jacquard_derive::{IntoStatic, open_union}; +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct GetFile { + pub cid: Cid, + #[serde(skip_serializing_if = "Option::is_none")] + pub did: Option>, +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde(rename_all = "camelCase")] +pub struct GetFileOutput { + pub body: Bytes, +} + +#[derive( + Serialize, Deserialize, Debug, Clone, PartialEq, Eq, thiserror::Error, miette::Diagnostic, +)] +#[serde(tag = "error", content = "message")] +pub enum GetFileError { + /// No file is stored under this cid, or — when did is supplied — that account holds no claim on it; the two are reported identically, matching com.atproto.sync.getBlob's own behavior. + #[serde(rename = "BlobNotFound")] + BlobNotFound(Option), + /// Catch-all for unknown error codes. + #[serde(untagged)] + Other { + error: SmolStr, + message: Option, + }, +} + +impl core::fmt::Display for GetFileError { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + match self { + Self::BlobNotFound(msg) => { + write!(f, "BlobNotFound")?; + if let Some(msg) = msg { + write!(f, ": {}", msg)?; + } + Ok(()) + } + Self::Other { error, message } => { + write!(f, "{}", error)?; + if let Some(msg) = message { + write!(f, ": {}", msg)?; + } + Ok(()) + } + } + } +} + +/** Response marker for the `dev.atfs.repo.getFile` query. + +Implements `jacquard_common::xrpc::XrpcResp`; successful bodies decode as `Self::Output`, which is `GetFileOutput` for this endpoint.*/ +pub struct GetFileResponse; +impl jacquard_common::xrpc::XrpcResp for GetFileResponse { + const NSID: &'static str = "dev.atfs.repo.getFile"; + const ENCODING: &'static str = "*/*"; + type Output = GetFileOutput; + type Err = GetFileError; + fn encode_output( + output: &Self::Output, + ) -> Result, jacquard_common::xrpc::EncodeError> + where + Self::Output: Serialize, + { + Ok(output.body.to_vec()) + } + fn decode_output<'de, S>( + body: &'de [u8], + ) -> Result, jacquard_common::error::DecodeError> + where + S: BosStr + Deserialize<'de>, + Self::Output: Deserialize<'de>, + { + Ok(GetFileOutput { + body: jacquard_common::deps::bytes::Bytes::copy_from_slice(body), + }) + } +} + +impl jacquard_common::xrpc::XrpcRequest for GetFile { + const NSID: &'static str = "dev.atfs.repo.getFile"; + const METHOD: jacquard_common::xrpc::XrpcMethod = jacquard_common::xrpc::XrpcMethod::Query; + type Response = GetFileResponse; +} + +/** Endpoint marker for the `dev.atfs.repo.getFile` query. + +Path: `/xrpc/dev.atfs.repo.getFile`. The request payload type is `GetFile`; send that request with `jacquard::Client` or use this marker through lower-level `XrpcEndpoint` APIs.*/ +pub struct GetFileRequest; +impl jacquard_common::xrpc::XrpcEndpoint for GetFileRequest { + const PATH: &'static str = "/xrpc/dev.atfs.repo.getFile"; + const METHOD: jacquard_common::xrpc::XrpcMethod = jacquard_common::xrpc::XrpcMethod::Query; + type Request = GetFile; + type Response = GetFileResponse; +} + +pub mod get_file_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 Cid; + } + /// Empty state - all required fields are unset + pub struct Empty(()); + impl sealed::Sealed for Empty {} + impl State for Empty { + type Cid = Unset; + } + ///State transition - sets the `cid` field to Set + pub struct SetCid(PhantomData St>); + impl sealed::Sealed for SetCid {} + impl State for SetCid { + type Cid = Set; + } + /// Marker types for field names + #[allow(non_camel_case_types)] + pub mod members { + ///Marker type for the `cid` field + pub struct cid(()); + } +} + +/// Builder for constructing an instance of this type. +pub struct GetFileBuilder { + _state: PhantomData St>, + _fields: (Option>, Option>), + _type: PhantomData S>, +} + +impl GetFile { + /// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed + pub fn new() -> GetFileBuilder { + GetFileBuilder::new() + } +} + +impl GetFile { + /// Create a new builder for this type + pub fn builder() -> GetFileBuilder { + GetFileBuilder::builder() + } +} + +impl GetFileBuilder { + /// Create a new builder with all fields unset, using the default string type, if needed + pub fn new() -> Self { + GetFileBuilder { + _state: PhantomData, + _fields: (None, None), + _type: PhantomData, + } + } +} + +impl GetFileBuilder { + /// Create a new builder with all fields unset + pub fn builder() -> Self { + GetFileBuilder { + _state: PhantomData, + _fields: (None, None), + _type: PhantomData, + } + } +} + +impl GetFileBuilder +where + St: get_file_state::State, + St::Cid: get_file_state::IsUnset, +{ + /// Set the `cid` field (required) + pub fn cid( + mut self, + value: impl Into>, + ) -> GetFileBuilder, S> { + self._fields.0 = Option::Some(value.into()); + GetFileBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl GetFileBuilder { + /// Set the `did` field (optional) + pub fn did(mut self, value: impl Into>>) -> Self { + self._fields.1 = value.into(); + self + } + /// Set the `did` field to an Option value (optional) + pub fn maybe_did(mut self, value: Option>) -> Self { + self._fields.1 = value; + self + } +} + +impl GetFileBuilder +where + St: get_file_state::State, + St::Cid: get_file_state::IsSet, +{ + /// Build the final struct. + pub fn build(self) -> GetFile { + GetFile { + cid: self._fields.0.unwrap(), + did: self._fields.1, + } + } +} diff --git a/crates/jacquard-api/src/dev_atfs/repo/list_files.rs b/crates/jacquard-api/src/dev_atfs/repo/list_files.rs new file mode 100644 index 000000000..e9a0fe57c --- /dev/null +++ b/crates/jacquard-api/src/dev_atfs/repo/list_files.rs @@ -0,0 +1,179 @@ +// @generated by jacquard-lexicon. DO NOT EDIT. +// +// Lexicon: dev.atfs.repo.listFiles +// +// 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; + +use crate::dev_atfs::file::File; +#[allow(unused_imports)] +use core::marker::PhantomData; +use jacquard_common::deps::smol_str::SmolStr; +use jacquard_common::types::value::Data; +use jacquard_common::{BosStr, CowStr, DefaultStr, FromStaticStr}; +use jacquard_derive::IntoStatic; +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct ListFiles { + #[serde(skip_serializing_if = "Option::is_none")] + pub cursor: Option, + /// Defaults to `500`. Min: 1. Max: 1000. + #[serde(default = "_default_limit")] + #[serde(skip_serializing_if = "Option::is_none")] + pub limit: Option, +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct ListFilesOutput { + ///Present only when this page filled up to the requested limit, meaning more files may follow. Its absence marks the final page. + #[serde(skip_serializing_if = "Option::is_none")] + pub cursor: Option, + pub files: Vec>, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +/** Response marker for the `dev.atfs.repo.listFiles` query. + +Implements `jacquard_common::xrpc::XrpcResp`; successful bodies decode as `Self::Output`, which is `ListFilesOutput` for this endpoint.*/ +pub struct ListFilesResponse; +impl jacquard_common::xrpc::XrpcResp for ListFilesResponse { + const NSID: &'static str = "dev.atfs.repo.listFiles"; + const ENCODING: &'static str = "application/json"; + type Output = ListFilesOutput; + type Err = jacquard_common::xrpc::GenericError; +} + +impl jacquard_common::xrpc::XrpcRequest for ListFiles { + const NSID: &'static str = "dev.atfs.repo.listFiles"; + const METHOD: jacquard_common::xrpc::XrpcMethod = jacquard_common::xrpc::XrpcMethod::Query; + type Response = ListFilesResponse; +} + +/** Endpoint marker for the `dev.atfs.repo.listFiles` query. + +Path: `/xrpc/dev.atfs.repo.listFiles`. The request payload type is `ListFiles`; send that request with `jacquard::Client` or use this marker through lower-level `XrpcEndpoint` APIs.*/ +pub struct ListFilesRequest; +impl jacquard_common::xrpc::XrpcEndpoint for ListFilesRequest { + const PATH: &'static str = "/xrpc/dev.atfs.repo.listFiles"; + const METHOD: jacquard_common::xrpc::XrpcMethod = jacquard_common::xrpc::XrpcMethod::Query; + type Request = ListFiles; + type Response = ListFilesResponse; +} + +fn _default_limit() -> Option { + Some(500i64) +} + +pub mod list_files_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 {} + /// Empty state - all required fields are unset + pub struct Empty(()); + impl sealed::Sealed for Empty {} + impl State for Empty {} + /// Marker types for field names + #[allow(non_camel_case_types)] + pub mod members {} +} + +/// Builder for constructing an instance of this type. +pub struct ListFilesBuilder { + _state: PhantomData St>, + _fields: (Option, Option), + _type: PhantomData S>, +} + +impl ListFiles { + /// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed + pub fn new() -> ListFilesBuilder { + ListFilesBuilder::new() + } +} + +impl ListFiles { + /// Create a new builder for this type + pub fn builder() -> ListFilesBuilder { + ListFilesBuilder::builder() + } +} + +impl ListFilesBuilder { + /// Create a new builder with all fields unset, using the default string type, if needed + pub fn new() -> Self { + ListFilesBuilder { + _state: PhantomData, + _fields: (None, None), + _type: PhantomData, + } + } +} + +impl ListFilesBuilder { + /// Create a new builder with all fields unset + pub fn builder() -> Self { + ListFilesBuilder { + _state: PhantomData, + _fields: (None, None), + _type: PhantomData, + } + } +} + +impl ListFilesBuilder { + /// Set the `cursor` field (optional) + pub fn cursor(mut self, value: impl Into>) -> Self { + self._fields.0 = value.into(); + self + } + /// Set the `cursor` field to an Option value (optional) + pub fn maybe_cursor(mut self, value: Option) -> Self { + self._fields.0 = value; + self + } +} + +impl ListFilesBuilder { + /// Set the `limit` field (optional) + pub fn limit(mut self, value: impl Into>) -> Self { + self._fields.1 = value.into(); + self + } + /// Set the `limit` field to an Option value (optional) + pub fn maybe_limit(mut self, value: Option) -> Self { + self._fields.1 = value; + self + } +} + +impl ListFilesBuilder +where + St: list_files_state::State, +{ + /// Build the final struct. + pub fn build(self) -> ListFiles { + ListFiles { + cursor: self._fields.0, + limit: self._fields.1, + } + } +} diff --git a/crates/jacquard-api/src/dev_atfs/repo/pin_file.rs b/crates/jacquard-api/src/dev_atfs/repo/pin_file.rs new file mode 100644 index 000000000..a84b234ee --- /dev/null +++ b/crates/jacquard-api/src/dev_atfs/repo/pin_file.rs @@ -0,0 +1,593 @@ +// @generated by jacquard-lexicon. DO NOT EDIT. +// +// Lexicon: dev.atfs.repo.pinFile +// +// 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::cid::CidLink; +use jacquard_common::types::value::Data; +use jacquard_derive::{IntoStatic, open_union}; +use jacquard_lexicon::lexicon::LexiconDoc; +use jacquard_lexicon::schema::LexiconSchema; + +use crate::dev_atfs::file::File; +use crate::dev_atfs::repo::pin_file; +#[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", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct PinFile { + ///The file to pin, exactly as it would be embedded in a record. Wrapped in an object rather than being the request body itself so later additions to the call have somewhere to live. + pub file: File, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic, Default)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct PinFileOutput { + ///How many fetch attempts this pin has cost so far. Reset to zero when a failed pin is re-triggered. + #[serde(skip_serializing_if = "Option::is_none")] + pub attempts: Option, + ///Present only when state is pinned: the CID this instance now serves the file's DAG under, and deliberately the same field name as dev.atfs.repo.uploadFile's, since it means exactly the same thing. Usually this is the reference's own ipfsRoot, fetched and kept verbatim. It differs when the instance had already committed a root for these bytes — from an earlier upload, or an earlier pin naming a different DAG shape — because that root has already been handed out in responses, embedded in dev.atfs.file records and announced to the DHT: first root wins, the pin still succeeds (recording the claim is what a pin means), and this field reports what is really being served so the caller can tell its requester the file is here but reachable under a different root than their reference names. + #[serde(skip_serializing_if = "Option::is_none")] + pub ipfs_root: Option>, + ///Why the most recent attempt failed, for a human. Present alongside seeking (a failure being retried), failed (the one that ended it), and the first response after a failed pin is re-triggered. + #[serde(skip_serializing_if = "Option::is_none")] + pub last_error: Option, + ///Seconds until the next attempt starts. Deliberately relative rather than an absolute timestamp: an atfs appliance can boot with its clock reading 1970 and no network to correct it, so any absolute time it quoted would be a lie. Absent when nothing is scheduled — an attempt is running now, the pin has finished, or it has failed. + #[serde(skip_serializing_if = "Option::is_none")] + pub next_attempt_in: Option, + ///Present only while state is fetching. + #[serde(skip_serializing_if = "Option::is_none")] + pub progress: Option>, + ///seeking: the node is looking for a source, or waiting out the backoff before looking again. fetching: bytes are actually arriving; seeking and fetching can bounce back and forth as sources come and go. pinned: the bytes are stored, served and announced, and the caller holds a claim on them — this is read from ground truth (content in the store, caller in its pin set), not from anything the pin request recorded. failed: the node has stopped trying (see lastError); the request rests until it is either re-triggered by another pinFile call or released by every account waiting on it. A failure the node could not prove — no providers found yet, an origin that wouldn't answer, a transfer cut short — is never reported as failed on the spot: provider records on the DHT routinely take hours to propagate, so those are retried on a backoff doubling from a minute to an hour, for roughly 48 hours of the instance's uptime (uptime, not wall time: a box that spends a day powered off spends none of it), and the state stays seeking throughout. Only a failure the node could prove — bytes that don't hash to the cid, a source holding more than the declared size, a root that isn't a readable UnixFS file, a size over this instance's limit — fails immediately, since no retry could change it. + pub state: PinFileOutputState, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +/// seeking: the node is looking for a source, or waiting out the backoff before looking again. fetching: bytes are actually arriving; seeking and fetching can bounce back and forth as sources come and go. pinned: the bytes are stored, served and announced, and the caller holds a claim on them — this is read from ground truth (content in the store, caller in its pin set), not from anything the pin request recorded. failed: the node has stopped trying (see lastError); the request rests until it is either re-triggered by another pinFile call or released by every account waiting on it. A failure the node could not prove — no providers found yet, an origin that wouldn't answer, a transfer cut short — is never reported as failed on the spot: provider records on the DHT routinely take hours to propagate, so those are retried on a backoff doubling from a minute to an hour, for roughly 48 hours of the instance's uptime (uptime, not wall time: a box that spends a day powered off spends none of it), and the state stays seeking throughout. Only a failure the node could prove — bytes that don't hash to the cid, a source holding more than the declared size, a root that isn't a readable UnixFS file, a size over this instance's limit — fails immediately, since no retry could change it. + +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub enum PinFileOutputState { + Seeking, + Fetching, + Pinned, + Failed, + Other(S), +} + +impl PinFileOutputState { + pub fn as_str(&self) -> &str { + match self { + Self::Seeking => "seeking", + Self::Fetching => "fetching", + Self::Pinned => "pinned", + Self::Failed => "failed", + 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() { + "seeking" => Self::Seeking, + "fetching" => Self::Fetching, + "pinned" => Self::Pinned, + "failed" => Self::Failed, + _ => Self::Other(s), + } + } +} + +impl core::fmt::Display for PinFileOutputState { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!(f, "{}", self.as_str()) + } +} + +impl AsRef for PinFileOutputState { + fn as_ref(&self) -> &str { + self.as_str() + } +} + +impl Serialize for PinFileOutputState { + 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 PinFileOutputState { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = S::deserialize(deserializer)?; + Ok(Self::from_value(s)) + } +} + +impl Default for PinFileOutputState { + fn default() -> Self { + Self::Other(Default::default()) + } +} + +impl jacquard_common::IntoStatic for PinFileOutputState +where + S: BosStr + jacquard_common::IntoStatic, + S::Output: BosStr, +{ + type Output = PinFileOutputState; + fn into_static(self) -> Self::Output { + match self { + PinFileOutputState::Seeking => PinFileOutputState::Seeking, + PinFileOutputState::Fetching => PinFileOutputState::Fetching, + PinFileOutputState::Pinned => PinFileOutputState::Pinned, + PinFileOutputState::Failed => PinFileOutputState::Failed, + PinFileOutputState::Other(v) => PinFileOutputState::Other(v.into_static()), + } + } +} + +#[derive( + Serialize, Deserialize, Debug, Clone, PartialEq, Eq, thiserror::Error, miette::Diagnostic, +)] +#[serde(tag = "error", content = "message")] +pub enum PinFileError { + /// This instance is running without its IPFS node, so it has no way to fetch anything. Uploads and retrieval are unaffected. + #[serde(rename = "PinningUnavailable")] + PinningUnavailable(Option), + /// The reference's declared size exceeds this instance's maximum blob size — checked before any fetch is attempted, the same limit dev.atfs.repo.uploadFile enforces on bytes it receives directly. + #[serde(rename = "BlobTooLarge")] + BlobTooLarge(Option), + /// Catch-all for unknown error codes. + #[serde(untagged)] + Other { + error: SmolStr, + message: Option, + }, +} + +impl core::fmt::Display for PinFileError { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + match self { + Self::PinningUnavailable(msg) => { + write!(f, "PinningUnavailable")?; + if let Some(msg) = msg { + write!(f, ": {}", msg)?; + } + Ok(()) + } + Self::BlobTooLarge(msg) => { + write!(f, "BlobTooLarge")?; + if let Some(msg) = msg { + write!(f, ": {}", msg)?; + } + Ok(()) + } + Self::Other { error, message } => { + write!(f, "{}", error)?; + if let Some(msg) = message { + write!(f, ": {}", msg)?; + } + Ok(()) + } + } + } +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct Progress { + ///Bytes of the file verified into the store so far by the attempt currently running. It restarts from zero on each attempt: a fetch that was cut short leaves nothing behind, so the next one starts from the beginning. + pub bytes_fetched: i64, + ///The file's total size, as the reference declares it — repeated here so a progress bar needs only this object. + pub size: i64, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +/** Response marker for the `dev.atfs.repo.pinFile` procedure. + +Implements `jacquard_common::xrpc::XrpcResp`; successful bodies decode as `Self::Output`, which is `PinFileOutput` for this endpoint.*/ +pub struct PinFileResponse; +impl jacquard_common::xrpc::XrpcResp for PinFileResponse { + const NSID: &'static str = "dev.atfs.repo.pinFile"; + const ENCODING: &'static str = "application/json"; + type Output = PinFileOutput; + type Err = PinFileError; +} + +impl jacquard_common::xrpc::XrpcRequest for PinFile { + const NSID: &'static str = "dev.atfs.repo.pinFile"; + const METHOD: jacquard_common::xrpc::XrpcMethod = + jacquard_common::xrpc::XrpcMethod::Procedure("application/json"); + type Response = PinFileResponse; +} + +/** Endpoint marker for the `dev.atfs.repo.pinFile` procedure. + +Path: `/xrpc/dev.atfs.repo.pinFile`. The request payload type is `PinFile`; send that request with `jacquard::Client` or use this marker through lower-level `XrpcEndpoint` APIs.*/ +pub struct PinFileRequest; +impl jacquard_common::xrpc::XrpcEndpoint for PinFileRequest { + const PATH: &'static str = "/xrpc/dev.atfs.repo.pinFile"; + const METHOD: jacquard_common::xrpc::XrpcMethod = + jacquard_common::xrpc::XrpcMethod::Procedure("application/json"); + type Request = PinFile; + type Response = PinFileResponse; +} + +impl LexiconSchema for Progress { + fn nsid() -> &'static str { + "dev.atfs.repo.pinFile" + } + fn def_name() -> &'static str { + "progress" + } + fn lexicon_doc() -> LexiconDoc<'static> { + lexicon_doc_dev_atfs_repo_pinFile() + } + fn validate(&self) -> Result<(), ConstraintError> { + Ok(()) + } +} + +pub mod pin_file_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 File; + } + /// Empty state - all required fields are unset + pub struct Empty(()); + impl sealed::Sealed for Empty {} + impl State for Empty { + type File = Unset; + } + ///State transition - sets the `file` field to Set + pub struct SetFile(PhantomData St>); + impl sealed::Sealed for SetFile {} + impl State for SetFile { + type File = Set; + } + /// Marker types for field names + #[allow(non_camel_case_types)] + pub mod members { + ///Marker type for the `file` field + pub struct file(()); + } +} + +/// Builder for constructing an instance of this type. +pub struct PinFileBuilder { + _state: PhantomData St>, + _fields: (Option>,), + _type: PhantomData S>, +} + +impl PinFile { + /// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed + pub fn new() -> PinFileBuilder { + PinFileBuilder::new() + } +} + +impl PinFile { + /// Create a new builder for this type + pub fn builder() -> PinFileBuilder { + PinFileBuilder::builder() + } +} + +impl PinFileBuilder { + /// Create a new builder with all fields unset, using the default string type, if needed + pub fn new() -> Self { + PinFileBuilder { + _state: PhantomData, + _fields: (None,), + _type: PhantomData, + } + } +} + +impl PinFileBuilder { + /// Create a new builder with all fields unset + pub fn builder() -> Self { + PinFileBuilder { + _state: PhantomData, + _fields: (None,), + _type: PhantomData, + } + } +} + +impl PinFileBuilder +where + St: pin_file_state::State, + St::File: pin_file_state::IsUnset, +{ + /// Set the `file` field (required) + pub fn file( + mut self, + value: impl Into>, + ) -> PinFileBuilder, S> { + self._fields.0 = Option::Some(value.into()); + PinFileBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl PinFileBuilder +where + St: pin_file_state::State, + St::File: pin_file_state::IsSet, +{ + /// Build the final struct. + pub fn build(self) -> PinFile { + PinFile { + file: self._fields.0.unwrap(), + extra_data: Default::default(), + } + } + /// Build the final struct with custom extra_data. + pub fn build_with_data(self, extra_data: BTreeMap>) -> PinFile { + PinFile { + file: self._fields.0.unwrap(), + extra_data: Some(extra_data), + } + } +} + +pub mod progress_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 BytesFetched; + type Size; + } + /// Empty state - all required fields are unset + pub struct Empty(()); + impl sealed::Sealed for Empty {} + impl State for Empty { + type BytesFetched = Unset; + type Size = Unset; + } + ///State transition - sets the `bytes_fetched` field to Set + pub struct SetBytesFetched(PhantomData St>); + impl sealed::Sealed for SetBytesFetched {} + impl State for SetBytesFetched { + type BytesFetched = Set; + type Size = St::Size; + } + ///State transition - sets the `size` field to Set + pub struct SetSize(PhantomData St>); + impl sealed::Sealed for SetSize {} + impl State for SetSize { + type BytesFetched = St::BytesFetched; + type Size = Set; + } + /// Marker types for field names + #[allow(non_camel_case_types)] + pub mod members { + ///Marker type for the `bytes_fetched` field + pub struct bytes_fetched(()); + ///Marker type for the `size` field + pub struct size(()); + } +} + +/// Builder for constructing an instance of this type. +pub struct ProgressBuilder { + _state: PhantomData St>, + _fields: (Option, Option), + _type: PhantomData S>, +} + +impl Progress { + /// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed + pub fn new() -> ProgressBuilder { + ProgressBuilder::new() + } +} + +impl Progress { + /// Create a new builder for this type + pub fn builder() -> ProgressBuilder { + ProgressBuilder::builder() + } +} + +impl ProgressBuilder { + /// Create a new builder with all fields unset, using the default string type, if needed + pub fn new() -> Self { + ProgressBuilder { + _state: PhantomData, + _fields: (None, None), + _type: PhantomData, + } + } +} + +impl ProgressBuilder { + /// Create a new builder with all fields unset + pub fn builder() -> Self { + ProgressBuilder { + _state: PhantomData, + _fields: (None, None), + _type: PhantomData, + } + } +} + +impl ProgressBuilder +where + St: progress_state::State, + St::BytesFetched: progress_state::IsUnset, +{ + /// Set the `bytesFetched` field (required) + pub fn bytes_fetched( + mut self, + value: impl Into, + ) -> ProgressBuilder, S> { + self._fields.0 = Option::Some(value.into()); + ProgressBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl ProgressBuilder +where + St: progress_state::State, + St::Size: progress_state::IsUnset, +{ + /// Set the `size` field (required) + pub fn size( + mut self, + value: impl Into, + ) -> ProgressBuilder, S> { + self._fields.1 = Option::Some(value.into()); + ProgressBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl ProgressBuilder +where + St: progress_state::State, + St::BytesFetched: progress_state::IsSet, + St::Size: progress_state::IsSet, +{ + /// Build the final struct. + pub fn build(self) -> Progress { + Progress { + bytes_fetched: self._fields.0.unwrap(), + size: self._fields.1.unwrap(), + extra_data: Default::default(), + } + } + /// Build the final struct with custom extra_data. + pub fn build_with_data(self, extra_data: BTreeMap>) -> Progress { + Progress { + bytes_fetched: self._fields.0.unwrap(), + size: self._fields.1.unwrap(), + extra_data: Some(extra_data), + } + } +} + +fn lexicon_doc_dev_atfs_repo_pinFile() -> 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("dev.atfs.repo.pinFile"), + defs: { + let mut map = BTreeMap::new(); + map.insert( + SmolStr::new_static("main"), + LexUserType::XrpcProcedure(LexXrpcProcedure { + input: Some(LexXrpcBody { + encoding: CowStr::new_static("application/json"), + schema: Some(LexXrpcBodySchema::Object(LexObject { + required: Some(vec![SmolStr::new_static("file")]), + properties: { + #[allow(unused_mut)] + let mut map = BTreeMap::new(); + map.insert( + SmolStr::new_static("file"), + LexObjectProperty::Ref(LexRef { + r#ref: CowStr::new_static("dev.atfs.file"), + ..Default::default() + }), + ); + map + }, + ..Default::default() + })), + ..Default::default() + }), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("progress"), + LexUserType::Object(LexObject { + required: Some(vec![ + SmolStr::new_static("bytesFetched"), + SmolStr::new_static("size"), + ]), + properties: { + #[allow(unused_mut)] + let mut map = BTreeMap::new(); + map.insert( + SmolStr::new_static("bytesFetched"), + LexObjectProperty::Integer(LexInteger { + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("size"), + LexObjectProperty::Integer(LexInteger { + ..Default::default() + }), + ); + map + }, + ..Default::default() + }), + ); + map + }, + ..Default::default() + } +} diff --git a/crates/jacquard-api/src/dev_atfs/repo/upload_file.rs b/crates/jacquard-api/src/dev_atfs/repo/upload_file.rs new file mode 100644 index 000000000..d3f1ffe31 --- /dev/null +++ b/crates/jacquard-api/src/dev_atfs/repo/upload_file.rs @@ -0,0 +1,122 @@ +// @generated by jacquard-lexicon. DO NOT EDIT. +// +// Lexicon: dev.atfs.repo.uploadFile +// +// 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::deps::bytes::Bytes; +use jacquard_common::deps::smol_str::SmolStr; +use jacquard_common::types::blob::BlobRef; +use jacquard_common::types::cid::CidLink; +use jacquard_common::types::value::Data; +use jacquard_common::{BosStr, CowStr, DefaultStr, FromStaticStr}; +use jacquard_derive::{IntoStatic, open_union}; +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde(rename_all = "camelCase")] +pub struct UploadFile { + pub body: Bytes, +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct UploadFileOutput { + ///The PDS's own uploadBlob response shape: the uploaded bytes' blessed CID (see dev.atfs.file's cid field), the mimeType recorded (defaulting to application/octet-stream when the request carried no Content-Type), and size in bytes. + pub blob: BlobRef, + ///atfs's own addition to the PDS response shape, absent from a plain com.atproto.repo.uploadBlob response: the CID to fetch the just-uploaded file over the IPFS network, exactly as dev.atfs.file's ipfsRoot field documents — the UnixFS root for a large file, or equal to blob's own CID when it fits a single Bitswap block. Standard atproto clients ignore unknown top-level fields, so this stays response-compatible with the PDS. Omitted (not a misleading zero value) on the rare occasion indexing hasn't finished yet; the file is already safely stored either way, and a later dev.atfs.repo.getFile or /ipfs/ request is unaffected. + #[serde(skip_serializing_if = "Option::is_none")] + pub ipfs_root: Option>, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +#[derive( + Serialize, Deserialize, Debug, Clone, PartialEq, Eq, thiserror::Error, miette::Diagnostic, +)] +#[serde(tag = "error", content = "message")] +pub enum UploadFileError { + /// The request body exceeds this instance's maximum blob size. + #[serde(rename = "BlobTooLarge")] + BlobTooLarge(Option), + /// Catch-all for unknown error codes. + #[serde(untagged)] + Other { + error: SmolStr, + message: Option, + }, +} + +impl core::fmt::Display for UploadFileError { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + match self { + Self::BlobTooLarge(msg) => { + write!(f, "BlobTooLarge")?; + if let Some(msg) = msg { + write!(f, ": {}", msg)?; + } + Ok(()) + } + Self::Other { error, message } => { + write!(f, "{}", error)?; + if let Some(msg) = message { + write!(f, ": {}", msg)?; + } + Ok(()) + } + } + } +} + +/** Response marker for the `dev.atfs.repo.uploadFile` procedure. + +Implements `jacquard_common::xrpc::XrpcResp`; successful bodies decode as `Self::Output`, which is `UploadFileOutput` for this endpoint.*/ +pub struct UploadFileResponse; +impl jacquard_common::xrpc::XrpcResp for UploadFileResponse { + const NSID: &'static str = "dev.atfs.repo.uploadFile"; + const ENCODING: &'static str = "application/json"; + type Output = UploadFileOutput; + type Err = UploadFileError; +} + +impl jacquard_common::xrpc::XrpcRequest for UploadFile { + const NSID: &'static str = "dev.atfs.repo.uploadFile"; + const METHOD: jacquard_common::xrpc::XrpcMethod = + jacquard_common::xrpc::XrpcMethod::Procedure("*/*"); + type Response = UploadFileResponse; + fn encode_body(&self, buffer: &mut Vec) -> Result<(), jacquard_common::xrpc::EncodeError> + where + Self: Serialize, + { + Ok(buffer.extend_from_slice(self.body.as_ref())) + } + fn decode_body<'de>(body: &'de [u8]) -> Result + where + Self: Deserialize<'de>, + { + Ok(Self { + body: jacquard_common::deps::bytes::Bytes::copy_from_slice(body), + }) + } +} + +/** Endpoint marker for the `dev.atfs.repo.uploadFile` procedure. + +Path: `/xrpc/dev.atfs.repo.uploadFile`. The request payload type is `UploadFile`; send that request with `jacquard::Client` or use this marker through lower-level `XrpcEndpoint` APIs.*/ +pub struct UploadFileRequest; +impl jacquard_common::xrpc::XrpcEndpoint for UploadFileRequest { + const PATH: &'static str = "/xrpc/dev.atfs.repo.uploadFile"; + const METHOD: jacquard_common::xrpc::XrpcMethod = + jacquard_common::xrpc::XrpcMethod::Procedure("*/*"); + type Request = UploadFile; + type Response = UploadFileResponse; +} diff --git a/crates/jacquard-api/src/dev_atfs/server.rs b/crates/jacquard-api/src/dev_atfs/server.rs new file mode 100644 index 000000000..2f167e47b --- /dev/null +++ b/crates/jacquard-api/src/dev_atfs/server.rs @@ -0,0 +1,327 @@ +// @generated by jacquard-lexicon. DO NOT EDIT. +// +// Lexicon: dev.atfs.server +// +// 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, 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 = "dev.atfs.server", + tag = "$type", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct Server { + ///The complete upload allowlist: atproto accounts permitted to call uploadFile/uploadBlob and pinFile. Required, and the owner is NOT implicitly included — an operator who wants to upload to their own instance must list themselves like any other account. DIDs only, never handles: an entry then survives a handle change, and a reverse index over accounts can answer 'which atfs instances can this person use' without resolving anything first. + pub accounts: Vec>, + ///Other atfs instances this one mirrors, each named by the at-uri of that instance's own dev.atfs.server record (at://{their-owner}/dev.atfs.server/{their-peer-id}). Identity rather than a URL, so a followed instance can move without breaking the follow: the follower resolves this record to learn where to poll (its bare-domain did:web serviceDid, derived the same way as above) and whose name to hold the mirrored claims under (that same serviceDid, or an identity derived from its peer ID when it declares none). The follower periodically walks the followed instance's dev.atfs.repo.listFiles, pins whatever is new, and releases whatever has been absent from two consecutive listings. Following is unilateral and needs no consent: listFiles is public and every pinned cid is already a DHT provider record, so an opt-in would be unenforceable. Only directly-claimed content is exported by listFiles, so following an instance never transitively mirrors what *it* follows — follow each origin you want. Removing an entry releases every claim that instance's mirror held here, and the content is deleted once nothing else claims it. + #[serde(skip_serializing_if = "Option::is_none")] + pub follows: Option>>, + ///This instance's own identity and address. It's the `aud` uploaders must address in their inter-service auth JWTs, and — only when it's a bare-domain did:web (exactly one segment after `did:web:`, so no path and no port suffix: `did:web:atfs.example.com`, never `did:web:atfs.example.com:user:alice` or an encoded-port form) — it also doubles as this instance's single HTTPS base URL, and atfs serves its own DID document at that domain's /.well-known/did.json. Uploads stay disabled until this is a bare-domain did:web and accounts names at least one account. + #[serde(skip_serializing_if = "Option::is_none")] + pub service_did: 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 ServerGetRecordOutput { + #[serde(skip_serializing_if = "Option::is_none")] + pub cid: Option>, + pub uri: AtUri, + pub value: Server, +} + +impl Server { + 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 ServerRecord; +impl XrpcResp for ServerRecord { + const NSID: &'static str = "dev.atfs.server"; + const ENCODING: &'static str = "application/json"; + type Output = ServerGetRecordOutput; + type Err = RecordError; +} + +impl From> for Server { + fn from(output: ServerGetRecordOutput) -> Self { + output.value + } +} + +impl Collection for Server { + const NSID: &'static str = "dev.atfs.server"; + type Record = ServerRecord; +} + +impl Collection for ServerRecord { + const NSID: &'static str = "dev.atfs.server"; + type Record = ServerRecord; +} + +impl LexiconSchema for Server { + fn nsid() -> &'static str { + "dev.atfs.server" + } + fn def_name() -> &'static str { + "main" + } + fn lexicon_doc() -> LexiconDoc<'static> { + lexicon_doc_dev_atfs_server() + } + fn validate(&self) -> Result<(), ConstraintError> { + Ok(()) + } +} + +pub mod server_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 Accounts; + } + /// Empty state - all required fields are unset + pub struct Empty(()); + impl sealed::Sealed for Empty {} + impl State for Empty { + type Accounts = Unset; + } + ///State transition - sets the `accounts` field to Set + pub struct SetAccounts(PhantomData St>); + impl sealed::Sealed for SetAccounts {} + impl State for SetAccounts { + type Accounts = Set; + } + /// Marker types for field names + #[allow(non_camel_case_types)] + pub mod members { + ///Marker type for the `accounts` field + pub struct accounts(()); + } +} + +/// Builder for constructing an instance of this type. +pub struct ServerBuilder { + _state: PhantomData St>, + _fields: (Option>>, Option>>, Option>), + _type: PhantomData S>, +} + +impl Server { + /// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed + pub fn new() -> ServerBuilder { + ServerBuilder::new() + } +} + +impl Server { + /// Create a new builder for this type + pub fn builder() -> ServerBuilder { + ServerBuilder::builder() + } +} + +impl ServerBuilder { + /// Create a new builder with all fields unset, using the default string type, if needed + pub fn new() -> Self { + ServerBuilder { + _state: PhantomData, + _fields: (None, None, None), + _type: PhantomData, + } + } +} + +impl ServerBuilder { + /// Create a new builder with all fields unset + pub fn builder() -> Self { + ServerBuilder { + _state: PhantomData, + _fields: (None, None, None), + _type: PhantomData, + } + } +} + +impl ServerBuilder +where + St: server_state::State, + St::Accounts: server_state::IsUnset, +{ + /// Set the `accounts` field (required) + pub fn accounts( + mut self, + value: impl Into>>, + ) -> ServerBuilder, S> { + self._fields.0 = Option::Some(value.into()); + ServerBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl ServerBuilder { + /// Set the `follows` field (optional) + pub fn follows(mut self, value: impl Into>>>) -> Self { + self._fields.1 = value.into(); + self + } + /// Set the `follows` field to an Option value (optional) + pub fn maybe_follows(mut self, value: Option>>) -> Self { + self._fields.1 = value; + self + } +} + +impl ServerBuilder { + /// Set the `serviceDid` field (optional) + pub fn service_did(mut self, value: impl Into>>) -> Self { + self._fields.2 = value.into(); + self + } + /// Set the `serviceDid` field to an Option value (optional) + pub fn maybe_service_did(mut self, value: Option>) -> Self { + self._fields.2 = value; + self + } +} + +impl ServerBuilder +where + St: server_state::State, + St::Accounts: server_state::IsSet, +{ + /// Build the final struct. + pub fn build(self) -> Server { + Server { + accounts: self._fields.0.unwrap(), + follows: self._fields.1, + service_did: self._fields.2, + extra_data: Default::default(), + } + } + /// Build the final struct with custom extra_data. + pub fn build_with_data(self, extra_data: BTreeMap>) -> Server { + Server { + accounts: self._fields.0.unwrap(), + follows: self._fields.1, + service_did: self._fields.2, + extra_data: Some(extra_data), + } + } +} + +fn lexicon_doc_dev_atfs_server() -> 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("dev.atfs.server"), + defs: { + let mut map = BTreeMap::new(); + map.insert( + SmolStr::new_static("main"), + LexUserType::Record(LexRecord { + key: Some(CowStr::new_static("any")), + record: LexRecordRecord::Object(LexObject { + required: Some(vec![SmolStr::new_static("accounts")]), + properties: { + #[allow(unused_mut)] + let mut map = BTreeMap::new(); + map.insert( + SmolStr::new_static("accounts"), + LexObjectProperty::Array(LexArray { + description: Some( + CowStr::new_static( + "The complete upload allowlist: atproto accounts permitted to call uploadFile/uploadBlob and pinFile. Required, and the owner is NOT implicitly included — an operator who wants to upload to their own instance must list themselves like any other account. DIDs only, never handles: an entry then survives a handle change, and a reverse index over accounts can answer 'which atfs instances can this person use' without resolving anything first.", + ), + ), + items: LexArrayItem::String(LexString { + format: Some(LexStringFormat::Did), + ..Default::default() + }), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("follows"), + LexObjectProperty::Array(LexArray { + description: Some( + CowStr::new_static( + "Other atfs instances this one mirrors, each named by the at-uri of that instance's own dev.atfs.server record (at://{their-owner}/dev.atfs.server/{their-peer-id}). Identity rather than a URL, so a followed instance can move without breaking the follow: the follower resolves this record to learn where to poll (its bare-domain did:web serviceDid, derived the same way as above) and whose name to hold the mirrored claims under (that same serviceDid, or an identity derived from its peer ID when it declares none). The follower periodically walks the followed instance's dev.atfs.repo.listFiles, pins whatever is new, and releases whatever has been absent from two consecutive listings. Following is unilateral and needs no consent: listFiles is public and every pinned cid is already a DHT provider record, so an opt-in would be unenforceable. Only directly-claimed content is exported by listFiles, so following an instance never transitively mirrors what *it* follows — follow each origin you want. Removing an entry releases every claim that instance's mirror held here, and the content is deleted once nothing else claims it.", + ), + ), + items: LexArrayItem::String(LexString { + format: Some(LexStringFormat::AtUri), + ..Default::default() + }), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("serviceDid"), + LexObjectProperty::String(LexString { + description: Some( + CowStr::new_static( + "This instance's own identity and address. It's the `aud` uploaders must address in their inter-service auth JWTs, and — only when it's a bare-domain did:web (exactly one segment after `did:web:`, so no path and no port suffix: `did:web:atfs.example.com`, never `did:web:atfs.example.com:user:alice` or an encoded-port form) — it also doubles as this instance's single HTTPS base URL, and atfs serves its own DID document at that domain's /.well-known/did.json. Uploads stay disabled until this is a bare-domain did:web and accounts names at least one account.", + ), + ), + format: Some(LexStringFormat::Did), + ..Default::default() + }), + ); + map + }, + ..Default::default() + }), + ..Default::default() + }), + ); + map + }, + ..Default::default() + } +} diff --git a/crates/jacquard-api/src/dev_fudgeu/experimental/atforumv1/feed/post.rs b/crates/jacquard-api/src/dev_fudgeu/experimental/atforumv1/feed/post.rs index ecdfe7bb3..39c5c430f 100644 --- a/crates/jacquard-api/src/dev_fudgeu/experimental/atforumv1/feed/post.rs +++ b/crates/jacquard-api/src/dev_fudgeu/experimental/atforumv1/feed/post.rs @@ -140,6 +140,26 @@ impl LexiconSchema for Post { }); } } + for value in &self.tags { + #[allow(unused_comparisons)] + if ::len(value.as_ref()) > 25usize { + return Err(ConstraintError::MaxLength { + path: ValidationPath::from_field("tags"), + max: 25usize, + actual: ::len(value.as_ref()), + }); + } + } + for value in &self.tags { + #[allow(unused_comparisons)] + if ::len(value.as_ref()) < 1usize { + return Err(ConstraintError::MinLength { + path: ValidationPath::from_field("tags"), + min: 1usize, + actual: ::len(value.as_ref()), + }); + } + } { let value = &self.title; #[allow(unused_comparisons)] diff --git a/crates/jacquard-api/src/dev_fudgeu/experimental/atforumv1/feed/question.rs b/crates/jacquard-api/src/dev_fudgeu/experimental/atforumv1/feed/question.rs index 8f0276f20..dde0b55ae 100644 --- a/crates/jacquard-api/src/dev_fudgeu/experimental/atforumv1/feed/question.rs +++ b/crates/jacquard-api/src/dev_fudgeu/experimental/atforumv1/feed/question.rs @@ -138,6 +138,26 @@ impl LexiconSchema for Question { }); } } + for value in &self.tags { + #[allow(unused_comparisons)] + if ::len(value.as_ref()) > 25usize { + return Err(ConstraintError::MaxLength { + path: ValidationPath::from_field("tags"), + max: 25usize, + actual: ::len(value.as_ref()), + }); + } + } + for value in &self.tags { + #[allow(unused_comparisons)] + if ::len(value.as_ref()) < 1usize { + return Err(ConstraintError::MinLength { + path: ValidationPath::from_field("tags"), + min: 1usize, + actual: ::len(value.as_ref()), + }); + } + } { let value = &self.title; #[allow(unused_comparisons)] diff --git a/crates/jacquard-api/src/events_smokesignal/lfg.rs b/crates/jacquard-api/src/events_smokesignal/lfg.rs index 971daf3d2..b2bd4a7c2 100644 --- a/crates/jacquard-api/src/events_smokesignal/lfg.rs +++ b/crates/jacquard-api/src/events_smokesignal/lfg.rs @@ -134,6 +134,28 @@ impl LexiconSchema for Lfg { }); } } + for value in &self.tags { + #[allow(unused_comparisons)] + if ::len(value.as_ref()) > 64usize { + return Err(ConstraintError::MaxLength { + path: ValidationPath::from_field("tags"), + max: 64usize, + actual: ::len(value.as_ref()), + }); + } + } + for value in &self.tags { + { + let count = UnicodeSegmentation::graphemes(value.as_ref(), true).count(); + if count > 64usize { + return Err(ConstraintError::MaxGraphemes { + path: ValidationPath::from_field("tags"), + max: 64usize, + actual: count, + }); + } + } + } Ok(()) } } diff --git a/crates/jacquard-api/src/fm_teal/alpha/feed/play.rs b/crates/jacquard-api/src/fm_teal/alpha/feed/play.rs index ca08ad983..917d14f17 100644 --- a/crates/jacquard-api/src/fm_teal/alpha/feed/play.rs +++ b/crates/jacquard-api/src/fm_teal/alpha/feed/play.rs @@ -143,6 +143,44 @@ impl LexiconSchema for Play { lexicon_doc_fm_teal_alpha_feed_play() } fn validate(&self) -> Result<(), ConstraintError> { + if let Some(values) = &self.artist_names { + for value in values { + #[allow(unused_comparisons)] + if ::len(value.as_ref()) > 256usize { + return Err(ConstraintError::MaxLength { + path: ValidationPath::from_field("artist_names"), + max: 256usize, + actual: ::len(value.as_ref()), + }); + } + } + } + if let Some(values) = &self.artist_names { + for value in values { + #[allow(unused_comparisons)] + if ::len(value.as_ref()) < 1usize { + return Err(ConstraintError::MinLength { + path: ValidationPath::from_field("artist_names"), + min: 1usize, + actual: ::len(value.as_ref()), + }); + } + } + } + if let Some(values) = &self.artist_names { + for value in values { + { + let count = UnicodeSegmentation::graphemes(value.as_ref(), true).count(); + if count > 2560usize { + return Err(ConstraintError::MaxGraphemes { + path: ValidationPath::from_field("artist_names"), + max: 2560usize, + actual: count, + }); + } + } + } + } if let Some(ref value) = self.release_discriminant { #[allow(unused_comparisons)] if ::len(value.as_ref()) > 128usize { diff --git a/crates/jacquard-api/src/games_gamesgamesgamesgames/list_games.rs b/crates/jacquard-api/src/games_gamesgamesgamesgames/list_games.rs index ffe0f944b..49ef00f77 100644 --- a/crates/jacquard-api/src/games_gamesgamesgamesgames/list_games.rs +++ b/crates/jacquard-api/src/games_gamesgamesgamesgames/list_games.rs @@ -28,6 +28,7 @@ pub struct ListGames { pub age_ratings: Option>, #[serde(skip_serializing_if = "Option::is_none")] pub application_types: Option>, + /// (max length: 256) #[serde(skip_serializing_if = "Option::is_none")] pub cursor: Option, #[serde(skip_serializing_if = "Option::is_none")] @@ -39,6 +40,10 @@ pub struct ListGames { #[serde(skip_serializing_if = "Option::is_none")] pub include_cancelled: Option, /// Defaults to `false`. + #[serde(default = "_default_include_unpublished")] + #[serde(skip_serializing_if = "Option::is_none")] + pub include_unpublished: Option, + /// Defaults to `false`. #[serde(default = "_default_include_unrated")] #[serde(skip_serializing_if = "Option::is_none")] pub include_unrated: Option, @@ -50,11 +55,11 @@ pub struct ListGames { pub modes: Option>, #[serde(skip_serializing_if = "Option::is_none")] pub player_perspectives: Option>, - /// Defaults to `"indexed_at"`. + /// Defaults to `"indexed_at"`. Max length: 64. #[serde(default = "_default_sort")] #[serde(skip_serializing_if = "Option::is_none")] pub sort: Option, - /// Defaults to `"desc"`. + /// Defaults to `"desc"`. Max length: 64. #[serde(default = "_default_sort_direction")] #[serde(skip_serializing_if = "Option::is_none")] pub sort_direction: Option, @@ -107,6 +112,10 @@ fn _default_include_cancelled() -> Option { Some(false) } +fn _default_include_unpublished() -> Option { + Some(false) +} + fn _default_include_unrated() -> Option { Some(false) } @@ -153,6 +162,7 @@ pub struct ListGamesBuilder Option>, Option, Option, + Option, Option, Option>, Option>, @@ -183,7 +193,7 @@ impl ListGamesBuilder { ListGamesBuilder { _state: PhantomData, _fields: ( - None, None, None, None, None, None, None, None, None, None, None, None, None, + None, None, None, None, None, None, None, None, None, None, None, None, None, None, ), _type: PhantomData, } @@ -196,7 +206,7 @@ impl ListGamesBuilder { ListGamesBuilder { _state: PhantomData, _fields: ( - None, None, None, None, None, None, None, None, None, None, None, None, None, + None, None, None, None, None, None, None, None, None, None, None, None, None, None, ), _type: PhantomData, } @@ -281,15 +291,28 @@ impl ListGamesBuilder { } } +impl ListGamesBuilder { + /// Set the `includeUnpublished` field (optional) + pub fn include_unpublished(mut self, value: impl Into>) -> Self { + self._fields.6 = value.into(); + self + } + /// Set the `includeUnpublished` field to an Option value (optional) + pub fn maybe_include_unpublished(mut self, value: Option) -> Self { + self._fields.6 = value; + self + } +} + impl ListGamesBuilder { /// Set the `includeUnrated` field (optional) pub fn include_unrated(mut self, value: impl Into>) -> Self { - self._fields.6 = value.into(); + self._fields.7 = value.into(); self } /// Set the `includeUnrated` field to an Option value (optional) pub fn maybe_include_unrated(mut self, value: Option) -> Self { - self._fields.6 = value; + self._fields.7 = value; self } } @@ -297,12 +320,12 @@ impl ListGamesBuilder { impl ListGamesBuilder { /// Set the `limit` field (optional) pub fn limit(mut self, value: impl Into>) -> Self { - self._fields.7 = value.into(); + self._fields.8 = value.into(); self } /// Set the `limit` field to an Option value (optional) pub fn maybe_limit(mut self, value: Option) -> Self { - self._fields.7 = value; + self._fields.8 = value; self } } @@ -310,12 +333,12 @@ impl ListGamesBuilder { impl ListGamesBuilder { /// Set the `modes` field (optional) pub fn modes(mut self, value: impl Into>>) -> Self { - self._fields.8 = value.into(); + self._fields.9 = value.into(); self } /// Set the `modes` field to an Option value (optional) pub fn maybe_modes(mut self, value: Option>) -> Self { - self._fields.8 = value; + self._fields.9 = value; self } } @@ -323,12 +346,12 @@ impl ListGamesBuilder { impl ListGamesBuilder { /// Set the `playerPerspectives` field (optional) pub fn player_perspectives(mut self, value: impl Into>>) -> Self { - self._fields.9 = value.into(); + self._fields.10 = value.into(); self } /// Set the `playerPerspectives` field to an Option value (optional) pub fn maybe_player_perspectives(mut self, value: Option>) -> Self { - self._fields.9 = value; + self._fields.10 = value; self } } @@ -336,12 +359,12 @@ impl ListGamesBuilder { impl ListGamesBuilder { /// Set the `sort` field (optional) pub fn sort(mut self, value: impl Into>) -> Self { - self._fields.10 = value.into(); + self._fields.11 = value.into(); self } /// Set the `sort` field to an Option value (optional) pub fn maybe_sort(mut self, value: Option) -> Self { - self._fields.10 = value; + self._fields.11 = value; self } } @@ -349,12 +372,12 @@ impl ListGamesBuilder { impl ListGamesBuilder { /// Set the `sortDirection` field (optional) pub fn sort_direction(mut self, value: impl Into>) -> Self { - self._fields.11 = value.into(); + self._fields.12 = value.into(); self } /// Set the `sortDirection` field to an Option value (optional) pub fn maybe_sort_direction(mut self, value: Option) -> Self { - self._fields.11 = value; + self._fields.12 = value; self } } @@ -362,12 +385,12 @@ impl ListGamesBuilder { impl ListGamesBuilder { /// Set the `themes` field (optional) pub fn themes(mut self, value: impl Into>>) -> Self { - self._fields.12 = value.into(); + self._fields.13 = value.into(); self } /// Set the `themes` field to an Option value (optional) pub fn maybe_themes(mut self, value: Option>) -> Self { - self._fields.12 = value; + self._fields.13 = value; self } } @@ -385,13 +408,14 @@ where did: self._fields.3, genres: self._fields.4, include_cancelled: self._fields.5, - include_unrated: self._fields.6, - limit: self._fields.7, - modes: self._fields.8, - player_perspectives: self._fields.9, - sort: self._fields.10, - sort_direction: self._fields.11, - themes: self._fields.12, + include_unpublished: self._fields.6, + include_unrated: self._fields.7, + limit: self._fields.8, + modes: self._fields.9, + player_perspectives: self._fields.10, + sort: self._fields.11, + sort_direction: self._fields.12, + themes: self._fields.13, } } } diff --git a/crates/jacquard-api/src/garden_goals/goal.rs b/crates/jacquard-api/src/garden_goals/goal.rs index d14f95f78..1677c58c9 100644 --- a/crates/jacquard-api/src/garden_goals/goal.rs +++ b/crates/jacquard-api/src/garden_goals/goal.rs @@ -148,6 +148,18 @@ impl LexiconSchema for Goal { }); } } + if let Some(values) = &self.categories { + for value in values { + #[allow(unused_comparisons)] + if ::len(value.as_ref()) > 64usize { + return Err(ConstraintError::MaxLength { + path: ValidationPath::from_field("categories"), + max: 64usize, + actual: ::len(value.as_ref()), + }); + } + } + } if let Some(ref value) = self.completed_accent_color { #[allow(unused_comparisons)] if ::len(value.as_ref()) > 50usize { diff --git a/crates/jacquard-api/src/garden_lexicon/service.rs b/crates/jacquard-api/src/garden_lexicon/service.rs index 0bdbbfd56..c85844a70 100644 --- a/crates/jacquard-api/src/garden_lexicon/service.rs +++ b/crates/jacquard-api/src/garden_lexicon/service.rs @@ -180,6 +180,18 @@ impl LexiconSchema for Method { lexicon_doc_garden_lexicon_service() } fn validate(&self) -> Result<(), ConstraintError> { + if let Some(values) = &self.auth_methods { + for value in values { + #[allow(unused_comparisons)] + if ::len(value.as_ref()) > 50usize { + return Err(ConstraintError::MaxLength { + path: ValidationPath::from_field("auth_methods"), + max: 50usize, + actual: ::len(value.as_ref()), + }); + } + } + } Ok(()) } } diff --git a/crates/jacquard-api/src/internal_bsky/actor/get_profiles.rs b/crates/jacquard-api/src/internal_bsky/actor/get_profiles.rs index 11a7afcf2..eee8e4cec 100644 --- a/crates/jacquard-api/src/internal_bsky/actor/get_profiles.rs +++ b/crates/jacquard-api/src/internal_bsky/actor/get_profiles.rs @@ -25,6 +25,10 @@ use serde::{Deserialize, Serialize}; )] pub struct GetProfiles { pub dids: Vec>, + /// Defaults to `false`. + #[serde(default = "_default_include_takedowns")] + #[serde(skip_serializing_if = "Option::is_none")] + pub include_takedowns: Option, #[serde(skip_serializing_if = "Option::is_none")] pub social_proof: Option>>, #[serde(skip_serializing_if = "Option::is_none")] @@ -70,6 +74,10 @@ impl jacquard_common::xrpc::XrpcEndpoint for GetProfilesRequest { type Response = GetProfilesResponse; } +fn _default_include_takedowns() -> Option { + Some(false) +} + pub mod get_profiles_state { pub use crate::builder_types::{IsSet, IsUnset, Set, Unset}; @@ -105,7 +113,12 @@ pub mod get_profiles_state { /// Builder for constructing an instance of this type. pub struct GetProfilesBuilder { _state: PhantomData St>, - _fields: (Option>>, Option>>, Option>), + _fields: ( + Option>>, + Option, + Option>>, + Option>, + ), _type: PhantomData S>, } @@ -128,7 +141,7 @@ impl GetProfilesBuilder { pub fn new() -> Self { GetProfilesBuilder { _state: PhantomData, - _fields: (None, None, None), + _fields: (None, None, None, None), _type: PhantomData, } } @@ -139,7 +152,7 @@ impl GetProfilesBuilder { pub fn builder() -> Self { GetProfilesBuilder { _state: PhantomData, - _fields: (None, None, None), + _fields: (None, None, None, None), _type: PhantomData, } } @@ -164,15 +177,28 @@ where } } +impl GetProfilesBuilder { + /// Set the `includeTakedowns` field (optional) + pub fn include_takedowns(mut self, value: impl Into>) -> Self { + self._fields.1 = value.into(); + self + } + /// Set the `includeTakedowns` field to an Option value (optional) + pub fn maybe_include_takedowns(mut self, value: Option) -> Self { + self._fields.1 = value; + self + } +} + impl GetProfilesBuilder { /// Set the `socialProof` field (optional) pub fn social_proof(mut self, value: impl Into>>>) -> Self { - self._fields.1 = value.into(); + self._fields.2 = value.into(); self } /// Set the `socialProof` field to an Option value (optional) pub fn maybe_social_proof(mut self, value: Option>>) -> Self { - self._fields.1 = value; + self._fields.2 = value; self } } @@ -180,12 +206,12 @@ impl GetProfilesBuilder { impl GetProfilesBuilder { /// Set the `viewer` field (optional) pub fn viewer(mut self, value: impl Into>>) -> Self { - self._fields.2 = value.into(); + self._fields.3 = value.into(); self } /// Set the `viewer` field to an Option value (optional) pub fn maybe_viewer(mut self, value: Option>) -> Self { - self._fields.2 = value; + self._fields.3 = value; self } } @@ -199,8 +225,9 @@ where pub fn build(self) -> GetProfiles { GetProfiles { dids: self._fields.0.unwrap(), - social_proof: self._fields.1, - viewer: self._fields.2, + include_takedowns: self._fields.1, + social_proof: self._fields.2, + viewer: self._fields.3, } } } diff --git a/crates/jacquard-api/src/io_atcr.rs b/crates/jacquard-api/src/io_atcr.rs index 68bc94131..c5e996943 100644 --- a/crates/jacquard-api/src/io_atcr.rs +++ b/crates/jacquard-api/src/io_atcr.rs @@ -4,6 +4,7 @@ // Any manual changes will be overwritten on the next regeneration. //! Generated bindings for the `io.atcr` Lexicon namespace/module. +pub mod auth_full_app; pub mod hold; pub mod manifest; pub mod repo; diff --git a/crates/jacquard-api/src/io_atcr/auth_full_app.rs b/crates/jacquard-api/src/io_atcr/auth_full_app.rs new file mode 100644 index 000000000..ca2f84277 --- /dev/null +++ b/crates/jacquard-api/src/io_atcr/auth_full_app.rs @@ -0,0 +1,8 @@ +// @generated by jacquard-lexicon. DO NOT EDIT. +// +// Lexicon: io.atcr.authFullApp +// +// This file was automatically generated from Lexicon schemas. +// Any manual changes will be overwritten on the next regeneration. + +use jacquard_common::{BosStr, DefaultStr, FromStaticStr}; diff --git a/crates/jacquard-api/src/io_atcr/hold.rs b/crates/jacquard-api/src/io_atcr/hold.rs index 46ccdd621..cbb17cfc5 100644 --- a/crates/jacquard-api/src/io_atcr/hold.rs +++ b/crates/jacquard-api/src/io_atcr/hold.rs @@ -10,6 +10,7 @@ pub mod complete_upload; pub mod crew; pub mod delete_user_data; pub mod export_user_data; +pub mod get_layers_for_manifest; pub mod get_part_upload_url; pub mod get_quota; pub mod initiate_upload; diff --git a/crates/jacquard-api/src/io_atcr/hold/crew.rs b/crates/jacquard-api/src/io_atcr/hold/crew.rs index 6440f605e..1546ad695 100644 --- a/crates/jacquard-api/src/io_atcr/hold/crew.rs +++ b/crates/jacquard-api/src/io_atcr/hold/crew.rs @@ -194,6 +194,16 @@ impl LexiconSchema for Crew { lexicon_doc_io_atcr_hold_crew() } fn validate(&self) -> Result<(), ConstraintError> { + for value in &self.permissions { + #[allow(unused_comparisons)] + if ::len(value.as_ref()) > 64usize { + return Err(ConstraintError::MaxLength { + path: ValidationPath::from_field("permissions"), + max: 64usize, + actual: ::len(value.as_ref()), + }); + } + } { let value = &self.role; #[allow(unused_comparisons)] diff --git a/crates/jacquard-api/src/io_atcr/hold/export_user_data.rs b/crates/jacquard-api/src/io_atcr/hold/export_user_data.rs index b27aa11f8..d737bb5c7 100644 --- a/crates/jacquard-api/src/io_atcr/hold/export_user_data.rs +++ b/crates/jacquard-api/src/io_atcr/hold/export_user_data.rs @@ -180,6 +180,18 @@ impl LexiconSchema for CrewExport { lexicon_doc_io_atcr_hold_exportUserData() } fn validate(&self) -> Result<(), ConstraintError> { + if let Some(values) = &self.permissions { + for value in values { + #[allow(unused_comparisons)] + if ::len(value.as_ref()) > 64usize { + return Err(ConstraintError::MaxLength { + path: ValidationPath::from_field("permissions"), + max: 64usize, + actual: ::len(value.as_ref()), + }); + } + } + } if let Some(ref value) = self.role { #[allow(unused_comparisons)] if ::len(value.as_ref()) > 32usize { diff --git a/crates/jacquard-api/src/io_atcr/hold/get_layers_for_manifest.rs b/crates/jacquard-api/src/io_atcr/hold/get_layers_for_manifest.rs new file mode 100644 index 000000000..4fe14aa14 --- /dev/null +++ b/crates/jacquard-api/src/io_atcr/hold/get_layers_for_manifest.rs @@ -0,0 +1,177 @@ +// @generated by jacquard-lexicon. DO NOT EDIT. +// +// Lexicon: io.atcr.hold.getLayersForManifest +// +// 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; + +use crate::io_atcr::hold::layer::Layer; +#[allow(unused_imports)] +use core::marker::PhantomData; +use jacquard_common::deps::smol_str::SmolStr; +use jacquard_common::types::string::AtUri; +use jacquard_common::types::value::Data; +use jacquard_common::{BosStr, DefaultStr, FromStaticStr}; +use jacquard_derive::IntoStatic; +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct GetLayersForManifest { + pub manifest: AtUri, +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct GetLayersForManifestOutput { + pub layers: Vec>, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +/** Response marker for the `io.atcr.hold.getLayersForManifest` query. + +Implements `jacquard_common::xrpc::XrpcResp`; successful bodies decode as `Self::Output`, which is `GetLayersForManifestOutput` for this endpoint.*/ +pub struct GetLayersForManifestResponse; +impl jacquard_common::xrpc::XrpcResp for GetLayersForManifestResponse { + const NSID: &'static str = "io.atcr.hold.getLayersForManifest"; + const ENCODING: &'static str = "application/json"; + type Output = GetLayersForManifestOutput; + type Err = jacquard_common::xrpc::GenericError; +} + +impl jacquard_common::xrpc::XrpcRequest for GetLayersForManifest { + const NSID: &'static str = "io.atcr.hold.getLayersForManifest"; + const METHOD: jacquard_common::xrpc::XrpcMethod = jacquard_common::xrpc::XrpcMethod::Query; + type Response = GetLayersForManifestResponse; +} + +/** Endpoint marker for the `io.atcr.hold.getLayersForManifest` query. + +Path: `/xrpc/io.atcr.hold.getLayersForManifest`. The request payload type is `GetLayersForManifest`; send that request with `jacquard::Client` or use this marker through lower-level `XrpcEndpoint` APIs.*/ +pub struct GetLayersForManifestRequest; +impl jacquard_common::xrpc::XrpcEndpoint for GetLayersForManifestRequest { + const PATH: &'static str = "/xrpc/io.atcr.hold.getLayersForManifest"; + const METHOD: jacquard_common::xrpc::XrpcMethod = jacquard_common::xrpc::XrpcMethod::Query; + type Request = GetLayersForManifest; + type Response = GetLayersForManifestResponse; +} + +pub mod get_layers_for_manifest_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 Manifest; + } + /// Empty state - all required fields are unset + pub struct Empty(()); + impl sealed::Sealed for Empty {} + impl State for Empty { + type Manifest = Unset; + } + ///State transition - sets the `manifest` field to Set + pub struct SetManifest(PhantomData St>); + impl sealed::Sealed for SetManifest {} + impl State for SetManifest { + type Manifest = Set; + } + /// Marker types for field names + #[allow(non_camel_case_types)] + pub mod members { + ///Marker type for the `manifest` field + pub struct manifest(()); + } +} + +/// Builder for constructing an instance of this type. +pub struct GetLayersForManifestBuilder< + St: get_layers_for_manifest_state::State, + S: BosStr = DefaultStr, +> { + _state: PhantomData St>, + _fields: (Option>,), + _type: PhantomData S>, +} + +impl GetLayersForManifest { + /// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed + pub fn new() -> GetLayersForManifestBuilder { + GetLayersForManifestBuilder::new() + } +} + +impl GetLayersForManifest { + /// Create a new builder for this type + pub fn builder() -> GetLayersForManifestBuilder { + GetLayersForManifestBuilder::builder() + } +} + +impl GetLayersForManifestBuilder { + /// Create a new builder with all fields unset, using the default string type, if needed + pub fn new() -> Self { + GetLayersForManifestBuilder { + _state: PhantomData, + _fields: (None,), + _type: PhantomData, + } + } +} + +impl GetLayersForManifestBuilder { + /// Create a new builder with all fields unset + pub fn builder() -> Self { + GetLayersForManifestBuilder { + _state: PhantomData, + _fields: (None,), + _type: PhantomData, + } + } +} + +impl GetLayersForManifestBuilder +where + St: get_layers_for_manifest_state::State, + St::Manifest: get_layers_for_manifest_state::IsUnset, +{ + /// Set the `manifest` field (required) + pub fn manifest( + mut self, + value: impl Into>, + ) -> GetLayersForManifestBuilder, S> { + self._fields.0 = Option::Some(value.into()); + GetLayersForManifestBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl GetLayersForManifestBuilder +where + St: get_layers_for_manifest_state::State, + St::Manifest: get_layers_for_manifest_state::IsSet, +{ + /// Build the final struct. + pub fn build(self) -> GetLayersForManifest { + GetLayersForManifest { + manifest: self._fields.0.unwrap(), + } + } +} diff --git a/crates/jacquard-api/src/io_atcr/hold/scan.rs b/crates/jacquard-api/src/io_atcr/hold/scan.rs index afbd843a6..46996383e 100644 --- a/crates/jacquard-api/src/io_atcr/hold/scan.rs +++ b/crates/jacquard-api/src/io_atcr/hold/scan.rs @@ -48,6 +48,9 @@ pub struct Scan { pub manifest: AtUri, ///Count of medium severity vulnerabilities pub medium: i64, + ///Optional human-readable explanation for non-ok status (e.g. 'unscannable artifact type application/vnd.cncf.helm.config.v1+json'). + #[serde(skip_serializing_if = "Option::is_none")] + pub reason: Option, ///Repository name (e.g., myapp) pub repository: S, ///SBOM blob (SPDX JSON format) uploaded to the hold's blob storage @@ -57,6 +60,9 @@ pub struct Scan { pub scanned_at: Datetime, ///Version of the scanner that produced this result (e.g., atcr-scanner-v1.0.0) pub scanner_version: S, + ///Outcome of the scan attempt. 'ok' (or omitted, for back-compat) means the scanner produced an SBOM. 'failed' means the scanner ran but errored. 'skipped' means the scanner intentionally bypassed this artifact type (e.g. helm charts). + #[serde(skip_serializing_if = "Option::is_none")] + pub status: Option>, ///Total vulnerability count pub total: i64, ///DID of the image owner @@ -68,6 +74,89 @@ pub struct Scan { pub extra_data: Option>>, } +/// Outcome of the scan attempt. 'ok' (or omitted, for back-compat) means the scanner produced an SBOM. 'failed' means the scanner ran but errored. 'skipped' means the scanner intentionally bypassed this artifact type (e.g. helm charts). + +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub enum ScanStatus { + Ok, + Failed, + Skipped, + Other(S), +} + +impl ScanStatus { + pub fn as_str(&self) -> &str { + match self { + Self::Ok => "ok", + Self::Failed => "failed", + Self::Skipped => "skipped", + 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() { + "ok" => Self::Ok, + "failed" => Self::Failed, + "skipped" => Self::Skipped, + _ => Self::Other(s), + } + } +} + +impl core::fmt::Display for ScanStatus { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!(f, "{}", self.as_str()) + } +} + +impl AsRef for ScanStatus { + fn as_ref(&self) -> &str { + self.as_str() + } +} + +impl Serialize for ScanStatus { + 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 ScanStatus { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = S::deserialize(deserializer)?; + Ok(Self::from_value(s)) + } +} + +impl Default for ScanStatus { + fn default() -> Self { + Self::Other(Default::default()) + } +} + +impl jacquard_common::IntoStatic for ScanStatus +where + S: BosStr + jacquard_common::IntoStatic, + S::Output: BosStr, +{ + type Output = ScanStatus; + fn into_static(self) -> Self::Output { + match self { + ScanStatus::Ok => ScanStatus::Ok, + ScanStatus::Failed => ScanStatus::Failed, + ScanStatus::Skipped => ScanStatus::Skipped, + ScanStatus::Other(v) => ScanStatus::Other(v.into_static()), + } + } +} + /// Typed wrapper for GetRecord response with this collection's record type. #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] @@ -163,6 +252,16 @@ impl LexiconSchema for Scan { }); } } + if let Some(ref value) = self.reason { + #[allow(unused_comparisons)] + if ::len(value.as_ref()) > 256usize { + return Err(ConstraintError::MaxLength { + path: ValidationPath::from_field("reason"), + max: 256usize, + actual: ::len(value.as_ref()), + }); + } + } { let value = &self.repository; #[allow(unused_comparisons)] @@ -208,6 +307,16 @@ impl LexiconSchema for Scan { }); } } + if let Some(ref value) = self.status { + #[allow(unused_comparisons)] + if ::len(value.as_ref()) > 32usize { + return Err(ConstraintError::MaxLength { + path: ValidationPath::from_field("status"), + max: 32usize, + actual: ::len(value.as_ref()), + }); + } + } { let value = &self.total; if *value < 0i64 { @@ -467,9 +576,11 @@ pub struct ScanBuilder { Option>, Option, Option, + Option, Option>, Option, Option, + Option>, Option, Option>, Option>, @@ -497,7 +608,7 @@ impl ScanBuilder { ScanBuilder { _state: PhantomData, _fields: ( - None, None, None, None, None, None, None, None, None, None, None, None, + None, None, None, None, None, None, None, None, None, None, None, None, None, None, ), _type: PhantomData, } @@ -510,7 +621,7 @@ impl ScanBuilder { ScanBuilder { _state: PhantomData, _fields: ( - None, None, None, None, None, None, None, None, None, None, None, None, + None, None, None, None, None, None, None, None, None, None, None, None, None, None, ), _type: PhantomData, } @@ -603,6 +714,19 @@ where } } +impl ScanBuilder { + /// Set the `reason` field (optional) + pub fn reason(mut self, value: impl Into>) -> Self { + self._fields.5 = value.into(); + self + } + /// Set the `reason` field to an Option value (optional) + pub fn maybe_reason(mut self, value: Option) -> Self { + self._fields.5 = value; + self + } +} + impl ScanBuilder where St: scan_state::State, @@ -613,7 +737,7 @@ where mut self, value: impl Into, ) -> ScanBuilder, S> { - self._fields.5 = Option::Some(value.into()); + self._fields.6 = Option::Some(value.into()); ScanBuilder { _state: PhantomData, _fields: self._fields, @@ -625,12 +749,12 @@ where impl ScanBuilder { /// Set the `sbomBlob` field (optional) pub fn sbom_blob(mut self, value: impl Into>>) -> Self { - self._fields.6 = value.into(); + self._fields.7 = value.into(); self } /// Set the `sbomBlob` field to an Option value (optional) pub fn maybe_sbom_blob(mut self, value: Option>) -> Self { - self._fields.6 = value; + self._fields.7 = value; self } } @@ -645,7 +769,7 @@ where mut self, value: impl Into, ) -> ScanBuilder, S> { - self._fields.7 = Option::Some(value.into()); + self._fields.8 = Option::Some(value.into()); ScanBuilder { _state: PhantomData, _fields: self._fields, @@ -664,7 +788,7 @@ where mut self, value: impl Into, ) -> ScanBuilder, S> { - self._fields.8 = Option::Some(value.into()); + self._fields.9 = Option::Some(value.into()); ScanBuilder { _state: PhantomData, _fields: self._fields, @@ -673,6 +797,19 @@ where } } +impl ScanBuilder { + /// Set the `status` field (optional) + pub fn status(mut self, value: impl Into>>) -> Self { + self._fields.10 = value.into(); + self + } + /// Set the `status` field to an Option value (optional) + pub fn maybe_status(mut self, value: Option>) -> Self { + self._fields.10 = value; + self + } +} + impl ScanBuilder where St: scan_state::State, @@ -680,7 +817,7 @@ where { /// Set the `total` field (required) pub fn total(mut self, value: impl Into) -> ScanBuilder, S> { - self._fields.9 = Option::Some(value.into()); + self._fields.11 = Option::Some(value.into()); ScanBuilder { _state: PhantomData, _fields: self._fields, @@ -699,7 +836,7 @@ where mut self, value: impl Into>, ) -> ScanBuilder, S> { - self._fields.10 = Option::Some(value.into()); + self._fields.12 = Option::Some(value.into()); ScanBuilder { _state: PhantomData, _fields: self._fields, @@ -711,12 +848,12 @@ where impl ScanBuilder { /// Set the `vulnReportBlob` field (optional) pub fn vuln_report_blob(mut self, value: impl Into>>) -> Self { - self._fields.11 = value.into(); + self._fields.13 = value.into(); self } /// Set the `vulnReportBlob` field to an Option value (optional) pub fn maybe_vuln_report_blob(mut self, value: Option>) -> Self { - self._fields.11 = value; + self._fields.13 = value; self } } @@ -743,13 +880,15 @@ where low: self._fields.2.unwrap(), manifest: self._fields.3.unwrap(), medium: self._fields.4.unwrap(), - repository: self._fields.5.unwrap(), - sbom_blob: self._fields.6, - scanned_at: self._fields.7.unwrap(), - scanner_version: self._fields.8.unwrap(), - total: self._fields.9.unwrap(), - user_did: self._fields.10.unwrap(), - vuln_report_blob: self._fields.11, + reason: self._fields.5, + repository: self._fields.6.unwrap(), + sbom_blob: self._fields.7, + scanned_at: self._fields.8.unwrap(), + scanner_version: self._fields.9.unwrap(), + status: self._fields.10, + total: self._fields.11.unwrap(), + user_did: self._fields.12.unwrap(), + vuln_report_blob: self._fields.13, extra_data: Default::default(), } } @@ -761,13 +900,15 @@ where low: self._fields.2.unwrap(), manifest: self._fields.3.unwrap(), medium: self._fields.4.unwrap(), - repository: self._fields.5.unwrap(), - sbom_blob: self._fields.6, - scanned_at: self._fields.7.unwrap(), - scanner_version: self._fields.8.unwrap(), - total: self._fields.9.unwrap(), - user_did: self._fields.10.unwrap(), - vuln_report_blob: self._fields.11, + reason: self._fields.5, + repository: self._fields.6.unwrap(), + sbom_blob: self._fields.7, + scanned_at: self._fields.8.unwrap(), + scanner_version: self._fields.9.unwrap(), + status: self._fields.10, + total: self._fields.11.unwrap(), + user_did: self._fields.12.unwrap(), + vuln_report_blob: self._fields.13, extra_data: Some(extra_data), } } @@ -848,6 +989,18 @@ fn lexicon_doc_io_atcr_hold_scan() -> LexiconDoc<'static> { ..Default::default() }), ); + map.insert( + SmolStr::new_static("reason"), + LexObjectProperty::String(LexString { + description: Some( + CowStr::new_static( + "Optional human-readable explanation for non-ok status (e.g. 'unscannable artifact type application/vnd.cncf.helm.config.v1+json').", + ), + ), + max_length: Some(256usize), + ..Default::default() + }), + ); map.insert( SmolStr::new_static("repository"), LexObjectProperty::String(LexString { @@ -886,6 +1039,18 @@ fn lexicon_doc_io_atcr_hold_scan() -> LexiconDoc<'static> { ..Default::default() }), ); + map.insert( + SmolStr::new_static("status"), + LexObjectProperty::String(LexString { + description: Some( + CowStr::new_static( + "Outcome of the scan attempt. 'ok' (or omitted, for back-compat) means the scanner produced an SBOM. 'failed' means the scanner ran but errored. 'skipped' means the scanner intentionally bypassed this artifact type (e.g. helm charts).", + ), + ), + max_length: Some(32usize), + ..Default::default() + }), + ); map.insert( SmolStr::new_static("total"), LexObjectProperty::Integer(LexInteger { diff --git a/crates/jacquard-api/src/io_atcr/manifest.rs b/crates/jacquard-api/src/io_atcr/manifest.rs index fb0bb4b7f..331c360c1 100644 --- a/crates/jacquard-api/src/io_atcr/manifest.rs +++ b/crates/jacquard-api/src/io_atcr/manifest.rs @@ -456,6 +456,18 @@ impl LexiconSchema for Platform { }); } } + if let Some(values) = &self.os_features { + for value in values { + #[allow(unused_comparisons)] + if ::len(value.as_ref()) > 64usize { + return Err(ConstraintError::MaxLength { + path: ValidationPath::from_field("os_features"), + max: 64usize, + actual: ::len(value.as_ref()), + }); + } + } + } if let Some(ref value) = self.os_version { #[allow(unused_comparisons)] if ::len(value.as_ref()) > 64usize { diff --git a/crates/jacquard-api/src/io_atcr/repo/page.rs b/crates/jacquard-api/src/io_atcr/repo/page.rs index 8806ea9c4..1d6dcb67e 100644 --- a/crates/jacquard-api/src/io_atcr/repo/page.rs +++ b/crates/jacquard-api/src/io_atcr/repo/page.rs @@ -50,6 +50,9 @@ pub struct Page { pub repository: S, ///Record last updated timestamp pub updated_at: Datetime, + ///Whether the description was manually edited by the user. When true, auto-population from manifest annotations is skipped on push. + #[serde(skip_serializing_if = "Option::is_none")] + pub user_edited: Option, #[serde(flatten, default, skip_serializing_if = "Option::is_none")] pub extra_data: Option>>, } @@ -240,6 +243,7 @@ pub struct PageBuilder { Option, Option, Option, + Option, ), _type: PhantomData S>, } @@ -263,7 +267,7 @@ impl PageBuilder { pub fn new() -> Self { PageBuilder { _state: PhantomData, - _fields: (None, None, None, None, None), + _fields: (None, None, None, None, None, None), _type: PhantomData, } } @@ -274,7 +278,7 @@ impl PageBuilder { pub fn builder() -> Self { PageBuilder { _state: PhantomData, - _fields: (None, None, None, None, None), + _fields: (None, None, None, None, None, None), _type: PhantomData, } } @@ -363,6 +367,19 @@ where } } +impl PageBuilder { + /// Set the `userEdited` field (optional) + pub fn user_edited(mut self, value: impl Into>) -> Self { + self._fields.5 = value.into(); + self + } + /// Set the `userEdited` field to an Option value (optional) + pub fn maybe_user_edited(mut self, value: Option) -> Self { + self._fields.5 = value; + self + } +} + impl PageBuilder where St: page_state::State, @@ -378,6 +395,7 @@ where description: self._fields.2, repository: self._fields.3.unwrap(), updated_at: self._fields.4.unwrap(), + user_edited: self._fields.5, extra_data: Default::default(), } } @@ -389,6 +407,7 @@ where description: self._fields.2, repository: self._fields.3.unwrap(), updated_at: self._fields.4.unwrap(), + user_edited: self._fields.5, extra_data: Some(extra_data), } } @@ -472,6 +491,12 @@ fn lexicon_doc_io_atcr_repo_page() -> LexiconDoc<'static> { ..Default::default() }), ); + map.insert( + SmolStr::new_static("userEdited"), + LexObjectProperty::Boolean(LexBoolean { + ..Default::default() + }), + ); map }, ..Default::default() diff --git a/crates/jacquard-api/src/io_atcr/sailor/profile.rs b/crates/jacquard-api/src/io_atcr/sailor/profile.rs index 8c8f3d960..7c4e6996f 100644 --- a/crates/jacquard-api/src/io_atcr/sailor/profile.rs +++ b/crates/jacquard-api/src/io_atcr/sailor/profile.rs @@ -45,6 +45,12 @@ pub struct Profile { ///Default hold DID for blob storage. If null, user has opted out of defaults. #[serde(skip_serializing_if = "Option::is_none")] pub default_hold: Option>, + ///Preferred client for pull commands (docker, podman, buildah, nerdctl, crane). 'none' shows the image reference only. Defaults to docker if empty. + #[serde(skip_serializing_if = "Option::is_none")] + pub oci_client: Option>, + ///Preferred registry domain for UI display. Must be one of the appview's configured registry domains. Empty means the primary (first configured) domain. + #[serde(skip_serializing_if = "Option::is_none")] + pub registry_domain: Option, ///Profile last updated timestamp #[serde(skip_serializing_if = "Option::is_none")] pub updated_at: Option, @@ -52,6 +58,101 @@ pub struct Profile { pub extra_data: Option>>, } +/// Preferred client for pull commands (docker, podman, buildah, nerdctl, crane). 'none' shows the image reference only. Defaults to docker if empty. + +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub enum ProfileOciClient { + Docker, + Podman, + Buildah, + Nerdctl, + Crane, + None, + Other(S), +} + +impl ProfileOciClient { + pub fn as_str(&self) -> &str { + match self { + Self::Docker => "docker", + Self::Podman => "podman", + Self::Buildah => "buildah", + Self::Nerdctl => "nerdctl", + Self::Crane => "crane", + Self::None => "none", + 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() { + "docker" => Self::Docker, + "podman" => Self::Podman, + "buildah" => Self::Buildah, + "nerdctl" => Self::Nerdctl, + "crane" => Self::Crane, + "none" => Self::None, + _ => Self::Other(s), + } + } +} + +impl core::fmt::Display for ProfileOciClient { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!(f, "{}", self.as_str()) + } +} + +impl AsRef for ProfileOciClient { + fn as_ref(&self) -> &str { + self.as_str() + } +} + +impl Serialize for ProfileOciClient { + 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 ProfileOciClient { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = S::deserialize(deserializer)?; + Ok(Self::from_value(s)) + } +} + +impl Default for ProfileOciClient { + fn default() -> Self { + Self::Other(Default::default()) + } +} + +impl jacquard_common::IntoStatic for ProfileOciClient +where + S: BosStr + jacquard_common::IntoStatic, + S::Output: BosStr, +{ + type Output = ProfileOciClient; + fn into_static(self) -> Self::Output { + match self { + ProfileOciClient::Docker => ProfileOciClient::Docker, + ProfileOciClient::Podman => ProfileOciClient::Podman, + ProfileOciClient::Buildah => ProfileOciClient::Buildah, + ProfileOciClient::Nerdctl => ProfileOciClient::Nerdctl, + ProfileOciClient::Crane => ProfileOciClient::Crane, + ProfileOciClient::None => ProfileOciClient::None, + ProfileOciClient::Other(v) => ProfileOciClient::Other(v.into_static()), + } + } +} + /// Typed wrapper for GetRecord response with this collection's record type. #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] @@ -107,6 +208,26 @@ impl LexiconSchema for Profile { lexicon_doc_io_atcr_sailor_profile() } fn validate(&self) -> Result<(), ConstraintError> { + if let Some(ref value) = self.oci_client { + #[allow(unused_comparisons)] + if ::len(value.as_ref()) > 32usize { + return Err(ConstraintError::MaxLength { + path: ValidationPath::from_field("oci_client"), + max: 32usize, + actual: ::len(value.as_ref()), + }); + } + } + if let Some(ref value) = self.registry_domain { + #[allow(unused_comparisons)] + if ::len(value.as_ref()) > 255usize { + return Err(ConstraintError::MaxLength { + path: ValidationPath::from_field("registry_domain"), + max: 255usize, + actual: ::len(value.as_ref()), + }); + } + } Ok(()) } } @@ -150,6 +271,8 @@ pub struct ProfileBuilder { Option, Option, Option>, + Option>, + Option, Option, ), _type: PhantomData S>, @@ -174,7 +297,7 @@ impl ProfileBuilder { pub fn new() -> Self { ProfileBuilder { _state: PhantomData, - _fields: (None, None, None, None), + _fields: (None, None, None, None, None, None), _type: PhantomData, } } @@ -185,7 +308,7 @@ impl ProfileBuilder { pub fn builder() -> Self { ProfileBuilder { _state: PhantomData, - _fields: (None, None, None, None), + _fields: (None, None, None, None, None, None), _type: PhantomData, } } @@ -236,15 +359,41 @@ impl ProfileBuilder { } } +impl ProfileBuilder { + /// Set the `ociClient` field (optional) + pub fn oci_client(mut self, value: impl Into>>) -> Self { + self._fields.3 = value.into(); + self + } + /// Set the `ociClient` field to an Option value (optional) + pub fn maybe_oci_client(mut self, value: Option>) -> Self { + self._fields.3 = value; + self + } +} + +impl ProfileBuilder { + /// Set the `registryDomain` field (optional) + pub fn registry_domain(mut self, value: impl Into>) -> Self { + self._fields.4 = value.into(); + self + } + /// Set the `registryDomain` field to an Option value (optional) + pub fn maybe_registry_domain(mut self, value: Option) -> Self { + self._fields.4 = value; + self + } +} + impl ProfileBuilder { /// Set the `updatedAt` field (optional) pub fn updated_at(mut self, value: impl Into>) -> Self { - self._fields.3 = value.into(); + self._fields.5 = value.into(); self } /// Set the `updatedAt` field to an Option value (optional) pub fn maybe_updated_at(mut self, value: Option) -> Self { - self._fields.3 = value; + self._fields.5 = value; self } } @@ -260,7 +409,9 @@ where auto_remove_untagged: self._fields.0, created_at: self._fields.1.unwrap(), default_hold: self._fields.2, - updated_at: self._fields.3, + oci_client: self._fields.3, + registry_domain: self._fields.4, + updated_at: self._fields.5, extra_data: Default::default(), } } @@ -270,7 +421,9 @@ where auto_remove_untagged: self._fields.0, created_at: self._fields.1.unwrap(), default_hold: self._fields.2, - updated_at: self._fields.3, + oci_client: self._fields.3, + registry_domain: self._fields.4, + updated_at: self._fields.5, extra_data: Some(extra_data), } } @@ -328,6 +481,30 @@ fn lexicon_doc_io_atcr_sailor_profile() -> LexiconDoc<'static> { ..Default::default() }), ); + map.insert( + SmolStr::new_static("ociClient"), + LexObjectProperty::String(LexString { + description: Some( + CowStr::new_static( + "Preferred client for pull commands (docker, podman, buildah, nerdctl, crane). 'none' shows the image reference only. Defaults to docker if empty.", + ), + ), + max_length: Some(32usize), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("registryDomain"), + LexObjectProperty::String(LexString { + description: Some( + CowStr::new_static( + "Preferred registry domain for UI display. Must be one of the appview's configured registry domains. Empty means the primary (first configured) domain.", + ), + ), + max_length: Some(255usize), + ..Default::default() + }), + ); map.insert( SmolStr::new_static("updatedAt"), LexObjectProperty::String(LexString { diff --git a/crates/jacquard-api/src/io_atcr/tag.rs b/crates/jacquard-api/src/io_atcr/tag.rs index c1bb07609..098f58465 100644 --- a/crates/jacquard-api/src/io_atcr/tag.rs +++ b/crates/jacquard-api/src/io_atcr/tag.rs @@ -43,6 +43,9 @@ pub struct Tag { ///DEPRECATED: Digest of the manifest (e.g., 'sha256:...'). Kept for backward compatibility with old records. New records should use 'manifest' field instead. #[serde(skip_serializing_if = "Option::is_none")] pub manifest_digest: Option, + ///OCI media type of the manifest (e.g., 'application/vnd.oci.image.manifest.v1+json' or 'application/vnd.oci.image.index.v1+json') + #[serde(skip_serializing_if = "Option::is_none")] + pub media_type: Option, ///Repository name (e.g., 'myapp'). Scoped to user's DID. pub repository: S, ///Tag name (e.g., 'latest', 'v1.0.0', '12-slim') @@ -119,6 +122,16 @@ impl LexiconSchema for Tag { }); } } + if let Some(ref value) = self.media_type { + #[allow(unused_comparisons)] + if ::len(value.as_ref()) > 255usize { + return Err(ConstraintError::MaxLength { + path: ValidationPath::from_field("media_type"), + max: 255usize, + actual: ::len(value.as_ref()), + }); + } + } { let value = &self.repository; #[allow(unused_comparisons)] @@ -197,6 +210,7 @@ pub struct TagBuilder { Option, Option, Option, + Option, Option, ), _type: PhantomData S>, @@ -221,7 +235,7 @@ impl TagBuilder { pub fn new() -> Self { TagBuilder { _state: PhantomData, - _fields: (None, None, None, None, None), + _fields: (None, None, None, None, None, None), _type: PhantomData, } } @@ -232,7 +246,7 @@ impl TagBuilder { pub fn builder() -> Self { TagBuilder { _state: PhantomData, - _fields: (None, None, None, None, None), + _fields: (None, None, None, None, None, None), _type: PhantomData, } } @@ -264,6 +278,19 @@ impl TagBuilder { } } +impl TagBuilder { + /// Set the `mediaType` field (optional) + pub fn media_type(mut self, value: impl Into>) -> Self { + self._fields.2 = value.into(); + self + } + /// Set the `mediaType` field to an Option value (optional) + pub fn maybe_media_type(mut self, value: Option) -> Self { + self._fields.2 = value; + self + } +} + impl TagBuilder where St: tag_state::State, @@ -274,7 +301,7 @@ where mut self, value: impl Into, ) -> TagBuilder, S> { - self._fields.2 = Option::Some(value.into()); + self._fields.3 = Option::Some(value.into()); TagBuilder { _state: PhantomData, _fields: self._fields, @@ -290,7 +317,7 @@ where { /// Set the `tag` field (required) pub fn tag(mut self, value: impl Into) -> TagBuilder, S> { - self._fields.3 = Option::Some(value.into()); + self._fields.4 = Option::Some(value.into()); TagBuilder { _state: PhantomData, _fields: self._fields, @@ -302,12 +329,12 @@ where impl TagBuilder { /// Set the `updatedAt` field (optional) pub fn updated_at(mut self, value: impl Into>) -> Self { - self._fields.4 = value.into(); + self._fields.5 = value.into(); self } /// Set the `updatedAt` field to an Option value (optional) pub fn maybe_updated_at(mut self, value: Option) -> Self { - self._fields.4 = value; + self._fields.5 = value; self } } @@ -323,9 +350,10 @@ where Tag { manifest: self._fields.0, manifest_digest: self._fields.1, - repository: self._fields.2.unwrap(), - tag: self._fields.3.unwrap(), - updated_at: self._fields.4, + media_type: self._fields.2, + repository: self._fields.3.unwrap(), + tag: self._fields.4.unwrap(), + updated_at: self._fields.5, extra_data: Default::default(), } } @@ -334,9 +362,10 @@ where Tag { manifest: self._fields.0, manifest_digest: self._fields.1, - repository: self._fields.2.unwrap(), - tag: self._fields.3.unwrap(), - updated_at: self._fields.4, + media_type: self._fields.2, + repository: self._fields.3.unwrap(), + tag: self._fields.4.unwrap(), + updated_at: self._fields.5, extra_data: Some(extra_data), } } @@ -395,6 +424,18 @@ fn lexicon_doc_io_atcr_tag() -> LexiconDoc<'static> { ..Default::default() }), ); + map.insert( + SmolStr::new_static("mediaType"), + LexObjectProperty::String(LexString { + description: Some( + CowStr::new_static( + "OCI media type of the manifest (e.g., 'application/vnd.oci.image.manifest.v1+json' or 'application/vnd.oci.image.index.v1+json')", + ), + ), + max_length: Some(255usize), + ..Default::default() + }), + ); map.insert( SmolStr::new_static("repository"), LexObjectProperty::String(LexString { diff --git a/crates/jacquard-api/src/io_sound/sequence.rs b/crates/jacquard-api/src/io_sound/sequence.rs index 232562472..c9aa1987e 100644 --- a/crates/jacquard-api/src/io_sound/sequence.rs +++ b/crates/jacquard-api/src/io_sound/sequence.rs @@ -174,6 +174,32 @@ impl LexiconSchema for Sequence { } } } + if let Some(values) = &self.tags { + for value in values { + #[allow(unused_comparisons)] + if ::len(value.as_ref()) > 1280usize { + return Err(ConstraintError::MaxLength { + path: ValidationPath::from_field("tags"), + max: 1280usize, + actual: ::len(value.as_ref()), + }); + } + } + } + if let Some(values) = &self.tags { + for value in values { + { + let count = UnicodeSegmentation::graphemes(value.as_ref(), true).count(); + if count > 128usize { + return Err(ConstraintError::MaxGraphemes { + path: ValidationPath::from_field("tags"), + max: 128usize, + actual: count, + }); + } + } + } + } Ok(()) } } diff --git a/crates/jacquard-api/src/media_ionosphere.rs b/crates/jacquard-api/src/media_ionosphere.rs index 6824e0d47..a46fa1256 100644 --- a/crates/jacquard-api/src/media_ionosphere.rs +++ b/crates/jacquard-api/src/media_ionosphere.rs @@ -404,6 +404,16 @@ impl LexiconSchema for Track { }); } } + for value in &self.artists { + #[allow(unused_comparisons)] + if ::len(value.as_ref()) > 256usize { + return Err(ConstraintError::MaxLength { + path: ValidationPath::from_field("artists"), + max: 256usize, + actual: ::len(value.as_ref()), + }); + } + } { let value = &self.title; #[allow(unused_comparisons)] diff --git a/crates/jacquard-api/src/media_ionosphere/group.rs b/crates/jacquard-api/src/media_ionosphere/group.rs index 7c6062b14..611f08598 100644 --- a/crates/jacquard-api/src/media_ionosphere/group.rs +++ b/crates/jacquard-api/src/media_ionosphere/group.rs @@ -261,6 +261,18 @@ impl LexiconSchema for Group { }); } } + if let Some(values) = &self.keywords { + for value in values { + #[allow(unused_comparisons)] + if ::len(value.as_ref()) > 128usize { + return Err(ConstraintError::MaxLength { + path: ValidationPath::from_field("keywords"), + max: 128usize, + actual: ::len(value.as_ref()), + }); + } + } + } if let Some(ref value) = self.kind { #[allow(unused_comparisons)] if ::len(value.as_ref()) > 128usize { diff --git a/crates/jacquard-api/src/media_ionosphere/programme.rs b/crates/jacquard-api/src/media_ionosphere/programme.rs index 3e89f71c3..24e9371d9 100644 --- a/crates/jacquard-api/src/media_ionosphere/programme.rs +++ b/crates/jacquard-api/src/media_ionosphere/programme.rs @@ -177,6 +177,18 @@ impl LexiconSchema for Programme { }); } } + if let Some(values) = &self.keywords { + for value in values { + #[allow(unused_comparisons)] + if ::len(value.as_ref()) > 128usize { + return Err(ConstraintError::MaxLength { + path: ValidationPath::from_field("keywords"), + max: 128usize, + actual: ::len(value.as_ref()), + }); + } + } + } { let value = &self.name; { diff --git a/crates/jacquard-api/src/media_ionosphere/service.rs b/crates/jacquard-api/src/media_ionosphere/service.rs index a681161d5..4da89765f 100644 --- a/crates/jacquard-api/src/media_ionosphere/service.rs +++ b/crates/jacquard-api/src/media_ionosphere/service.rs @@ -164,6 +164,18 @@ impl LexiconSchema for Service { }); } } + if let Some(values) = &self.keywords { + for value in values { + #[allow(unused_comparisons)] + if ::len(value.as_ref()) > 128usize { + return Err(ConstraintError::MaxLength { + path: ValidationPath::from_field("keywords"), + max: 128usize, + actual: ::len(value.as_ref()), + }); + } + } + } { let value = &self.name; { diff --git a/crates/jacquard-api/src/net_alternativeproto/submission.rs b/crates/jacquard-api/src/net_alternativeproto/submission.rs index d02e9cbbb..cf6dad3e5 100644 --- a/crates/jacquard-api/src/net_alternativeproto/submission.rs +++ b/crates/jacquard-api/src/net_alternativeproto/submission.rs @@ -205,6 +205,18 @@ impl LexiconSchema for Submission { lexicon_doc_net_alternativeproto_submission() } fn validate(&self) -> Result<(), ConstraintError> { + if let Some(values) = &self.alternative_to { + for value in values { + #[allow(unused_comparisons)] + if ::len(value.as_ref()) > 100usize { + return Err(ConstraintError::MaxLength { + path: ValidationPath::from_field("alternative_to"), + max: 100usize, + actual: ::len(value.as_ref()), + }); + } + } + } { let value = &self.description; #[allow(unused_comparisons)] @@ -276,6 +288,18 @@ impl LexiconSchema for Submission { }); } } + if let Some(values) = &self.tags { + for value in values { + #[allow(unused_comparisons)] + if ::len(value.as_ref()) > 50usize { + return Err(ConstraintError::MaxLength { + path: ValidationPath::from_field("tags"), + max: 50usize, + actual: ::len(value.as_ref()), + }); + } + } + } Ok(()) } } diff --git a/crates/jacquard-api/src/net_anisota.rs b/crates/jacquard-api/src/net_anisota.rs index 1fb305cf6..7ad028857 100644 --- a/crates/jacquard-api/src/net_anisota.rs +++ b/crates/jacquard-api/src/net_anisota.rs @@ -8,9 +8,11 @@ pub mod auth_full_app; pub mod beta; pub mod chronicle; pub mod feed; +pub mod fieldwork; pub mod graph; pub mod harvest; pub mod lab; pub mod observatory; pub mod player; pub mod settings; +pub mod spell; diff --git a/crates/jacquard-api/src/net_anisota/chronicle.rs b/crates/jacquard-api/src/net_anisota/chronicle.rs index 1fcb26693..a95b4aca6 100644 --- a/crates/jacquard-api/src/net_anisota/chronicle.rs +++ b/crates/jacquard-api/src/net_anisota/chronicle.rs @@ -7,7 +7,10 @@ pub mod achievement; pub mod collection; pub mod expedition; +pub mod fieldwork; pub mod inventory; pub mod level; pub mod log; +pub mod milestone; pub mod progress; +pub mod walk; diff --git a/crates/jacquard-api/src/net_anisota/chronicle/achievement.rs b/crates/jacquard-api/src/net_anisota/chronicle/achievement.rs index 6db591389..72d63284c 100644 --- a/crates/jacquard-api/src/net_anisota/chronicle/achievement.rs +++ b/crates/jacquard-api/src/net_anisota/chronicle/achievement.rs @@ -79,7 +79,7 @@ pub struct ChronicleSignature { pub extra_data: Option>>, } -/// Consolidated achievement record. Replaces 30 beta achievement lexicons. rkey is the achievement ID (e.g. followers2500, level50). Created once with createRecord when achievement is unlocked. Immutable. +/// DEPRECATED - superseded by net.anisota.chronicle.milestone. No new records are written to this collection; the schema is kept because earlier records still exist on users' PDSes and remain readable. rkey is the achievement ID (e.g. followers2500, level50). Immutable. #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] #[serde( @@ -444,7 +444,7 @@ fn lexicon_doc_net_anisota_chronicle_achievement() -> LexiconDoc<'static> { LexUserType::Record(LexRecord { description: Some( CowStr::new_static( - "Consolidated achievement record. Replaces 30 beta achievement lexicons. rkey is the achievement ID (e.g. followers2500, level50). Created once with createRecord when achievement is unlocked. Immutable.", + "DEPRECATED - superseded by net.anisota.chronicle.milestone. No new records are written to this collection; the schema is kept because earlier records still exist on users' PDSes and remain readable. rkey is the achievement ID (e.g. followers2500, level50). Immutable.", ), ), key: Some(CowStr::new_static("any")), diff --git a/crates/jacquard-api/src/net_anisota/chronicle/fieldwork.rs b/crates/jacquard-api/src/net_anisota/chronicle/fieldwork.rs new file mode 100644 index 000000000..72364dcc7 --- /dev/null +++ b/crates/jacquard-api/src/net_anisota/chronicle/fieldwork.rs @@ -0,0 +1,1206 @@ +// @generated by jacquard-lexicon. DO NOT EDIT. +// +// Lexicon: net.anisota.chronicle.fieldwork +// +// 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; + +use crate::net_anisota::chronicle::fieldwork; +#[allow(unused_imports)] +use jacquard_lexicon::validation::{ConstraintError, ValidationPath}; +use serde::{Deserialize, Serialize}; +/// ES256 cryptographic signature proving record authenticity. The signature itself proves legitimacy - no separate verification lexicons needed. + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct ChronicleSignature { + ///Signing algorithm (ES256) + pub alg: S, + ///Key identifier for the signing key + pub kid: S, + ///Unique random nonce to prevent replay + pub nonce: S, + ///Base64-encoded ES256 signature + pub sig: S, + ///When the record was signed + pub signed_at: Datetime, + ///Signature schema version + pub version: i64, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +/// Signed quest completion record. rkey is the quest ID (e.g. 'first-post', 'make-camp'). Created once with createRecord when the quest is completed. Immutable. + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + rename = "net.anisota.chronicle.fieldwork", + tag = "$type", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct Fieldwork { + ///When the quest was completed + pub completed_at: Datetime, + #[serde(skip_serializing_if = "Option::is_none")] + pub context: Option>, + ///When the quest record was created + pub created_at: Datetime, + ///Description of what was accomplished + #[serde(skip_serializing_if = "Option::is_none")] + pub description: Option, + ///Display title of the quest + #[serde(skip_serializing_if = "Option::is_none")] + pub name: Option, + ///Unique identifier for the quest (e.g. 'first-post'). Matches the record's rkey. + pub quest_id: S, + ///Whether the quest was completed retroactively from existing activity rather than live + #[serde(skip_serializing_if = "Option::is_none")] + pub retroactive: Option, + pub signature: fieldwork::ChronicleSignature, + ///Quest track this quest belongs to (e.g. 'field-basics', 'observatory', 'expedition', 'craft') + pub track: S, + ///XP awarded for completing this quest + pub xp_awarded: i64, + #[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 FieldworkGetRecordOutput { + #[serde(skip_serializing_if = "Option::is_none")] + pub cid: Option>, + pub uri: AtUri, + pub value: Fieldwork, +} + +/// Contextual data at the time of quest completion + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic, Default)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct QuestContext { + ///App mode ('story' or 'open') when the quest was completed + #[serde(skip_serializing_if = "Option::is_none")] + pub app_mode: Option, + ///Player level when the quest was completed + #[serde(skip_serializing_if = "Option::is_none")] + pub level: Option, + ///Total XP when the quest was completed + #[serde(skip_serializing_if = "Option::is_none")] + pub total_xp: Option, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +impl Fieldwork { + pub fn uri(uri: S) -> Result, UriError> { + RecordUri::try_from_uri(AtUri::new(uri)?) + } +} + +impl LexiconSchema for ChronicleSignature { + fn nsid() -> &'static str { + "net.anisota.chronicle.fieldwork" + } + fn def_name() -> &'static str { + "chronicleSignature" + } + fn lexicon_doc() -> LexiconDoc<'static> { + lexicon_doc_net_anisota_chronicle_fieldwork() + } + fn validate(&self) -> Result<(), ConstraintError> { + Ok(()) + } +} + +/// Marker type for deserializing records from this collection. + +#[derive(Debug, Serialize, Deserialize)] +pub struct FieldworkRecord; +impl XrpcResp for FieldworkRecord { + const NSID: &'static str = "net.anisota.chronicle.fieldwork"; + const ENCODING: &'static str = "application/json"; + type Output = FieldworkGetRecordOutput; + type Err = RecordError; +} + +impl From> for Fieldwork { + fn from(output: FieldworkGetRecordOutput) -> Self { + output.value + } +} + +impl Collection for Fieldwork { + const NSID: &'static str = "net.anisota.chronicle.fieldwork"; + type Record = FieldworkRecord; +} + +impl Collection for FieldworkRecord { + const NSID: &'static str = "net.anisota.chronicle.fieldwork"; + type Record = FieldworkRecord; +} + +impl LexiconSchema for Fieldwork { + fn nsid() -> &'static str { + "net.anisota.chronicle.fieldwork" + } + fn def_name() -> &'static str { + "main" + } + fn lexicon_doc() -> LexiconDoc<'static> { + lexicon_doc_net_anisota_chronicle_fieldwork() + } + fn validate(&self) -> Result<(), ConstraintError> { + if let Some(ref value) = self.description { + #[allow(unused_comparisons)] + if ::len(value.as_ref()) > 500usize { + return Err(ConstraintError::MaxLength { + path: ValidationPath::from_field("description"), + max: 500usize, + actual: ::len(value.as_ref()), + }); + } + } + if let Some(ref value) = self.name { + #[allow(unused_comparisons)] + if ::len(value.as_ref()) > 100usize { + return Err(ConstraintError::MaxLength { + path: ValidationPath::from_field("name"), + max: 100usize, + actual: ::len(value.as_ref()), + }); + } + } + { + let value = &self.quest_id; + #[allow(unused_comparisons)] + if ::len(value.as_ref()) > 100usize { + return Err(ConstraintError::MaxLength { + path: ValidationPath::from_field("quest_id"), + max: 100usize, + actual: ::len(value.as_ref()), + }); + } + } + { + let value = &self.track; + #[allow(unused_comparisons)] + if ::len(value.as_ref()) > 50usize { + return Err(ConstraintError::MaxLength { + path: ValidationPath::from_field("track"), + max: 50usize, + actual: ::len(value.as_ref()), + }); + } + } + { + let value = &self.xp_awarded; + if *value < 0i64 { + return Err(ConstraintError::Minimum { + path: ValidationPath::from_field("xp_awarded"), + min: 0i64, + actual: *value, + }); + } + } + Ok(()) + } +} + +impl LexiconSchema for QuestContext { + fn nsid() -> &'static str { + "net.anisota.chronicle.fieldwork" + } + fn def_name() -> &'static str { + "questContext" + } + fn lexicon_doc() -> LexiconDoc<'static> { + lexicon_doc_net_anisota_chronicle_fieldwork() + } + fn validate(&self) -> Result<(), ConstraintError> { + if let Some(ref value) = self.level { + if *value < 1i64 { + return Err(ConstraintError::Minimum { + path: ValidationPath::from_field("level"), + min: 1i64, + actual: *value, + }); + } + } + if let Some(ref value) = self.total_xp { + if *value < 0i64 { + return Err(ConstraintError::Minimum { + path: ValidationPath::from_field("total_xp"), + min: 0i64, + actual: *value, + }); + } + } + Ok(()) + } +} + +pub mod chronicle_signature_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 Alg; + type Kid; + type Nonce; + type Sig; + type SignedAt; + type Version; + } + /// Empty state - all required fields are unset + pub struct Empty(()); + impl sealed::Sealed for Empty {} + impl State for Empty { + type Alg = Unset; + type Kid = Unset; + type Nonce = Unset; + type Sig = Unset; + type SignedAt = Unset; + type Version = Unset; + } + ///State transition - sets the `alg` field to Set + pub struct SetAlg(PhantomData St>); + impl sealed::Sealed for SetAlg {} + impl State for SetAlg { + type Alg = Set; + type Kid = St::Kid; + type Nonce = St::Nonce; + type Sig = St::Sig; + type SignedAt = St::SignedAt; + type Version = St::Version; + } + ///State transition - sets the `kid` field to Set + pub struct SetKid(PhantomData St>); + impl sealed::Sealed for SetKid {} + impl State for SetKid { + type Alg = St::Alg; + type Kid = Set; + type Nonce = St::Nonce; + type Sig = St::Sig; + type SignedAt = St::SignedAt; + type Version = St::Version; + } + ///State transition - sets the `nonce` field to Set + pub struct SetNonce(PhantomData St>); + impl sealed::Sealed for SetNonce {} + impl State for SetNonce { + type Alg = St::Alg; + type Kid = St::Kid; + type Nonce = Set; + type Sig = St::Sig; + type SignedAt = St::SignedAt; + type Version = St::Version; + } + ///State transition - sets the `sig` field to Set + pub struct SetSig(PhantomData St>); + impl sealed::Sealed for SetSig {} + impl State for SetSig { + type Alg = St::Alg; + type Kid = St::Kid; + type Nonce = St::Nonce; + type Sig = Set; + type SignedAt = St::SignedAt; + type Version = St::Version; + } + ///State transition - sets the `signed_at` field to Set + pub struct SetSignedAt(PhantomData St>); + impl sealed::Sealed for SetSignedAt {} + impl State for SetSignedAt { + type Alg = St::Alg; + type Kid = St::Kid; + type Nonce = St::Nonce; + type Sig = St::Sig; + type SignedAt = Set; + type Version = St::Version; + } + ///State transition - sets the `version` field to Set + pub struct SetVersion(PhantomData St>); + impl sealed::Sealed for SetVersion {} + impl State for SetVersion { + type Alg = St::Alg; + type Kid = St::Kid; + type Nonce = St::Nonce; + type Sig = St::Sig; + type SignedAt = St::SignedAt; + type Version = Set; + } + /// Marker types for field names + #[allow(non_camel_case_types)] + pub mod members { + ///Marker type for the `alg` field + pub struct alg(()); + ///Marker type for the `kid` field + pub struct kid(()); + ///Marker type for the `nonce` field + pub struct nonce(()); + ///Marker type for the `sig` field + pub struct sig(()); + ///Marker type for the `signed_at` field + pub struct signed_at(()); + ///Marker type for the `version` field + pub struct version(()); + } +} + +/// Builder for constructing an instance of this type. +pub struct ChronicleSignatureBuilder { + _state: PhantomData St>, + _fields: ( + Option, + Option, + Option, + Option, + Option, + Option, + ), + _type: PhantomData S>, +} + +impl ChronicleSignature { + /// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed + pub fn new() -> ChronicleSignatureBuilder { + ChronicleSignatureBuilder::new() + } +} + +impl ChronicleSignature { + /// Create a new builder for this type + pub fn builder() -> ChronicleSignatureBuilder { + ChronicleSignatureBuilder::builder() + } +} + +impl ChronicleSignatureBuilder { + /// Create a new builder with all fields unset, using the default string type, if needed + pub fn new() -> Self { + ChronicleSignatureBuilder { + _state: PhantomData, + _fields: (None, None, None, None, None, None), + _type: PhantomData, + } + } +} + +impl ChronicleSignatureBuilder { + /// Create a new builder with all fields unset + pub fn builder() -> Self { + ChronicleSignatureBuilder { + _state: PhantomData, + _fields: (None, None, None, None, None, None), + _type: PhantomData, + } + } +} + +impl ChronicleSignatureBuilder +where + St: chronicle_signature_state::State, + St::Alg: chronicle_signature_state::IsUnset, +{ + /// Set the `alg` field (required) + pub fn alg( + mut self, + value: impl Into, + ) -> ChronicleSignatureBuilder, S> { + self._fields.0 = Option::Some(value.into()); + ChronicleSignatureBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl ChronicleSignatureBuilder +where + St: chronicle_signature_state::State, + St::Kid: chronicle_signature_state::IsUnset, +{ + /// Set the `kid` field (required) + pub fn kid( + mut self, + value: impl Into, + ) -> ChronicleSignatureBuilder, S> { + self._fields.1 = Option::Some(value.into()); + ChronicleSignatureBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl ChronicleSignatureBuilder +where + St: chronicle_signature_state::State, + St::Nonce: chronicle_signature_state::IsUnset, +{ + /// Set the `nonce` field (required) + pub fn nonce( + mut self, + value: impl Into, + ) -> ChronicleSignatureBuilder, S> { + self._fields.2 = Option::Some(value.into()); + ChronicleSignatureBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl ChronicleSignatureBuilder +where + St: chronicle_signature_state::State, + St::Sig: chronicle_signature_state::IsUnset, +{ + /// Set the `sig` field (required) + pub fn sig( + mut self, + value: impl Into, + ) -> ChronicleSignatureBuilder, S> { + self._fields.3 = Option::Some(value.into()); + ChronicleSignatureBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl ChronicleSignatureBuilder +where + St: chronicle_signature_state::State, + St::SignedAt: chronicle_signature_state::IsUnset, +{ + /// Set the `signedAt` field (required) + pub fn signed_at( + mut self, + value: impl Into, + ) -> ChronicleSignatureBuilder, S> { + self._fields.4 = Option::Some(value.into()); + ChronicleSignatureBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl ChronicleSignatureBuilder +where + St: chronicle_signature_state::State, + St::Version: chronicle_signature_state::IsUnset, +{ + /// Set the `version` field (required) + pub fn version( + mut self, + value: impl Into, + ) -> ChronicleSignatureBuilder, S> { + self._fields.5 = Option::Some(value.into()); + ChronicleSignatureBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl ChronicleSignatureBuilder +where + St: chronicle_signature_state::State, + St::Alg: chronicle_signature_state::IsSet, + St::Kid: chronicle_signature_state::IsSet, + St::Nonce: chronicle_signature_state::IsSet, + St::Sig: chronicle_signature_state::IsSet, + St::SignedAt: chronicle_signature_state::IsSet, + St::Version: chronicle_signature_state::IsSet, +{ + /// Build the final struct. + pub fn build(self) -> ChronicleSignature { + ChronicleSignature { + alg: self._fields.0.unwrap(), + kid: self._fields.1.unwrap(), + nonce: self._fields.2.unwrap(), + sig: self._fields.3.unwrap(), + signed_at: self._fields.4.unwrap(), + version: self._fields.5.unwrap(), + extra_data: Default::default(), + } + } + /// Build the final struct with custom extra_data. + pub fn build_with_data(self, extra_data: BTreeMap>) -> ChronicleSignature { + ChronicleSignature { + alg: self._fields.0.unwrap(), + kid: self._fields.1.unwrap(), + nonce: self._fields.2.unwrap(), + sig: self._fields.3.unwrap(), + signed_at: self._fields.4.unwrap(), + version: self._fields.5.unwrap(), + extra_data: Some(extra_data), + } + } +} + +fn lexicon_doc_net_anisota_chronicle_fieldwork() -> 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("net.anisota.chronicle.fieldwork"), + defs: { + let mut map = BTreeMap::new(); + map.insert( + SmolStr::new_static("chronicleSignature"), + LexUserType::Object(LexObject { + description: Some( + CowStr::new_static( + "ES256 cryptographic signature proving record authenticity. The signature itself proves legitimacy - no separate verification lexicons needed.", + ), + ), + required: Some( + vec![ + SmolStr::new_static("sig"), SmolStr::new_static("alg"), + SmolStr::new_static("kid"), SmolStr::new_static("signedAt"), + SmolStr::new_static("nonce"), SmolStr::new_static("version") + ], + ), + properties: { + #[allow(unused_mut)] + let mut map = BTreeMap::new(); + map.insert( + SmolStr::new_static("alg"), + LexObjectProperty::String(LexString { + description: Some( + CowStr::new_static("Signing algorithm (ES256)"), + ), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("kid"), + LexObjectProperty::String(LexString { + description: Some( + CowStr::new_static("Key identifier for the signing key"), + ), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("nonce"), + LexObjectProperty::String(LexString { + description: Some( + CowStr::new_static("Unique random nonce to prevent replay"), + ), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("sig"), + LexObjectProperty::String(LexString { + description: Some( + CowStr::new_static("Base64-encoded ES256 signature"), + ), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("signedAt"), + LexObjectProperty::String(LexString { + description: Some( + CowStr::new_static("When the record was signed"), + ), + format: Some(LexStringFormat::Datetime), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("version"), + LexObjectProperty::Integer(LexInteger { + ..Default::default() + }), + ); + map + }, + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("main"), + LexUserType::Record(LexRecord { + description: Some( + CowStr::new_static( + "Signed quest completion record. rkey is the quest ID (e.g. 'first-post', 'make-camp'). Created once with createRecord when the quest is completed. Immutable.", + ), + ), + key: Some(CowStr::new_static("any")), + record: LexRecordRecord::Object(LexObject { + required: Some( + vec![ + SmolStr::new_static("questId"), + SmolStr::new_static("track"), + SmolStr::new_static("xpAwarded"), + SmolStr::new_static("completedAt"), + SmolStr::new_static("signature"), + SmolStr::new_static("createdAt") + ], + ), + properties: { + #[allow(unused_mut)] + let mut map = BTreeMap::new(); + map.insert( + SmolStr::new_static("completedAt"), + LexObjectProperty::String(LexString { + description: Some( + CowStr::new_static("When the quest was completed"), + ), + format: Some(LexStringFormat::Datetime), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("context"), + LexObjectProperty::Ref(LexRef { + r#ref: CowStr::new_static("#questContext"), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("createdAt"), + LexObjectProperty::String(LexString { + description: Some( + CowStr::new_static("When the quest record was created"), + ), + format: Some(LexStringFormat::Datetime), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("description"), + LexObjectProperty::String(LexString { + description: Some( + CowStr::new_static("Description of what was accomplished"), + ), + max_length: Some(500usize), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("name"), + LexObjectProperty::String(LexString { + description: Some( + CowStr::new_static("Display title of the quest"), + ), + max_length: Some(100usize), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("questId"), + LexObjectProperty::String(LexString { + description: Some( + CowStr::new_static( + "Unique identifier for the quest (e.g. 'first-post'). Matches the record's rkey.", + ), + ), + max_length: Some(100usize), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("retroactive"), + LexObjectProperty::Boolean(LexBoolean { + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("signature"), + LexObjectProperty::Ref(LexRef { + r#ref: CowStr::new_static("#chronicleSignature"), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("track"), + LexObjectProperty::String(LexString { + description: Some( + CowStr::new_static( + "Quest track this quest belongs to (e.g. 'field-basics', 'observatory', 'expedition', 'craft')", + ), + ), + max_length: Some(50usize), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("xpAwarded"), + LexObjectProperty::Integer(LexInteger { + minimum: Some(0i64), + ..Default::default() + }), + ); + map + }, + ..Default::default() + }), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("questContext"), + LexUserType::Object(LexObject { + description: Some(CowStr::new_static( + "Contextual data at the time of quest completion", + )), + properties: { + #[allow(unused_mut)] + let mut map = BTreeMap::new(); + map.insert( + SmolStr::new_static("appMode"), + LexObjectProperty::String(LexString { + description: Some(CowStr::new_static( + "App mode ('story' or 'open') when the quest was completed", + )), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("level"), + LexObjectProperty::Integer(LexInteger { + minimum: Some(1i64), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("totalXP"), + LexObjectProperty::Integer(LexInteger { + minimum: Some(0i64), + ..Default::default() + }), + ); + map + }, + ..Default::default() + }), + ); + map + }, + ..Default::default() + } +} + +pub mod fieldwork_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 CompletedAt; + type CreatedAt; + type QuestId; + type Signature; + type Track; + type XpAwarded; + } + /// Empty state - all required fields are unset + pub struct Empty(()); + impl sealed::Sealed for Empty {} + impl State for Empty { + type CompletedAt = Unset; + type CreatedAt = Unset; + type QuestId = Unset; + type Signature = Unset; + type Track = Unset; + type XpAwarded = Unset; + } + ///State transition - sets the `completed_at` field to Set + pub struct SetCompletedAt(PhantomData St>); + impl sealed::Sealed for SetCompletedAt {} + impl State for SetCompletedAt { + type CompletedAt = Set; + type CreatedAt = St::CreatedAt; + type QuestId = St::QuestId; + type Signature = St::Signature; + type Track = St::Track; + type XpAwarded = St::XpAwarded; + } + ///State transition - sets the `created_at` field to Set + pub struct SetCreatedAt(PhantomData St>); + impl sealed::Sealed for SetCreatedAt {} + impl State for SetCreatedAt { + type CompletedAt = St::CompletedAt; + type CreatedAt = Set; + type QuestId = St::QuestId; + type Signature = St::Signature; + type Track = St::Track; + type XpAwarded = St::XpAwarded; + } + ///State transition - sets the `quest_id` field to Set + pub struct SetQuestId(PhantomData St>); + impl sealed::Sealed for SetQuestId {} + impl State for SetQuestId { + type CompletedAt = St::CompletedAt; + type CreatedAt = St::CreatedAt; + type QuestId = Set; + type Signature = St::Signature; + type Track = St::Track; + type XpAwarded = St::XpAwarded; + } + ///State transition - sets the `signature` field to Set + pub struct SetSignature(PhantomData St>); + impl sealed::Sealed for SetSignature {} + impl State for SetSignature { + type CompletedAt = St::CompletedAt; + type CreatedAt = St::CreatedAt; + type QuestId = St::QuestId; + type Signature = Set; + type Track = St::Track; + type XpAwarded = St::XpAwarded; + } + ///State transition - sets the `track` field to Set + pub struct SetTrack(PhantomData St>); + impl sealed::Sealed for SetTrack {} + impl State for SetTrack { + type CompletedAt = St::CompletedAt; + type CreatedAt = St::CreatedAt; + type QuestId = St::QuestId; + type Signature = St::Signature; + type Track = Set; + type XpAwarded = St::XpAwarded; + } + ///State transition - sets the `xp_awarded` field to Set + pub struct SetXpAwarded(PhantomData St>); + impl sealed::Sealed for SetXpAwarded {} + impl State for SetXpAwarded { + type CompletedAt = St::CompletedAt; + type CreatedAt = St::CreatedAt; + type QuestId = St::QuestId; + type Signature = St::Signature; + type Track = St::Track; + type XpAwarded = Set; + } + /// Marker types for field names + #[allow(non_camel_case_types)] + pub mod members { + ///Marker type for the `completed_at` field + pub struct completed_at(()); + ///Marker type for the `created_at` field + pub struct created_at(()); + ///Marker type for the `quest_id` field + pub struct quest_id(()); + ///Marker type for the `signature` field + pub struct signature(()); + ///Marker type for the `track` field + pub struct track(()); + ///Marker type for the `xp_awarded` field + pub struct xp_awarded(()); + } +} + +/// Builder for constructing an instance of this type. +pub struct FieldworkBuilder { + _state: PhantomData St>, + _fields: ( + Option, + Option>, + Option, + Option, + Option, + Option, + Option, + Option>, + Option, + Option, + ), + _type: PhantomData S>, +} + +impl Fieldwork { + /// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed + pub fn new() -> FieldworkBuilder { + FieldworkBuilder::new() + } +} + +impl Fieldwork { + /// Create a new builder for this type + pub fn builder() -> FieldworkBuilder { + FieldworkBuilder::builder() + } +} + +impl FieldworkBuilder { + /// Create a new builder with all fields unset, using the default string type, if needed + pub fn new() -> Self { + FieldworkBuilder { + _state: PhantomData, + _fields: (None, None, None, None, None, None, None, None, None, None), + _type: PhantomData, + } + } +} + +impl FieldworkBuilder { + /// Create a new builder with all fields unset + pub fn builder() -> Self { + FieldworkBuilder { + _state: PhantomData, + _fields: (None, None, None, None, None, None, None, None, None, None), + _type: PhantomData, + } + } +} + +impl FieldworkBuilder +where + St: fieldwork_state::State, + St::CompletedAt: fieldwork_state::IsUnset, +{ + /// Set the `completedAt` field (required) + pub fn completed_at( + mut self, + value: impl Into, + ) -> FieldworkBuilder, S> { + self._fields.0 = Option::Some(value.into()); + FieldworkBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl FieldworkBuilder { + /// Set the `context` field (optional) + pub fn context(mut self, value: impl Into>>) -> Self { + self._fields.1 = value.into(); + self + } + /// Set the `context` field to an Option value (optional) + pub fn maybe_context(mut self, value: Option>) -> Self { + self._fields.1 = value; + self + } +} + +impl FieldworkBuilder +where + St: fieldwork_state::State, + St::CreatedAt: fieldwork_state::IsUnset, +{ + /// Set the `createdAt` field (required) + pub fn created_at( + mut self, + value: impl Into, + ) -> FieldworkBuilder, S> { + self._fields.2 = Option::Some(value.into()); + FieldworkBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl FieldworkBuilder { + /// Set the `description` field (optional) + pub fn description(mut self, value: impl Into>) -> Self { + self._fields.3 = value.into(); + self + } + /// Set the `description` field to an Option value (optional) + pub fn maybe_description(mut self, value: Option) -> Self { + self._fields.3 = value; + self + } +} + +impl FieldworkBuilder { + /// Set the `name` field (optional) + pub fn name(mut self, value: impl Into>) -> Self { + self._fields.4 = value.into(); + self + } + /// Set the `name` field to an Option value (optional) + pub fn maybe_name(mut self, value: Option) -> Self { + self._fields.4 = value; + self + } +} + +impl FieldworkBuilder +where + St: fieldwork_state::State, + St::QuestId: fieldwork_state::IsUnset, +{ + /// Set the `questId` field (required) + pub fn quest_id( + mut self, + value: impl Into, + ) -> FieldworkBuilder, S> { + self._fields.5 = Option::Some(value.into()); + FieldworkBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl FieldworkBuilder { + /// Set the `retroactive` field (optional) + pub fn retroactive(mut self, value: impl Into>) -> Self { + self._fields.6 = value.into(); + self + } + /// Set the `retroactive` field to an Option value (optional) + pub fn maybe_retroactive(mut self, value: Option) -> Self { + self._fields.6 = value; + self + } +} + +impl FieldworkBuilder +where + St: fieldwork_state::State, + St::Signature: fieldwork_state::IsUnset, +{ + /// Set the `signature` field (required) + pub fn signature( + mut self, + value: impl Into>, + ) -> FieldworkBuilder, S> { + self._fields.7 = Option::Some(value.into()); + FieldworkBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl FieldworkBuilder +where + St: fieldwork_state::State, + St::Track: fieldwork_state::IsUnset, +{ + /// Set the `track` field (required) + pub fn track( + mut self, + value: impl Into, + ) -> FieldworkBuilder, S> { + self._fields.8 = Option::Some(value.into()); + FieldworkBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl FieldworkBuilder +where + St: fieldwork_state::State, + St::XpAwarded: fieldwork_state::IsUnset, +{ + /// Set the `xpAwarded` field (required) + pub fn xp_awarded( + mut self, + value: impl Into, + ) -> FieldworkBuilder, S> { + self._fields.9 = Option::Some(value.into()); + FieldworkBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl FieldworkBuilder +where + St: fieldwork_state::State, + St::CompletedAt: fieldwork_state::IsSet, + St::CreatedAt: fieldwork_state::IsSet, + St::QuestId: fieldwork_state::IsSet, + St::Signature: fieldwork_state::IsSet, + St::Track: fieldwork_state::IsSet, + St::XpAwarded: fieldwork_state::IsSet, +{ + /// Build the final struct. + pub fn build(self) -> Fieldwork { + Fieldwork { + completed_at: self._fields.0.unwrap(), + context: self._fields.1, + created_at: self._fields.2.unwrap(), + description: self._fields.3, + name: self._fields.4, + quest_id: self._fields.5.unwrap(), + retroactive: self._fields.6, + signature: self._fields.7.unwrap(), + track: self._fields.8.unwrap(), + xp_awarded: self._fields.9.unwrap(), + extra_data: Default::default(), + } + } + /// Build the final struct with custom extra_data. + pub fn build_with_data(self, extra_data: BTreeMap>) -> Fieldwork { + Fieldwork { + completed_at: self._fields.0.unwrap(), + context: self._fields.1, + created_at: self._fields.2.unwrap(), + description: self._fields.3, + name: self._fields.4, + quest_id: self._fields.5.unwrap(), + retroactive: self._fields.6, + signature: self._fields.7.unwrap(), + track: self._fields.8.unwrap(), + xp_awarded: self._fields.9.unwrap(), + extra_data: Some(extra_data), + } + } +} diff --git a/crates/jacquard-api/src/net_anisota/chronicle/log/daily.rs b/crates/jacquard-api/src/net_anisota/chronicle/log/daily.rs index cf50b6e8f..d47213d4e 100644 --- a/crates/jacquard-api/src/net_anisota/chronicle/log/daily.rs +++ b/crates/jacquard-api/src/net_anisota/chronicle/log/daily.rs @@ -127,6 +127,48 @@ pub struct ExpeditionSummary { pub extra_data: Option>>, } +/// Per-category counts of activity performed inside anisota (never inferred; recorded at write time). + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic, Default)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct InAppCounts { + ///Likes created in anisota + #[serde(skip_serializing_if = "Option::is_none")] + pub likes: Option, + ///Top-level posts created in anisota + #[serde(skip_serializing_if = "Option::is_none")] + pub posts: Option, + ///Quote posts created in anisota + #[serde(skip_serializing_if = "Option::is_none")] + pub quotes: Option, + ///Replies created in anisota + #[serde(skip_serializing_if = "Option::is_none")] + pub replies: Option, + ///Reposts created in anisota + #[serde(skip_serializing_if = "Option::is_none")] + pub reposts: Option, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +/// One device's in-anisota activity counts for the day. Keyed by a stable per-install-per-account device id, so concurrent putRecords from different devices never clobber each other. The reserved deviceId 'scheduled' holds scheduled posts published server-side by the cocoon cron worker on their publish day. + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct InAppDeviceBucket { + pub counts: daily::InAppCounts, + ///Stable per-install-per-account device id (random; no fingerprinting). Reserved value 'scheduled' for cocoon-published scheduled posts. + pub device_id: S, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + /// Daily activity snapshot. Updated throughout the day via putRecord. rkey is YYYY-MM-DD in user's local timezone. #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] @@ -149,6 +191,9 @@ pub struct Daily { pub expedition_refs: Option>, #[serde(skip_serializing_if = "Option::is_none")] pub expeditions: Option>, + ///First-party ledger of activity performed INSIDE anisota this day, one bucket per device. Optional and additive. The cross-device in-app total per field is the SUM over buckets. Used to compute an honest 'outside' floor (max(0, total - inApp)); a device only ever writes its own bucket. + #[serde(skip_serializing_if = "Option::is_none")] + pub in_app: Option>>, #[serde(skip_serializing_if = "Option::is_none")] pub patterns: Option>, pub player: daily::PlayerSnapshot, @@ -159,6 +204,8 @@ pub struct Daily { ///AT URIs of containing logs (weekly, monthly, yearly) this day belongs to #[serde(skip_serializing_if = "Option::is_none")] pub upper_log_refs: Option>, + #[serde(skip_serializing_if = "Option::is_none")] + pub walks: Option>, #[serde(flatten, default, skip_serializing_if = "Option::is_none")] pub extra_data: Option>>, } @@ -226,6 +273,27 @@ pub struct PlayerSnapshot { pub extra_data: Option>>, } +/// Summary of walks for the day (details in chronicle.walk). Parallel to expeditionSummary; both are merged additively. + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic, Default)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct WalkSummary { + ///Number of walks completed today (additive) + #[serde(skip_serializing_if = "Option::is_none")] + pub count: Option, + ///Total walk duration in minutes (additive) + #[serde(skip_serializing_if = "Option::is_none")] + pub total_duration: Option, + ///AT URIs of walk records that occurred on this day + #[serde(skip_serializing_if = "Option::is_none")] + pub walk_refs: Option>, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + impl Daily { pub fn uri(uri: S) -> Result, UriError> { RecordUri::try_from_uri(AtUri::new(uri)?) @@ -409,6 +477,81 @@ impl LexiconSchema for ExpeditionSummary { } } +impl LexiconSchema for InAppCounts { + fn nsid() -> &'static str { + "net.anisota.chronicle.log.daily" + } + fn def_name() -> &'static str { + "inAppCounts" + } + fn lexicon_doc() -> LexiconDoc<'static> { + lexicon_doc_net_anisota_chronicle_log_daily() + } + fn validate(&self) -> Result<(), ConstraintError> { + if let Some(ref value) = self.likes { + if *value < 0i64 { + return Err(ConstraintError::Minimum { + path: ValidationPath::from_field("likes"), + min: 0i64, + actual: *value, + }); + } + } + if let Some(ref value) = self.posts { + if *value < 0i64 { + return Err(ConstraintError::Minimum { + path: ValidationPath::from_field("posts"), + min: 0i64, + actual: *value, + }); + } + } + if let Some(ref value) = self.quotes { + if *value < 0i64 { + return Err(ConstraintError::Minimum { + path: ValidationPath::from_field("quotes"), + min: 0i64, + actual: *value, + }); + } + } + if let Some(ref value) = self.replies { + if *value < 0i64 { + return Err(ConstraintError::Minimum { + path: ValidationPath::from_field("replies"), + min: 0i64, + actual: *value, + }); + } + } + if let Some(ref value) = self.reposts { + if *value < 0i64 { + return Err(ConstraintError::Minimum { + path: ValidationPath::from_field("reposts"), + min: 0i64, + actual: *value, + }); + } + } + Ok(()) + } +} + +impl LexiconSchema for InAppDeviceBucket { + fn nsid() -> &'static str { + "net.anisota.chronicle.log.daily" + } + fn def_name() -> &'static str { + "inAppDeviceBucket" + } + fn lexicon_doc() -> LexiconDoc<'static> { + lexicon_doc_net_anisota_chronicle_log_daily() + } + fn validate(&self) -> Result<(), ConstraintError> { + Ok(()) + } +} + /// Marker type for deserializing records from this collection. #[derive(Debug, Serialize, Deserialize)] @@ -583,6 +726,39 @@ impl LexiconSchema for PlayerSnapshot { } } +impl LexiconSchema for WalkSummary { + fn nsid() -> &'static str { + "net.anisota.chronicle.log.daily" + } + fn def_name() -> &'static str { + "walkSummary" + } + fn lexicon_doc() -> LexiconDoc<'static> { + lexicon_doc_net_anisota_chronicle_log_daily() + } + fn validate(&self) -> Result<(), ConstraintError> { + if let Some(ref value) = self.count { + if *value < 0i64 { + return Err(ConstraintError::Minimum { + path: ValidationPath::from_field("count"), + min: 0i64, + actual: *value, + }); + } + } + if let Some(ref value) = self.total_duration { + if *value < 0i64 { + return Err(ConstraintError::Minimum { + path: ValidationPath::from_field("total_duration"), + min: 0i64, + actual: *value, + }); + } + } + Ok(()) + } +} + fn lexicon_doc_net_anisota_chronicle_log_daily() -> LexiconDoc<'static> { use alloc::collections::BTreeMap; #[allow(unused_imports)] @@ -796,6 +972,97 @@ fn lexicon_doc_net_anisota_chronicle_log_daily() -> LexiconDoc<'static> { ..Default::default() }), ); + map.insert( + SmolStr::new_static("inAppCounts"), + LexUserType::Object(LexObject { + description: Some( + CowStr::new_static( + "Per-category counts of activity performed inside anisota (never inferred; recorded at write time).", + ), + ), + properties: { + #[allow(unused_mut)] + let mut map = BTreeMap::new(); + map.insert( + SmolStr::new_static("likes"), + LexObjectProperty::Integer(LexInteger { + minimum: Some(0i64), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("posts"), + LexObjectProperty::Integer(LexInteger { + minimum: Some(0i64), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("quotes"), + LexObjectProperty::Integer(LexInteger { + minimum: Some(0i64), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("replies"), + LexObjectProperty::Integer(LexInteger { + minimum: Some(0i64), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("reposts"), + LexObjectProperty::Integer(LexInteger { + minimum: Some(0i64), + ..Default::default() + }), + ); + map + }, + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("inAppDeviceBucket"), + LexUserType::Object(LexObject { + description: Some( + CowStr::new_static( + "One device's in-anisota activity counts for the day. Keyed by a stable per-install-per-account device id, so concurrent putRecords from different devices never clobber each other. The reserved deviceId 'scheduled' holds scheduled posts published server-side by the cocoon cron worker on their publish day.", + ), + ), + required: Some( + vec![ + SmolStr::new_static("deviceId"), + SmolStr::new_static("counts") + ], + ), + properties: { + #[allow(unused_mut)] + let mut map = BTreeMap::new(); + map.insert( + SmolStr::new_static("counts"), + LexObjectProperty::Ref(LexRef { + r#ref: CowStr::new_static("#inAppCounts"), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("deviceId"), + LexObjectProperty::String(LexString { + description: Some( + CowStr::new_static( + "Stable per-install-per-account device id (random; no fingerprinting). Reserved value 'scheduled' for cocoon-published scheduled posts.", + ), + ), + ..Default::default() + }), + ); + map + }, + ..Default::default() + }), + ); map.insert( SmolStr::new_static("main"), LexUserType::Record(LexRecord { @@ -875,6 +1142,21 @@ fn lexicon_doc_net_anisota_chronicle_log_daily() -> LexiconDoc<'static> { ..Default::default() }), ); + map.insert( + SmolStr::new_static("inApp"), + LexObjectProperty::Array(LexArray { + description: Some( + CowStr::new_static( + "First-party ledger of activity performed INSIDE anisota this day, one bucket per device. Optional and additive. The cross-device in-app total per field is the SUM over buckets. Used to compute an honest 'outside' floor (max(0, total - inApp)); a device only ever writes its own bucket.", + ), + ), + items: LexArrayItem::Ref(LexRef { + r#ref: CowStr::new_static("#inAppDeviceBucket"), + ..Default::default() + }), + ..Default::default() + }), + ); map.insert( SmolStr::new_static("patterns"), LexObjectProperty::Ref(LexRef { @@ -920,6 +1202,13 @@ fn lexicon_doc_net_anisota_chronicle_log_daily() -> LexiconDoc<'static> { ..Default::default() }), ); + map.insert( + SmolStr::new_static("walks"), + LexObjectProperty::Ref(LexRef { + r#ref: CowStr::new_static("#walkSummary"), + ..Default::default() + }), + ); map }, ..Default::default() @@ -1038,6 +1327,50 @@ fn lexicon_doc_net_anisota_chronicle_log_daily() -> LexiconDoc<'static> { ..Default::default() }), ); + map.insert( + SmolStr::new_static("walkSummary"), + LexUserType::Object(LexObject { + description: Some( + CowStr::new_static( + "Summary of walks for the day (details in chronicle.walk). Parallel to expeditionSummary; both are merged additively.", + ), + ), + properties: { + #[allow(unused_mut)] + let mut map = BTreeMap::new(); + map.insert( + SmolStr::new_static("count"), + LexObjectProperty::Integer(LexInteger { + minimum: Some(0i64), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("totalDuration"), + LexObjectProperty::Integer(LexInteger { + minimum: Some(0i64), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("walkRefs"), + LexObjectProperty::Array(LexArray { + description: Some( + CowStr::new_static( + "AT URIs of walk records that occurred on this day", + ), + ), + items: LexArrayItem::String(LexString { + ..Default::default() + }), + ..Default::default() + }), + ); + map + }, + ..Default::default() + }), + ); map }, ..Default::default() @@ -1356,6 +1689,155 @@ where } } +pub mod in_app_device_bucket_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 Counts; + type DeviceId; + } + /// Empty state - all required fields are unset + pub struct Empty(()); + impl sealed::Sealed for Empty {} + impl State for Empty { + type Counts = Unset; + type DeviceId = Unset; + } + ///State transition - sets the `counts` field to Set + pub struct SetCounts(PhantomData St>); + impl sealed::Sealed for SetCounts {} + impl State for SetCounts { + type Counts = Set; + type DeviceId = St::DeviceId; + } + ///State transition - sets the `device_id` field to Set + pub struct SetDeviceId(PhantomData St>); + impl sealed::Sealed for SetDeviceId {} + impl State for SetDeviceId { + type Counts = St::Counts; + type DeviceId = Set; + } + /// Marker types for field names + #[allow(non_camel_case_types)] + pub mod members { + ///Marker type for the `counts` field + pub struct counts(()); + ///Marker type for the `device_id` field + pub struct device_id(()); + } +} + +/// Builder for constructing an instance of this type. +pub struct InAppDeviceBucketBuilder { + _state: PhantomData St>, + _fields: (Option>, Option), + _type: PhantomData S>, +} + +impl InAppDeviceBucket { + /// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed + pub fn new() -> InAppDeviceBucketBuilder { + InAppDeviceBucketBuilder::new() + } +} + +impl InAppDeviceBucket { + /// Create a new builder for this type + pub fn builder() -> InAppDeviceBucketBuilder { + InAppDeviceBucketBuilder::builder() + } +} + +impl InAppDeviceBucketBuilder { + /// Create a new builder with all fields unset, using the default string type, if needed + pub fn new() -> Self { + InAppDeviceBucketBuilder { + _state: PhantomData, + _fields: (None, None), + _type: PhantomData, + } + } +} + +impl InAppDeviceBucketBuilder { + /// Create a new builder with all fields unset + pub fn builder() -> Self { + InAppDeviceBucketBuilder { + _state: PhantomData, + _fields: (None, None), + _type: PhantomData, + } + } +} + +impl InAppDeviceBucketBuilder +where + St: in_app_device_bucket_state::State, + St::Counts: in_app_device_bucket_state::IsUnset, +{ + /// Set the `counts` field (required) + pub fn counts( + mut self, + value: impl Into>, + ) -> InAppDeviceBucketBuilder, S> { + self._fields.0 = Option::Some(value.into()); + InAppDeviceBucketBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl InAppDeviceBucketBuilder +where + St: in_app_device_bucket_state::State, + St::DeviceId: in_app_device_bucket_state::IsUnset, +{ + /// Set the `deviceId` field (required) + pub fn device_id( + mut self, + value: impl Into, + ) -> InAppDeviceBucketBuilder, S> { + self._fields.1 = Option::Some(value.into()); + InAppDeviceBucketBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl InAppDeviceBucketBuilder +where + St: in_app_device_bucket_state::State, + St::Counts: in_app_device_bucket_state::IsSet, + St::DeviceId: in_app_device_bucket_state::IsSet, +{ + /// Build the final struct. + pub fn build(self) -> InAppDeviceBucket { + InAppDeviceBucket { + counts: self._fields.0.unwrap(), + device_id: self._fields.1.unwrap(), + extra_data: Default::default(), + } + } + /// Build the final struct with custom extra_data. + pub fn build_with_data(self, extra_data: BTreeMap>) -> InAppDeviceBucket { + InAppDeviceBucket { + counts: self._fields.0.unwrap(), + device_id: self._fields.1.unwrap(), + extra_data: Some(extra_data), + } + } +} + pub mod daily_state { pub use crate::builder_types::{IsSet, IsUnset, Set, Unset}; @@ -1458,11 +1940,13 @@ pub struct DailyBuilder { Option>, Option>, Option>, + Option>>, Option>, Option>, Option>, Option, Option>, + Option>, ), _type: PhantomData S>, } @@ -1487,7 +1971,7 @@ impl DailyBuilder { DailyBuilder { _state: PhantomData, _fields: ( - None, None, None, None, None, None, None, None, None, None, None, + None, None, None, None, None, None, None, None, None, None, None, None, None, ), _type: PhantomData, } @@ -1500,7 +1984,7 @@ impl DailyBuilder { DailyBuilder { _state: PhantomData, _fields: ( - None, None, None, None, None, None, None, None, None, None, None, + None, None, None, None, None, None, None, None, None, None, None, None, None, ), _type: PhantomData, } @@ -1600,15 +2084,28 @@ impl DailyBuilder { } } +impl DailyBuilder { + /// Set the `inApp` field (optional) + pub fn in_app(mut self, value: impl Into>>>) -> Self { + self._fields.6 = value.into(); + self + } + /// Set the `inApp` field to an Option value (optional) + pub fn maybe_in_app(mut self, value: Option>>) -> Self { + self._fields.6 = value; + self + } +} + impl DailyBuilder { /// Set the `patterns` field (optional) pub fn patterns(mut self, value: impl Into>>) -> Self { - self._fields.6 = value.into(); + self._fields.7 = value.into(); self } /// Set the `patterns` field to an Option value (optional) pub fn maybe_patterns(mut self, value: Option>) -> Self { - self._fields.6 = value; + self._fields.7 = value; self } } @@ -1623,7 +2120,7 @@ where mut self, value: impl Into>, ) -> DailyBuilder, S> { - self._fields.7 = Option::Some(value.into()); + self._fields.8 = Option::Some(value.into()); DailyBuilder { _state: PhantomData, _fields: self._fields, @@ -1642,7 +2139,7 @@ where mut self, value: impl Into>, ) -> DailyBuilder, S> { - self._fields.8 = Option::Some(value.into()); + self._fields.9 = Option::Some(value.into()); DailyBuilder { _state: PhantomData, _fields: self._fields, @@ -1654,12 +2151,12 @@ where impl DailyBuilder { /// Set the `updatedAt` field (optional) pub fn updated_at(mut self, value: impl Into>) -> Self { - self._fields.9 = value.into(); + self._fields.10 = value.into(); self } /// Set the `updatedAt` field to an Option value (optional) pub fn maybe_updated_at(mut self, value: Option) -> Self { - self._fields.9 = value; + self._fields.10 = value; self } } @@ -1667,12 +2164,25 @@ impl DailyBuilder { impl DailyBuilder { /// Set the `upperLogRefs` field (optional) pub fn upper_log_refs(mut self, value: impl Into>>) -> Self { - self._fields.10 = value.into(); + self._fields.11 = value.into(); self } /// Set the `upperLogRefs` field to an Option value (optional) pub fn maybe_upper_log_refs(mut self, value: Option>) -> Self { - self._fields.10 = value; + self._fields.11 = value; + self + } +} + +impl DailyBuilder { + /// Set the `walks` field (optional) + pub fn walks(mut self, value: impl Into>>) -> Self { + self._fields.12 = value.into(); + self + } + /// Set the `walks` field to an Option value (optional) + pub fn maybe_walks(mut self, value: Option>) -> Self { + self._fields.12 = value; self } } @@ -1695,11 +2205,13 @@ where engagement: self._fields.3, expedition_refs: self._fields.4, expeditions: self._fields.5, - patterns: self._fields.6, - player: self._fields.7.unwrap(), - signature: self._fields.8.unwrap(), - updated_at: self._fields.9, - upper_log_refs: self._fields.10, + in_app: self._fields.6, + patterns: self._fields.7, + player: self._fields.8.unwrap(), + signature: self._fields.9.unwrap(), + updated_at: self._fields.10, + upper_log_refs: self._fields.11, + walks: self._fields.12, extra_data: Default::default(), } } @@ -1712,11 +2224,13 @@ where engagement: self._fields.3, expedition_refs: self._fields.4, expeditions: self._fields.5, - patterns: self._fields.6, - player: self._fields.7.unwrap(), - signature: self._fields.8.unwrap(), - updated_at: self._fields.9, - upper_log_refs: self._fields.10, + in_app: self._fields.6, + patterns: self._fields.7, + player: self._fields.8.unwrap(), + signature: self._fields.9.unwrap(), + updated_at: self._fields.10, + upper_log_refs: self._fields.11, + walks: self._fields.12, extra_data: Some(extra_data), } } diff --git a/crates/jacquard-api/src/net_anisota/chronicle/log/monthly.rs b/crates/jacquard-api/src/net_anisota/chronicle/log/monthly.rs index b8223554d..86db80ac8 100644 --- a/crates/jacquard-api/src/net_anisota/chronicle/log/monthly.rs +++ b/crates/jacquard-api/src/net_anisota/chronicle/log/monthly.rs @@ -52,6 +52,33 @@ pub struct ChronicleSignature { pub extra_data: Option>>, } +/// Per-category counts of activity performed inside anisota, summed across the period and across devices. + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic, Default)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct InAppCounts { + ///Likes created in anisota + #[serde(skip_serializing_if = "Option::is_none")] + pub likes: Option, + ///Top-level posts created in anisota + #[serde(skip_serializing_if = "Option::is_none")] + pub posts: Option, + ///Quote posts created in anisota + #[serde(skip_serializing_if = "Option::is_none")] + pub quotes: Option, + ///Replies created in anisota + #[serde(skip_serializing_if = "Option::is_none")] + pub replies: Option, + ///Reposts created in anisota + #[serde(skip_serializing_if = "Option::is_none")] + pub reposts: Option, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + /// Monthly aggregation of weekly records. rkey is YYYY-MM. Updated once per week, finalized when month ends. #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] @@ -71,6 +98,9 @@ pub struct Monthly { ///When the monthly record was finalized (end of month) #[serde(skip_serializing_if = "Option::is_none")] pub finalized_at: Option, + ///Rolled-up in-anisota activity for the month (summed daily inApp across devices, per field). Optional and additive; the read side may instead compute this from the month's daily logs. + #[serde(skip_serializing_if = "Option::is_none")] + pub in_app: Option>, ///AT URIs of weekly log records included in this month #[serde(skip_serializing_if = "Option::is_none")] pub lower_log_refs: Option>, @@ -177,6 +207,66 @@ impl LexiconSchema for ChronicleSignature { } } +impl LexiconSchema for InAppCounts { + fn nsid() -> &'static str { + "net.anisota.chronicle.log.monthly" + } + fn def_name() -> &'static str { + "inAppCounts" + } + fn lexicon_doc() -> LexiconDoc<'static> { + lexicon_doc_net_anisota_chronicle_log_monthly() + } + fn validate(&self) -> Result<(), ConstraintError> { + if let Some(ref value) = self.likes { + if *value < 0i64 { + return Err(ConstraintError::Minimum { + path: ValidationPath::from_field("likes"), + min: 0i64, + actual: *value, + }); + } + } + if let Some(ref value) = self.posts { + if *value < 0i64 { + return Err(ConstraintError::Minimum { + path: ValidationPath::from_field("posts"), + min: 0i64, + actual: *value, + }); + } + } + if let Some(ref value) = self.quotes { + if *value < 0i64 { + return Err(ConstraintError::Minimum { + path: ValidationPath::from_field("quotes"), + min: 0i64, + actual: *value, + }); + } + } + if let Some(ref value) = self.replies { + if *value < 0i64 { + return Err(ConstraintError::Minimum { + path: ValidationPath::from_field("replies"), + min: 0i64, + actual: *value, + }); + } + } + if let Some(ref value) = self.reposts { + if *value < 0i64 { + return Err(ConstraintError::Minimum { + path: ValidationPath::from_field("reposts"), + min: 0i64, + actual: *value, + }); + } + } + Ok(()) + } +} + /// Marker type for deserializing records from this collection. #[derive(Debug, Serialize, Deserialize)] @@ -749,6 +839,57 @@ fn lexicon_doc_net_anisota_chronicle_log_monthly() -> LexiconDoc<'static> { ..Default::default() }), ); + map.insert( + SmolStr::new_static("inAppCounts"), + LexUserType::Object(LexObject { + description: Some( + CowStr::new_static( + "Per-category counts of activity performed inside anisota, summed across the period and across devices.", + ), + ), + properties: { + #[allow(unused_mut)] + let mut map = BTreeMap::new(); + map.insert( + SmolStr::new_static("likes"), + LexObjectProperty::Integer(LexInteger { + minimum: Some(0i64), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("posts"), + LexObjectProperty::Integer(LexInteger { + minimum: Some(0i64), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("quotes"), + LexObjectProperty::Integer(LexInteger { + minimum: Some(0i64), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("replies"), + LexObjectProperty::Integer(LexInteger { + minimum: Some(0i64), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("reposts"), + LexObjectProperty::Integer(LexInteger { + minimum: Some(0i64), + ..Default::default() + }), + ); + map + }, + ..Default::default() + }), + ); map.insert( SmolStr::new_static("main"), LexUserType::Record(LexRecord { @@ -816,6 +957,13 @@ fn lexicon_doc_net_anisota_chronicle_log_monthly() -> LexiconDoc<'static> { ..Default::default() }), ); + map.insert( + SmolStr::new_static("inApp"), + LexObjectProperty::Ref(LexRef { + r#ref: CowStr::new_static("#inAppCounts"), + ..Default::default() + }), + ); map.insert( SmolStr::new_static("lowerLogRefs"), LexObjectProperty::Array(LexArray { @@ -1097,6 +1245,7 @@ pub struct MonthlyBuilder { Option, Option>, Option, + Option>, Option>, Option, Option>, @@ -1126,7 +1275,9 @@ impl MonthlyBuilder { pub fn new() -> Self { MonthlyBuilder { _state: PhantomData, - _fields: (None, None, None, None, None, None, None, None, None, None), + _fields: ( + None, None, None, None, None, None, None, None, None, None, None, + ), _type: PhantomData, } } @@ -1137,7 +1288,9 @@ impl MonthlyBuilder { pub fn builder() -> Self { MonthlyBuilder { _state: PhantomData, - _fields: (None, None, None, None, None, None, None, None, None, None), + _fields: ( + None, None, None, None, None, None, None, None, None, None, None, + ), _type: PhantomData, } } @@ -1207,15 +1360,28 @@ impl MonthlyBuilder { } } +impl MonthlyBuilder { + /// Set the `inApp` field (optional) + pub fn in_app(mut self, value: impl Into>>) -> Self { + self._fields.4 = value.into(); + self + } + /// Set the `inApp` field to an Option value (optional) + pub fn maybe_in_app(mut self, value: Option>) -> Self { + self._fields.4 = value; + self + } +} + impl MonthlyBuilder { /// Set the `lowerLogRefs` field (optional) pub fn lower_log_refs(mut self, value: impl Into>>) -> Self { - self._fields.4 = value.into(); + self._fields.5 = value.into(); self } /// Set the `lowerLogRefs` field to an Option value (optional) pub fn maybe_lower_log_refs(mut self, value: Option>) -> Self { - self._fields.4 = value; + self._fields.5 = value; self } } @@ -1227,7 +1393,7 @@ where { /// Set the `month` field (required) pub fn month(mut self, value: impl Into) -> MonthlyBuilder, S> { - self._fields.5 = Option::Some(value.into()); + self._fields.6 = Option::Some(value.into()); MonthlyBuilder { _state: PhantomData, _fields: self._fields, @@ -1239,12 +1405,12 @@ where impl MonthlyBuilder { /// Set the `patterns` field (optional) pub fn patterns(mut self, value: impl Into>>) -> Self { - self._fields.6 = value.into(); + self._fields.7 = value.into(); self } /// Set the `patterns` field to an Option value (optional) pub fn maybe_patterns(mut self, value: Option>) -> Self { - self._fields.6 = value; + self._fields.7 = value; self } } @@ -1259,7 +1425,7 @@ where mut self, value: impl Into>, ) -> MonthlyBuilder, S> { - self._fields.7 = Option::Some(value.into()); + self._fields.8 = Option::Some(value.into()); MonthlyBuilder { _state: PhantomData, _fields: self._fields, @@ -1278,7 +1444,7 @@ where mut self, value: impl Into, ) -> MonthlyBuilder, S> { - self._fields.8 = Option::Some(value.into()); + self._fields.9 = Option::Some(value.into()); MonthlyBuilder { _state: PhantomData, _fields: self._fields, @@ -1290,12 +1456,12 @@ where impl MonthlyBuilder { /// Set the `upperLogRefs` field (optional) pub fn upper_log_refs(mut self, value: impl Into>>) -> Self { - self._fields.9 = value.into(); + self._fields.10 = value.into(); self } /// Set the `upperLogRefs` field to an Option value (optional) pub fn maybe_upper_log_refs(mut self, value: Option>) -> Self { - self._fields.9 = value; + self._fields.10 = value; self } } @@ -1316,12 +1482,13 @@ where created_at: self._fields.1.unwrap(), expedition_refs: self._fields.2, finalized_at: self._fields.3, - lower_log_refs: self._fields.4, - month: self._fields.5.unwrap(), - patterns: self._fields.6, - signature: self._fields.7.unwrap(), - status: self._fields.8.unwrap(), - upper_log_refs: self._fields.9, + in_app: self._fields.4, + lower_log_refs: self._fields.5, + month: self._fields.6.unwrap(), + patterns: self._fields.7, + signature: self._fields.8.unwrap(), + status: self._fields.9.unwrap(), + upper_log_refs: self._fields.10, extra_data: Default::default(), } } @@ -1332,12 +1499,13 @@ where created_at: self._fields.1.unwrap(), expedition_refs: self._fields.2, finalized_at: self._fields.3, - lower_log_refs: self._fields.4, - month: self._fields.5.unwrap(), - patterns: self._fields.6, - signature: self._fields.7.unwrap(), - status: self._fields.8.unwrap(), - upper_log_refs: self._fields.9, + in_app: self._fields.4, + lower_log_refs: self._fields.5, + month: self._fields.6.unwrap(), + patterns: self._fields.7, + signature: self._fields.8.unwrap(), + status: self._fields.9.unwrap(), + upper_log_refs: self._fields.10, extra_data: Some(extra_data), } } diff --git a/crates/jacquard-api/src/net_anisota/chronicle/log/weekly.rs b/crates/jacquard-api/src/net_anisota/chronicle/log/weekly.rs index 00063c9e8..a2722a6d0 100644 --- a/crates/jacquard-api/src/net_anisota/chronicle/log/weekly.rs +++ b/crates/jacquard-api/src/net_anisota/chronicle/log/weekly.rs @@ -52,6 +52,33 @@ pub struct ChronicleSignature { pub extra_data: Option>>, } +/// Per-category counts of activity performed inside anisota, summed across the period and across devices. + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic, Default)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct InAppCounts { + ///Likes created in anisota + #[serde(skip_serializing_if = "Option::is_none")] + pub likes: Option, + ///Top-level posts created in anisota + #[serde(skip_serializing_if = "Option::is_none")] + pub posts: Option, + ///Quote posts created in anisota + #[serde(skip_serializing_if = "Option::is_none")] + pub quotes: Option, + ///Replies created in anisota + #[serde(skip_serializing_if = "Option::is_none")] + pub replies: Option, + ///Reposts created in anisota + #[serde(skip_serializing_if = "Option::is_none")] + pub reposts: Option, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + /// Weekly aggregation of daily records. rkey is YYYY-WNN (ISO week). Updated once per day, finalized when week ends. #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] @@ -71,6 +98,9 @@ pub struct Weekly { ///When the weekly record was finalized (end of week) #[serde(skip_serializing_if = "Option::is_none")] pub finalized_at: Option, + ///Rolled-up in-anisota activity for the week (summed daily inApp across devices, per field). Optional and additive; the read side may instead compute this from the week's daily logs. + #[serde(skip_serializing_if = "Option::is_none")] + pub in_app: Option>, ///AT URIs of daily log records included in this week #[serde(skip_serializing_if = "Option::is_none")] pub lower_log_refs: Option>, @@ -203,6 +233,66 @@ impl LexiconSchema for ChronicleSignature { } } +impl LexiconSchema for InAppCounts { + fn nsid() -> &'static str { + "net.anisota.chronicle.log.weekly" + } + fn def_name() -> &'static str { + "inAppCounts" + } + fn lexicon_doc() -> LexiconDoc<'static> { + lexicon_doc_net_anisota_chronicle_log_weekly() + } + fn validate(&self) -> Result<(), ConstraintError> { + if let Some(ref value) = self.likes { + if *value < 0i64 { + return Err(ConstraintError::Minimum { + path: ValidationPath::from_field("likes"), + min: 0i64, + actual: *value, + }); + } + } + if let Some(ref value) = self.posts { + if *value < 0i64 { + return Err(ConstraintError::Minimum { + path: ValidationPath::from_field("posts"), + min: 0i64, + actual: *value, + }); + } + } + if let Some(ref value) = self.quotes { + if *value < 0i64 { + return Err(ConstraintError::Minimum { + path: ValidationPath::from_field("quotes"), + min: 0i64, + actual: *value, + }); + } + } + if let Some(ref value) = self.replies { + if *value < 0i64 { + return Err(ConstraintError::Minimum { + path: ValidationPath::from_field("replies"), + min: 0i64, + actual: *value, + }); + } + } + if let Some(ref value) = self.reposts { + if *value < 0i64 { + return Err(ConstraintError::Minimum { + path: ValidationPath::from_field("reposts"), + min: 0i64, + actual: *value, + }); + } + } + Ok(()) + } +} + /// Marker type for deserializing records from this collection. #[derive(Debug, Serialize, Deserialize)] @@ -799,6 +889,57 @@ fn lexicon_doc_net_anisota_chronicle_log_weekly() -> LexiconDoc<'static> { ..Default::default() }), ); + map.insert( + SmolStr::new_static("inAppCounts"), + LexUserType::Object(LexObject { + description: Some( + CowStr::new_static( + "Per-category counts of activity performed inside anisota, summed across the period and across devices.", + ), + ), + properties: { + #[allow(unused_mut)] + let mut map = BTreeMap::new(); + map.insert( + SmolStr::new_static("likes"), + LexObjectProperty::Integer(LexInteger { + minimum: Some(0i64), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("posts"), + LexObjectProperty::Integer(LexInteger { + minimum: Some(0i64), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("quotes"), + LexObjectProperty::Integer(LexInteger { + minimum: Some(0i64), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("replies"), + LexObjectProperty::Integer(LexInteger { + minimum: Some(0i64), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("reposts"), + LexObjectProperty::Integer(LexInteger { + minimum: Some(0i64), + ..Default::default() + }), + ); + map + }, + ..Default::default() + }), + ); map.insert( SmolStr::new_static("main"), LexUserType::Record(LexRecord { @@ -866,6 +1007,13 @@ fn lexicon_doc_net_anisota_chronicle_log_weekly() -> LexiconDoc<'static> { ..Default::default() }), ); + map.insert( + SmolStr::new_static("inApp"), + LexObjectProperty::Ref(LexRef { + r#ref: CowStr::new_static("#inAppCounts"), + ..Default::default() + }), + ); map.insert( SmolStr::new_static("lowerLogRefs"), LexObjectProperty::Array(LexArray { @@ -1208,6 +1356,7 @@ pub struct WeeklyBuilder { Option, Option>, Option, + Option>, Option>, Option>, Option>, @@ -1239,7 +1388,7 @@ impl WeeklyBuilder { WeeklyBuilder { _state: PhantomData, _fields: ( - None, None, None, None, None, None, None, None, None, None, None, + None, None, None, None, None, None, None, None, None, None, None, None, ), _type: PhantomData, } @@ -1252,7 +1401,7 @@ impl WeeklyBuilder { WeeklyBuilder { _state: PhantomData, _fields: ( - None, None, None, None, None, None, None, None, None, None, None, + None, None, None, None, None, None, None, None, None, None, None, None, ), _type: PhantomData, } @@ -1323,15 +1472,28 @@ impl WeeklyBuilder { } } +impl WeeklyBuilder { + /// Set the `inApp` field (optional) + pub fn in_app(mut self, value: impl Into>>) -> Self { + self._fields.4 = value.into(); + self + } + /// Set the `inApp` field to an Option value (optional) + pub fn maybe_in_app(mut self, value: Option>) -> Self { + self._fields.4 = value; + self + } +} + impl WeeklyBuilder { /// Set the `lowerLogRefs` field (optional) pub fn lower_log_refs(mut self, value: impl Into>>) -> Self { - self._fields.4 = value.into(); + self._fields.5 = value.into(); self } /// Set the `lowerLogRefs` field to an Option value (optional) pub fn maybe_lower_log_refs(mut self, value: Option>) -> Self { - self._fields.4 = value; + self._fields.5 = value; self } } @@ -1339,12 +1501,12 @@ impl WeeklyBuilder { impl WeeklyBuilder { /// Set the `patterns` field (optional) pub fn patterns(mut self, value: impl Into>>) -> Self { - self._fields.5 = value.into(); + self._fields.6 = value.into(); self } /// Set the `patterns` field to an Option value (optional) pub fn maybe_patterns(mut self, value: Option>) -> Self { - self._fields.5 = value; + self._fields.6 = value; self } } @@ -1359,7 +1521,7 @@ where mut self, value: impl Into>, ) -> WeeklyBuilder, S> { - self._fields.6 = Option::Some(value.into()); + self._fields.7 = Option::Some(value.into()); WeeklyBuilder { _state: PhantomData, _fields: self._fields, @@ -1375,7 +1537,7 @@ where { /// Set the `status` field (required) pub fn status(mut self, value: impl Into) -> WeeklyBuilder, S> { - self._fields.7 = Option::Some(value.into()); + self._fields.8 = Option::Some(value.into()); WeeklyBuilder { _state: PhantomData, _fields: self._fields, @@ -1387,12 +1549,12 @@ where impl WeeklyBuilder { /// Set the `trends` field (optional) pub fn trends(mut self, value: impl Into>>) -> Self { - self._fields.8 = value.into(); + self._fields.9 = value.into(); self } /// Set the `trends` field to an Option value (optional) pub fn maybe_trends(mut self, value: Option>) -> Self { - self._fields.8 = value; + self._fields.9 = value; self } } @@ -1400,12 +1562,12 @@ impl WeeklyBuilder { impl WeeklyBuilder { /// Set the `upperLogRefs` field (optional) pub fn upper_log_refs(mut self, value: impl Into>>) -> Self { - self._fields.9 = value.into(); + self._fields.10 = value.into(); self } /// Set the `upperLogRefs` field to an Option value (optional) pub fn maybe_upper_log_refs(mut self, value: Option>) -> Self { - self._fields.9 = value; + self._fields.10 = value; self } } @@ -1417,7 +1579,7 @@ where { /// Set the `week` field (required) pub fn week(mut self, value: impl Into) -> WeeklyBuilder, S> { - self._fields.10 = Option::Some(value.into()); + self._fields.11 = Option::Some(value.into()); WeeklyBuilder { _state: PhantomData, _fields: self._fields, @@ -1442,13 +1604,14 @@ where created_at: self._fields.1.unwrap(), expedition_refs: self._fields.2, finalized_at: self._fields.3, - lower_log_refs: self._fields.4, - patterns: self._fields.5, - signature: self._fields.6.unwrap(), - status: self._fields.7.unwrap(), - trends: self._fields.8, - upper_log_refs: self._fields.9, - week: self._fields.10.unwrap(), + in_app: self._fields.4, + lower_log_refs: self._fields.5, + patterns: self._fields.6, + signature: self._fields.7.unwrap(), + status: self._fields.8.unwrap(), + trends: self._fields.9, + upper_log_refs: self._fields.10, + week: self._fields.11.unwrap(), extra_data: Default::default(), } } @@ -1459,13 +1622,14 @@ where created_at: self._fields.1.unwrap(), expedition_refs: self._fields.2, finalized_at: self._fields.3, - lower_log_refs: self._fields.4, - patterns: self._fields.5, - signature: self._fields.6.unwrap(), - status: self._fields.7.unwrap(), - trends: self._fields.8, - upper_log_refs: self._fields.9, - week: self._fields.10.unwrap(), + in_app: self._fields.4, + lower_log_refs: self._fields.5, + patterns: self._fields.6, + signature: self._fields.7.unwrap(), + status: self._fields.8.unwrap(), + trends: self._fields.9, + upper_log_refs: self._fields.10, + week: self._fields.11.unwrap(), extra_data: Some(extra_data), } } diff --git a/crates/jacquard-api/src/net_anisota/chronicle/log/yearly.rs b/crates/jacquard-api/src/net_anisota/chronicle/log/yearly.rs index 545d90413..88df5e2ba 100644 --- a/crates/jacquard-api/src/net_anisota/chronicle/log/yearly.rs +++ b/crates/jacquard-api/src/net_anisota/chronicle/log/yearly.rs @@ -52,6 +52,33 @@ pub struct ChronicleSignature { pub extra_data: Option>>, } +/// Per-category counts of activity performed inside anisota, summed across the period and across devices. + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic, Default)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct InAppCounts { + ///Likes created in anisota + #[serde(skip_serializing_if = "Option::is_none")] + pub likes: Option, + ///Top-level posts created in anisota + #[serde(skip_serializing_if = "Option::is_none")] + pub posts: Option, + ///Quote posts created in anisota + #[serde(skip_serializing_if = "Option::is_none")] + pub quotes: Option, + ///Replies created in anisota + #[serde(skip_serializing_if = "Option::is_none")] + pub replies: Option, + ///Reposts created in anisota + #[serde(skip_serializing_if = "Option::is_none")] + pub reposts: Option, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + /// Yearly aggregation of monthly records. rkey is YYYY. Updated once per month, finalized when year ends. #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] @@ -68,6 +95,9 @@ pub struct Yearly { ///When the yearly record was finalized (end of year) #[serde(skip_serializing_if = "Option::is_none")] pub finalized_at: Option, + ///Rolled-up in-anisota activity for the year (summed daily inApp across devices, per field). Optional and additive; the read side may instead compute this from the year's daily logs. + #[serde(skip_serializing_if = "Option::is_none")] + pub in_app: Option>, ///AT URIs of monthly log records included in this year #[serde(skip_serializing_if = "Option::is_none")] pub lower_log_refs: Option>, @@ -174,6 +204,66 @@ impl LexiconSchema for ChronicleSignature { } } +impl LexiconSchema for InAppCounts { + fn nsid() -> &'static str { + "net.anisota.chronicle.log.yearly" + } + fn def_name() -> &'static str { + "inAppCounts" + } + fn lexicon_doc() -> LexiconDoc<'static> { + lexicon_doc_net_anisota_chronicle_log_yearly() + } + fn validate(&self) -> Result<(), ConstraintError> { + if let Some(ref value) = self.likes { + if *value < 0i64 { + return Err(ConstraintError::Minimum { + path: ValidationPath::from_field("likes"), + min: 0i64, + actual: *value, + }); + } + } + if let Some(ref value) = self.posts { + if *value < 0i64 { + return Err(ConstraintError::Minimum { + path: ValidationPath::from_field("posts"), + min: 0i64, + actual: *value, + }); + } + } + if let Some(ref value) = self.quotes { + if *value < 0i64 { + return Err(ConstraintError::Minimum { + path: ValidationPath::from_field("quotes"), + min: 0i64, + actual: *value, + }); + } + } + if let Some(ref value) = self.replies { + if *value < 0i64 { + return Err(ConstraintError::Minimum { + path: ValidationPath::from_field("replies"), + min: 0i64, + actual: *value, + }); + } + } + if let Some(ref value) = self.reposts { + if *value < 0i64 { + return Err(ConstraintError::Minimum { + path: ValidationPath::from_field("reposts"), + min: 0i64, + actual: *value, + }); + } + } + Ok(()) + } +} + /// Marker type for deserializing records from this collection. #[derive(Debug, Serialize, Deserialize)] @@ -755,6 +845,57 @@ fn lexicon_doc_net_anisota_chronicle_log_yearly() -> LexiconDoc<'static> { ..Default::default() }), ); + map.insert( + SmolStr::new_static("inAppCounts"), + LexUserType::Object(LexObject { + description: Some( + CowStr::new_static( + "Per-category counts of activity performed inside anisota, summed across the period and across devices.", + ), + ), + properties: { + #[allow(unused_mut)] + let mut map = BTreeMap::new(); + map.insert( + SmolStr::new_static("likes"), + LexObjectProperty::Integer(LexInteger { + minimum: Some(0i64), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("posts"), + LexObjectProperty::Integer(LexInteger { + minimum: Some(0i64), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("quotes"), + LexObjectProperty::Integer(LexInteger { + minimum: Some(0i64), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("replies"), + LexObjectProperty::Integer(LexInteger { + minimum: Some(0i64), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("reposts"), + LexObjectProperty::Integer(LexInteger { + minimum: Some(0i64), + ..Default::default() + }), + ); + map + }, + ..Default::default() + }), + ); map.insert( SmolStr::new_static("main"), LexUserType::Record(LexRecord { @@ -808,6 +949,13 @@ fn lexicon_doc_net_anisota_chronicle_log_yearly() -> LexiconDoc<'static> { ..Default::default() }), ); + map.insert( + SmolStr::new_static("inApp"), + LexObjectProperty::Ref(LexRef { + r#ref: CowStr::new_static("#inAppCounts"), + ..Default::default() + }), + ); map.insert( SmolStr::new_static("lowerLogRefs"), LexObjectProperty::Array(LexArray { @@ -1079,6 +1227,7 @@ pub struct YearlyBuilder { Option>, Option, Option, + Option>, Option>, Option>, Option>, @@ -1107,7 +1256,7 @@ impl YearlyBuilder { pub fn new() -> Self { YearlyBuilder { _state: PhantomData, - _fields: (None, None, None, None, None, None, None, None), + _fields: (None, None, None, None, None, None, None, None, None), _type: PhantomData, } } @@ -1118,7 +1267,7 @@ impl YearlyBuilder { pub fn builder() -> Self { YearlyBuilder { _state: PhantomData, - _fields: (None, None, None, None, None, None, None, None), + _fields: (None, None, None, None, None, None, None, None, None), _type: PhantomData, } } @@ -1175,15 +1324,28 @@ impl YearlyBuilder { } } +impl YearlyBuilder { + /// Set the `inApp` field (optional) + pub fn in_app(mut self, value: impl Into>>) -> Self { + self._fields.3 = value.into(); + self + } + /// Set the `inApp` field to an Option value (optional) + pub fn maybe_in_app(mut self, value: Option>) -> Self { + self._fields.3 = value; + self + } +} + impl YearlyBuilder { /// Set the `lowerLogRefs` field (optional) pub fn lower_log_refs(mut self, value: impl Into>>) -> Self { - self._fields.3 = value.into(); + self._fields.4 = value.into(); self } /// Set the `lowerLogRefs` field to an Option value (optional) pub fn maybe_lower_log_refs(mut self, value: Option>) -> Self { - self._fields.3 = value; + self._fields.4 = value; self } } @@ -1191,12 +1353,12 @@ impl YearlyBuilder { impl YearlyBuilder { /// Set the `patterns` field (optional) pub fn patterns(mut self, value: impl Into>>) -> Self { - self._fields.4 = value.into(); + self._fields.5 = value.into(); self } /// Set the `patterns` field to an Option value (optional) pub fn maybe_patterns(mut self, value: Option>) -> Self { - self._fields.4 = value; + self._fields.5 = value; self } } @@ -1211,7 +1373,7 @@ where mut self, value: impl Into>, ) -> YearlyBuilder, S> { - self._fields.5 = Option::Some(value.into()); + self._fields.6 = Option::Some(value.into()); YearlyBuilder { _state: PhantomData, _fields: self._fields, @@ -1227,7 +1389,7 @@ where { /// Set the `status` field (required) pub fn status(mut self, value: impl Into) -> YearlyBuilder, S> { - self._fields.6 = Option::Some(value.into()); + self._fields.7 = Option::Some(value.into()); YearlyBuilder { _state: PhantomData, _fields: self._fields, @@ -1243,7 +1405,7 @@ where { /// Set the `year` field (required) pub fn year(mut self, value: impl Into) -> YearlyBuilder, S> { - self._fields.7 = Option::Some(value.into()); + self._fields.8 = Option::Some(value.into()); YearlyBuilder { _state: PhantomData, _fields: self._fields, @@ -1267,11 +1429,12 @@ where aggregates: self._fields.0.unwrap(), created_at: self._fields.1.unwrap(), finalized_at: self._fields.2, - lower_log_refs: self._fields.3, - patterns: self._fields.4, - signature: self._fields.5.unwrap(), - status: self._fields.6.unwrap(), - year: self._fields.7.unwrap(), + in_app: self._fields.3, + lower_log_refs: self._fields.4, + patterns: self._fields.5, + signature: self._fields.6.unwrap(), + status: self._fields.7.unwrap(), + year: self._fields.8.unwrap(), extra_data: Default::default(), } } @@ -1281,11 +1444,12 @@ where aggregates: self._fields.0.unwrap(), created_at: self._fields.1.unwrap(), finalized_at: self._fields.2, - lower_log_refs: self._fields.3, - patterns: self._fields.4, - signature: self._fields.5.unwrap(), - status: self._fields.6.unwrap(), - year: self._fields.7.unwrap(), + in_app: self._fields.3, + lower_log_refs: self._fields.4, + patterns: self._fields.5, + signature: self._fields.6.unwrap(), + status: self._fields.7.unwrap(), + year: self._fields.8.unwrap(), extra_data: Some(extra_data), } } diff --git a/crates/jacquard-api/src/net_anisota/chronicle/milestone.rs b/crates/jacquard-api/src/net_anisota/chronicle/milestone.rs new file mode 100644 index 000000000..fa3fc31cd --- /dev/null +++ b/crates/jacquard-api/src/net_anisota/chronicle/milestone.rs @@ -0,0 +1,1262 @@ +// @generated by jacquard-lexicon. DO NOT EDIT. +// +// Lexicon: net.anisota.chronicle.milestone +// +// 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; + +use crate::net_anisota::chronicle::milestone; +#[allow(unused_imports)] +use jacquard_lexicon::validation::{ConstraintError, ValidationPath}; +use serde::{Deserialize, Serialize}; +/// ES256 cryptographic signature proving record authenticity. The signature itself proves legitimacy - no separate verification lexicons needed. + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct ChronicleSignature { + ///Signing algorithm (ES256) + pub alg: S, + ///Key identifier for the signing key + pub kid: S, + ///Unique random nonce to prevent replay + pub nonce: S, + ///Base64-encoded ES256 signature + pub sig: S, + ///When the record was signed + pub signed_at: Datetime, + ///Signature schema version + pub version: i64, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +/// A milestone reached in the field, shown on the Fieldwork page's Milestones tab. Successor to net.anisota.chronicle.achievement (legacy records in that collection remain readable but no new ones are written). rkey is the milestone ID (e.g. level-50, expedition-first-light). Created once with createRecord when the milestone is reached. Immutable. + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + rename = "net.anisota.chronicle.milestone", + tag = "$type", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct Milestone { + ///Category of the milestone + pub category: S, + #[serde(skip_serializing_if = "Option::is_none")] + pub context: Option>, + ///When the milestone record was created + pub created_at: Datetime, + ///AT URI of the daily record when the milestone was reached + #[serde(skip_serializing_if = "Option::is_none")] + pub daily_record_ref: Option, + ///Description of what was reached + #[serde(skip_serializing_if = "Option::is_none")] + pub description: Option, + ///Unique identifier for the milestone (e.g. 'level-50', 'expedition-first-light') + pub milestone_id: S, + ///Display name of the milestone + #[serde(skip_serializing_if = "Option::is_none")] + pub name: Option, + ///Rarity tier of the milestone + #[serde(skip_serializing_if = "Option::is_none")] + pub rarity: Option, + pub signature: milestone::ChronicleSignature, + ///Tier or threshold value (e.g. 50 for level-50) + #[serde(skip_serializing_if = "Option::is_none")] + pub tier: Option, + ///When the milestone was reached + pub unlocked_at: Datetime, + ///XP awarded for this milestone + #[serde(skip_serializing_if = "Option::is_none")] + pub xp_reward: 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 MilestoneGetRecordOutput { + #[serde(skip_serializing_if = "Option::is_none")] + pub cid: Option>, + pub uri: AtUri, + pub value: Milestone, +} + +/// Contextual data at the time the milestone was reached + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic, Default)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct MilestoneContext { + ///Player level when the milestone was reached + #[serde(skip_serializing_if = "Option::is_none")] + pub level: Option, + ///Post count when the milestone was reached + #[serde(skip_serializing_if = "Option::is_none")] + pub post_count: Option, + ///Specimen count when the milestone was reached + #[serde(skip_serializing_if = "Option::is_none")] + pub specimen_count: Option, + ///Total XP when the milestone was reached + #[serde(skip_serializing_if = "Option::is_none")] + pub total_xp: Option, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +impl Milestone { + pub fn uri(uri: S) -> Result, UriError> { + RecordUri::try_from_uri(AtUri::new(uri)?) + } +} + +impl LexiconSchema for ChronicleSignature { + fn nsid() -> &'static str { + "net.anisota.chronicle.milestone" + } + fn def_name() -> &'static str { + "chronicleSignature" + } + fn lexicon_doc() -> LexiconDoc<'static> { + lexicon_doc_net_anisota_chronicle_milestone() + } + fn validate(&self) -> Result<(), ConstraintError> { + Ok(()) + } +} + +/// Marker type for deserializing records from this collection. + +#[derive(Debug, Serialize, Deserialize)] +pub struct MilestoneRecord; +impl XrpcResp for MilestoneRecord { + const NSID: &'static str = "net.anisota.chronicle.milestone"; + const ENCODING: &'static str = "application/json"; + type Output = MilestoneGetRecordOutput; + type Err = RecordError; +} + +impl From> for Milestone { + fn from(output: MilestoneGetRecordOutput) -> Self { + output.value + } +} + +impl Collection for Milestone { + const NSID: &'static str = "net.anisota.chronicle.milestone"; + type Record = MilestoneRecord; +} + +impl Collection for MilestoneRecord { + const NSID: &'static str = "net.anisota.chronicle.milestone"; + type Record = MilestoneRecord; +} + +impl LexiconSchema for Milestone { + fn nsid() -> &'static str { + "net.anisota.chronicle.milestone" + } + fn def_name() -> &'static str { + "main" + } + fn lexicon_doc() -> LexiconDoc<'static> { + lexicon_doc_net_anisota_chronicle_milestone() + } + fn validate(&self) -> Result<(), ConstraintError> { + if let Some(ref value) = self.description { + #[allow(unused_comparisons)] + if ::len(value.as_ref()) > 500usize { + return Err(ConstraintError::MaxLength { + path: ValidationPath::from_field("description"), + max: 500usize, + actual: ::len(value.as_ref()), + }); + } + } + { + let value = &self.milestone_id; + #[allow(unused_comparisons)] + if ::len(value.as_ref()) > 100usize { + return Err(ConstraintError::MaxLength { + path: ValidationPath::from_field("milestone_id"), + max: 100usize, + actual: ::len(value.as_ref()), + }); + } + } + if let Some(ref value) = self.name { + #[allow(unused_comparisons)] + if ::len(value.as_ref()) > 100usize { + return Err(ConstraintError::MaxLength { + path: ValidationPath::from_field("name"), + max: 100usize, + actual: ::len(value.as_ref()), + }); + } + } + if let Some(ref value) = self.tier { + if *value < 0i64 { + return Err(ConstraintError::Minimum { + path: ValidationPath::from_field("tier"), + min: 0i64, + actual: *value, + }); + } + } + if let Some(ref value) = self.xp_reward { + if *value < 0i64 { + return Err(ConstraintError::Minimum { + path: ValidationPath::from_field("xp_reward"), + min: 0i64, + actual: *value, + }); + } + } + Ok(()) + } +} + +impl LexiconSchema for MilestoneContext { + fn nsid() -> &'static str { + "net.anisota.chronicle.milestone" + } + fn def_name() -> &'static str { + "milestoneContext" + } + fn lexicon_doc() -> LexiconDoc<'static> { + lexicon_doc_net_anisota_chronicle_milestone() + } + fn validate(&self) -> Result<(), ConstraintError> { + if let Some(ref value) = self.level { + if *value < 1i64 { + return Err(ConstraintError::Minimum { + path: ValidationPath::from_field("level"), + min: 1i64, + actual: *value, + }); + } + } + if let Some(ref value) = self.post_count { + if *value < 0i64 { + return Err(ConstraintError::Minimum { + path: ValidationPath::from_field("post_count"), + min: 0i64, + actual: *value, + }); + } + } + if let Some(ref value) = self.specimen_count { + if *value < 0i64 { + return Err(ConstraintError::Minimum { + path: ValidationPath::from_field("specimen_count"), + min: 0i64, + actual: *value, + }); + } + } + if let Some(ref value) = self.total_xp { + if *value < 0i64 { + return Err(ConstraintError::Minimum { + path: ValidationPath::from_field("total_xp"), + min: 0i64, + actual: *value, + }); + } + } + Ok(()) + } +} + +pub mod chronicle_signature_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 Alg; + type Kid; + type Nonce; + type Sig; + type SignedAt; + type Version; + } + /// Empty state - all required fields are unset + pub struct Empty(()); + impl sealed::Sealed for Empty {} + impl State for Empty { + type Alg = Unset; + type Kid = Unset; + type Nonce = Unset; + type Sig = Unset; + type SignedAt = Unset; + type Version = Unset; + } + ///State transition - sets the `alg` field to Set + pub struct SetAlg(PhantomData St>); + impl sealed::Sealed for SetAlg {} + impl State for SetAlg { + type Alg = Set; + type Kid = St::Kid; + type Nonce = St::Nonce; + type Sig = St::Sig; + type SignedAt = St::SignedAt; + type Version = St::Version; + } + ///State transition - sets the `kid` field to Set + pub struct SetKid(PhantomData St>); + impl sealed::Sealed for SetKid {} + impl State for SetKid { + type Alg = St::Alg; + type Kid = Set; + type Nonce = St::Nonce; + type Sig = St::Sig; + type SignedAt = St::SignedAt; + type Version = St::Version; + } + ///State transition - sets the `nonce` field to Set + pub struct SetNonce(PhantomData St>); + impl sealed::Sealed for SetNonce {} + impl State for SetNonce { + type Alg = St::Alg; + type Kid = St::Kid; + type Nonce = Set; + type Sig = St::Sig; + type SignedAt = St::SignedAt; + type Version = St::Version; + } + ///State transition - sets the `sig` field to Set + pub struct SetSig(PhantomData St>); + impl sealed::Sealed for SetSig {} + impl State for SetSig { + type Alg = St::Alg; + type Kid = St::Kid; + type Nonce = St::Nonce; + type Sig = Set; + type SignedAt = St::SignedAt; + type Version = St::Version; + } + ///State transition - sets the `signed_at` field to Set + pub struct SetSignedAt(PhantomData St>); + impl sealed::Sealed for SetSignedAt {} + impl State for SetSignedAt { + type Alg = St::Alg; + type Kid = St::Kid; + type Nonce = St::Nonce; + type Sig = St::Sig; + type SignedAt = Set; + type Version = St::Version; + } + ///State transition - sets the `version` field to Set + pub struct SetVersion(PhantomData St>); + impl sealed::Sealed for SetVersion {} + impl State for SetVersion { + type Alg = St::Alg; + type Kid = St::Kid; + type Nonce = St::Nonce; + type Sig = St::Sig; + type SignedAt = St::SignedAt; + type Version = Set; + } + /// Marker types for field names + #[allow(non_camel_case_types)] + pub mod members { + ///Marker type for the `alg` field + pub struct alg(()); + ///Marker type for the `kid` field + pub struct kid(()); + ///Marker type for the `nonce` field + pub struct nonce(()); + ///Marker type for the `sig` field + pub struct sig(()); + ///Marker type for the `signed_at` field + pub struct signed_at(()); + ///Marker type for the `version` field + pub struct version(()); + } +} + +/// Builder for constructing an instance of this type. +pub struct ChronicleSignatureBuilder { + _state: PhantomData St>, + _fields: ( + Option, + Option, + Option, + Option, + Option, + Option, + ), + _type: PhantomData S>, +} + +impl ChronicleSignature { + /// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed + pub fn new() -> ChronicleSignatureBuilder { + ChronicleSignatureBuilder::new() + } +} + +impl ChronicleSignature { + /// Create a new builder for this type + pub fn builder() -> ChronicleSignatureBuilder { + ChronicleSignatureBuilder::builder() + } +} + +impl ChronicleSignatureBuilder { + /// Create a new builder with all fields unset, using the default string type, if needed + pub fn new() -> Self { + ChronicleSignatureBuilder { + _state: PhantomData, + _fields: (None, None, None, None, None, None), + _type: PhantomData, + } + } +} + +impl ChronicleSignatureBuilder { + /// Create a new builder with all fields unset + pub fn builder() -> Self { + ChronicleSignatureBuilder { + _state: PhantomData, + _fields: (None, None, None, None, None, None), + _type: PhantomData, + } + } +} + +impl ChronicleSignatureBuilder +where + St: chronicle_signature_state::State, + St::Alg: chronicle_signature_state::IsUnset, +{ + /// Set the `alg` field (required) + pub fn alg( + mut self, + value: impl Into, + ) -> ChronicleSignatureBuilder, S> { + self._fields.0 = Option::Some(value.into()); + ChronicleSignatureBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl ChronicleSignatureBuilder +where + St: chronicle_signature_state::State, + St::Kid: chronicle_signature_state::IsUnset, +{ + /// Set the `kid` field (required) + pub fn kid( + mut self, + value: impl Into, + ) -> ChronicleSignatureBuilder, S> { + self._fields.1 = Option::Some(value.into()); + ChronicleSignatureBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl ChronicleSignatureBuilder +where + St: chronicle_signature_state::State, + St::Nonce: chronicle_signature_state::IsUnset, +{ + /// Set the `nonce` field (required) + pub fn nonce( + mut self, + value: impl Into, + ) -> ChronicleSignatureBuilder, S> { + self._fields.2 = Option::Some(value.into()); + ChronicleSignatureBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl ChronicleSignatureBuilder +where + St: chronicle_signature_state::State, + St::Sig: chronicle_signature_state::IsUnset, +{ + /// Set the `sig` field (required) + pub fn sig( + mut self, + value: impl Into, + ) -> ChronicleSignatureBuilder, S> { + self._fields.3 = Option::Some(value.into()); + ChronicleSignatureBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl ChronicleSignatureBuilder +where + St: chronicle_signature_state::State, + St::SignedAt: chronicle_signature_state::IsUnset, +{ + /// Set the `signedAt` field (required) + pub fn signed_at( + mut self, + value: impl Into, + ) -> ChronicleSignatureBuilder, S> { + self._fields.4 = Option::Some(value.into()); + ChronicleSignatureBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl ChronicleSignatureBuilder +where + St: chronicle_signature_state::State, + St::Version: chronicle_signature_state::IsUnset, +{ + /// Set the `version` field (required) + pub fn version( + mut self, + value: impl Into, + ) -> ChronicleSignatureBuilder, S> { + self._fields.5 = Option::Some(value.into()); + ChronicleSignatureBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl ChronicleSignatureBuilder +where + St: chronicle_signature_state::State, + St::Alg: chronicle_signature_state::IsSet, + St::Kid: chronicle_signature_state::IsSet, + St::Nonce: chronicle_signature_state::IsSet, + St::Sig: chronicle_signature_state::IsSet, + St::SignedAt: chronicle_signature_state::IsSet, + St::Version: chronicle_signature_state::IsSet, +{ + /// Build the final struct. + pub fn build(self) -> ChronicleSignature { + ChronicleSignature { + alg: self._fields.0.unwrap(), + kid: self._fields.1.unwrap(), + nonce: self._fields.2.unwrap(), + sig: self._fields.3.unwrap(), + signed_at: self._fields.4.unwrap(), + version: self._fields.5.unwrap(), + extra_data: Default::default(), + } + } + /// Build the final struct with custom extra_data. + pub fn build_with_data(self, extra_data: BTreeMap>) -> ChronicleSignature { + ChronicleSignature { + alg: self._fields.0.unwrap(), + kid: self._fields.1.unwrap(), + nonce: self._fields.2.unwrap(), + sig: self._fields.3.unwrap(), + signed_at: self._fields.4.unwrap(), + version: self._fields.5.unwrap(), + extra_data: Some(extra_data), + } + } +} + +fn lexicon_doc_net_anisota_chronicle_milestone() -> 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("net.anisota.chronicle.milestone"), + defs: { + let mut map = BTreeMap::new(); + map.insert( + SmolStr::new_static("chronicleSignature"), + LexUserType::Object(LexObject { + description: Some( + CowStr::new_static( + "ES256 cryptographic signature proving record authenticity. The signature itself proves legitimacy - no separate verification lexicons needed.", + ), + ), + required: Some( + vec![ + SmolStr::new_static("sig"), SmolStr::new_static("alg"), + SmolStr::new_static("kid"), SmolStr::new_static("signedAt"), + SmolStr::new_static("nonce"), SmolStr::new_static("version") + ], + ), + properties: { + #[allow(unused_mut)] + let mut map = BTreeMap::new(); + map.insert( + SmolStr::new_static("alg"), + LexObjectProperty::String(LexString { + description: Some( + CowStr::new_static("Signing algorithm (ES256)"), + ), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("kid"), + LexObjectProperty::String(LexString { + description: Some( + CowStr::new_static("Key identifier for the signing key"), + ), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("nonce"), + LexObjectProperty::String(LexString { + description: Some( + CowStr::new_static("Unique random nonce to prevent replay"), + ), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("sig"), + LexObjectProperty::String(LexString { + description: Some( + CowStr::new_static("Base64-encoded ES256 signature"), + ), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("signedAt"), + LexObjectProperty::String(LexString { + description: Some( + CowStr::new_static("When the record was signed"), + ), + format: Some(LexStringFormat::Datetime), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("version"), + LexObjectProperty::Integer(LexInteger { + ..Default::default() + }), + ); + map + }, + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("main"), + LexUserType::Record(LexRecord { + description: Some( + CowStr::new_static( + "A milestone reached in the field, shown on the Fieldwork page's Milestones tab. Successor to net.anisota.chronicle.achievement (legacy records in that collection remain readable but no new ones are written). rkey is the milestone ID (e.g. level-50, expedition-first-light). Created once with createRecord when the milestone is reached. Immutable.", + ), + ), + key: Some(CowStr::new_static("any")), + record: LexRecordRecord::Object(LexObject { + required: Some( + vec![ + SmolStr::new_static("milestoneId"), + SmolStr::new_static("category"), + SmolStr::new_static("unlockedAt"), + SmolStr::new_static("signature"), + SmolStr::new_static("createdAt") + ], + ), + properties: { + #[allow(unused_mut)] + let mut map = BTreeMap::new(); + map.insert( + SmolStr::new_static("category"), + LexObjectProperty::String(LexString { + description: Some( + CowStr::new_static("Category of the milestone"), + ), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("context"), + LexObjectProperty::Ref(LexRef { + r#ref: CowStr::new_static("#milestoneContext"), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("createdAt"), + LexObjectProperty::String(LexString { + description: Some( + CowStr::new_static("When the milestone record was created"), + ), + format: Some(LexStringFormat::Datetime), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("dailyRecordRef"), + LexObjectProperty::String(LexString { + description: Some( + CowStr::new_static( + "AT URI of the daily record when the milestone was reached", + ), + ), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("description"), + LexObjectProperty::String(LexString { + description: Some( + CowStr::new_static("Description of what was reached"), + ), + max_length: Some(500usize), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("milestoneId"), + LexObjectProperty::String(LexString { + description: Some( + CowStr::new_static( + "Unique identifier for the milestone (e.g. 'level-50', 'expedition-first-light')", + ), + ), + max_length: Some(100usize), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("name"), + LexObjectProperty::String(LexString { + description: Some( + CowStr::new_static("Display name of the milestone"), + ), + max_length: Some(100usize), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("rarity"), + LexObjectProperty::String(LexString { + description: Some( + CowStr::new_static("Rarity tier of the milestone"), + ), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("signature"), + LexObjectProperty::Ref(LexRef { + r#ref: CowStr::new_static("#chronicleSignature"), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("tier"), + LexObjectProperty::Integer(LexInteger { + minimum: Some(0i64), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("unlockedAt"), + LexObjectProperty::String(LexString { + description: Some( + CowStr::new_static("When the milestone was reached"), + ), + format: Some(LexStringFormat::Datetime), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("xpReward"), + LexObjectProperty::Integer(LexInteger { + minimum: Some(0i64), + ..Default::default() + }), + ); + map + }, + ..Default::default() + }), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("milestoneContext"), + LexUserType::Object(LexObject { + description: Some(CowStr::new_static( + "Contextual data at the time the milestone was reached", + )), + properties: { + #[allow(unused_mut)] + let mut map = BTreeMap::new(); + map.insert( + SmolStr::new_static("level"), + LexObjectProperty::Integer(LexInteger { + minimum: Some(1i64), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("postCount"), + LexObjectProperty::Integer(LexInteger { + minimum: Some(0i64), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("specimenCount"), + LexObjectProperty::Integer(LexInteger { + minimum: Some(0i64), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("totalXP"), + LexObjectProperty::Integer(LexInteger { + minimum: Some(0i64), + ..Default::default() + }), + ); + map + }, + ..Default::default() + }), + ); + map + }, + ..Default::default() + } +} + +pub mod milestone_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 Category; + type CreatedAt; + type MilestoneId; + type Signature; + type UnlockedAt; + } + /// Empty state - all required fields are unset + pub struct Empty(()); + impl sealed::Sealed for Empty {} + impl State for Empty { + type Category = Unset; + type CreatedAt = Unset; + type MilestoneId = Unset; + type Signature = Unset; + type UnlockedAt = Unset; + } + ///State transition - sets the `category` field to Set + pub struct SetCategory(PhantomData St>); + impl sealed::Sealed for SetCategory {} + impl State for SetCategory { + type Category = Set; + type CreatedAt = St::CreatedAt; + type MilestoneId = St::MilestoneId; + type Signature = St::Signature; + type UnlockedAt = St::UnlockedAt; + } + ///State transition - sets the `created_at` field to Set + pub struct SetCreatedAt(PhantomData St>); + impl sealed::Sealed for SetCreatedAt {} + impl State for SetCreatedAt { + type Category = St::Category; + type CreatedAt = Set; + type MilestoneId = St::MilestoneId; + type Signature = St::Signature; + type UnlockedAt = St::UnlockedAt; + } + ///State transition - sets the `milestone_id` field to Set + pub struct SetMilestoneId(PhantomData St>); + impl sealed::Sealed for SetMilestoneId {} + impl State for SetMilestoneId { + type Category = St::Category; + type CreatedAt = St::CreatedAt; + type MilestoneId = Set; + type Signature = St::Signature; + type UnlockedAt = St::UnlockedAt; + } + ///State transition - sets the `signature` field to Set + pub struct SetSignature(PhantomData St>); + impl sealed::Sealed for SetSignature {} + impl State for SetSignature { + type Category = St::Category; + type CreatedAt = St::CreatedAt; + type MilestoneId = St::MilestoneId; + type Signature = Set; + type UnlockedAt = St::UnlockedAt; + } + ///State transition - sets the `unlocked_at` field to Set + pub struct SetUnlockedAt(PhantomData St>); + impl sealed::Sealed for SetUnlockedAt {} + impl State for SetUnlockedAt { + type Category = St::Category; + type CreatedAt = St::CreatedAt; + type MilestoneId = St::MilestoneId; + type Signature = St::Signature; + type UnlockedAt = Set; + } + /// Marker types for field names + #[allow(non_camel_case_types)] + pub mod members { + ///Marker type for the `category` field + pub struct category(()); + ///Marker type for the `created_at` field + pub struct created_at(()); + ///Marker type for the `milestone_id` field + pub struct milestone_id(()); + ///Marker type for the `signature` field + pub struct signature(()); + ///Marker type for the `unlocked_at` field + pub struct unlocked_at(()); + } +} + +/// Builder for constructing an instance of this type. +pub struct MilestoneBuilder { + _state: PhantomData St>, + _fields: ( + Option, + Option>, + Option, + Option, + Option, + Option, + Option, + Option, + Option>, + Option, + Option, + Option, + ), + _type: PhantomData S>, +} + +impl Milestone { + /// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed + pub fn new() -> MilestoneBuilder { + MilestoneBuilder::new() + } +} + +impl Milestone { + /// Create a new builder for this type + pub fn builder() -> MilestoneBuilder { + MilestoneBuilder::builder() + } +} + +impl MilestoneBuilder { + /// Create a new builder with all fields unset, using the default string type, if needed + pub fn new() -> Self { + MilestoneBuilder { + _state: PhantomData, + _fields: ( + None, None, None, None, None, None, None, None, None, None, None, None, + ), + _type: PhantomData, + } + } +} + +impl MilestoneBuilder { + /// Create a new builder with all fields unset + pub fn builder() -> Self { + MilestoneBuilder { + _state: PhantomData, + _fields: ( + None, None, None, None, None, None, None, None, None, None, None, None, + ), + _type: PhantomData, + } + } +} + +impl MilestoneBuilder +where + St: milestone_state::State, + St::Category: milestone_state::IsUnset, +{ + /// Set the `category` field (required) + pub fn category( + mut self, + value: impl Into, + ) -> MilestoneBuilder, S> { + self._fields.0 = Option::Some(value.into()); + MilestoneBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl MilestoneBuilder { + /// Set the `context` field (optional) + pub fn context(mut self, value: impl Into>>) -> Self { + self._fields.1 = value.into(); + self + } + /// Set the `context` field to an Option value (optional) + pub fn maybe_context(mut self, value: Option>) -> Self { + self._fields.1 = value; + self + } +} + +impl MilestoneBuilder +where + St: milestone_state::State, + St::CreatedAt: milestone_state::IsUnset, +{ + /// Set the `createdAt` field (required) + pub fn created_at( + mut self, + value: impl Into, + ) -> MilestoneBuilder, S> { + self._fields.2 = Option::Some(value.into()); + MilestoneBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl MilestoneBuilder { + /// Set the `dailyRecordRef` field (optional) + pub fn daily_record_ref(mut self, value: impl Into>) -> Self { + self._fields.3 = value.into(); + self + } + /// Set the `dailyRecordRef` field to an Option value (optional) + pub fn maybe_daily_record_ref(mut self, value: Option) -> Self { + self._fields.3 = value; + self + } +} + +impl MilestoneBuilder { + /// Set the `description` field (optional) + pub fn description(mut self, value: impl Into>) -> Self { + self._fields.4 = value.into(); + self + } + /// Set the `description` field to an Option value (optional) + pub fn maybe_description(mut self, value: Option) -> Self { + self._fields.4 = value; + self + } +} + +impl MilestoneBuilder +where + St: milestone_state::State, + St::MilestoneId: milestone_state::IsUnset, +{ + /// Set the `milestoneId` field (required) + pub fn milestone_id( + mut self, + value: impl Into, + ) -> MilestoneBuilder, S> { + self._fields.5 = Option::Some(value.into()); + MilestoneBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl MilestoneBuilder { + /// Set the `name` field (optional) + pub fn name(mut self, value: impl Into>) -> Self { + self._fields.6 = value.into(); + self + } + /// Set the `name` field to an Option value (optional) + pub fn maybe_name(mut self, value: Option) -> Self { + self._fields.6 = value; + self + } +} + +impl MilestoneBuilder { + /// Set the `rarity` field (optional) + pub fn rarity(mut self, value: impl Into>) -> Self { + self._fields.7 = value.into(); + self + } + /// Set the `rarity` field to an Option value (optional) + pub fn maybe_rarity(mut self, value: Option) -> Self { + self._fields.7 = value; + self + } +} + +impl MilestoneBuilder +where + St: milestone_state::State, + St::Signature: milestone_state::IsUnset, +{ + /// Set the `signature` field (required) + pub fn signature( + mut self, + value: impl Into>, + ) -> MilestoneBuilder, S> { + self._fields.8 = Option::Some(value.into()); + MilestoneBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl MilestoneBuilder { + /// Set the `tier` field (optional) + pub fn tier(mut self, value: impl Into>) -> Self { + self._fields.9 = value.into(); + self + } + /// Set the `tier` field to an Option value (optional) + pub fn maybe_tier(mut self, value: Option) -> Self { + self._fields.9 = value; + self + } +} + +impl MilestoneBuilder +where + St: milestone_state::State, + St::UnlockedAt: milestone_state::IsUnset, +{ + /// Set the `unlockedAt` field (required) + pub fn unlocked_at( + mut self, + value: impl Into, + ) -> MilestoneBuilder, S> { + self._fields.10 = Option::Some(value.into()); + MilestoneBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl MilestoneBuilder { + /// Set the `xpReward` field (optional) + pub fn xp_reward(mut self, value: impl Into>) -> Self { + self._fields.11 = value.into(); + self + } + /// Set the `xpReward` field to an Option value (optional) + pub fn maybe_xp_reward(mut self, value: Option) -> Self { + self._fields.11 = value; + self + } +} + +impl MilestoneBuilder +where + St: milestone_state::State, + St::Category: milestone_state::IsSet, + St::CreatedAt: milestone_state::IsSet, + St::MilestoneId: milestone_state::IsSet, + St::Signature: milestone_state::IsSet, + St::UnlockedAt: milestone_state::IsSet, +{ + /// Build the final struct. + pub fn build(self) -> Milestone { + Milestone { + category: self._fields.0.unwrap(), + context: self._fields.1, + created_at: self._fields.2.unwrap(), + daily_record_ref: self._fields.3, + description: self._fields.4, + milestone_id: self._fields.5.unwrap(), + name: self._fields.6, + rarity: self._fields.7, + signature: self._fields.8.unwrap(), + tier: self._fields.9, + unlocked_at: self._fields.10.unwrap(), + xp_reward: self._fields.11, + extra_data: Default::default(), + } + } + /// Build the final struct with custom extra_data. + pub fn build_with_data(self, extra_data: BTreeMap>) -> Milestone { + Milestone { + category: self._fields.0.unwrap(), + context: self._fields.1, + created_at: self._fields.2.unwrap(), + daily_record_ref: self._fields.3, + description: self._fields.4, + milestone_id: self._fields.5.unwrap(), + name: self._fields.6, + rarity: self._fields.7, + signature: self._fields.8.unwrap(), + tier: self._fields.9, + unlocked_at: self._fields.10.unwrap(), + xp_reward: self._fields.11, + extra_data: Some(extra_data), + } + } +} diff --git a/crates/jacquard-api/src/net_anisota/chronicle/walk.rs b/crates/jacquard-api/src/net_anisota/chronicle/walk.rs new file mode 100644 index 000000000..a2c040a56 --- /dev/null +++ b/crates/jacquard-api/src/net_anisota/chronicle/walk.rs @@ -0,0 +1,2129 @@ +// @generated by jacquard-lexicon. DO NOT EDIT. +// +// Lexicon: net.anisota.chronicle.walk +// +// This file was automatically generated from Lexicon schemas. +// Any manual changes will be overwritten on the next regeneration. + +//! Generated bindings for the `net.anisota.chronicle.walk` Lexicon namespace/module. +pub mod camp; + +#[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; + +use crate::net_anisota::chronicle::walk; +#[allow(unused_imports)] +use jacquard_lexicon::validation::{ConstraintError, ValidationPath}; +use serde::{Deserialize, Serialize}; +/// ES256 cryptographic signature proving record authenticity + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct ChronicleSignature { + ///Signing algorithm (ES256) + pub alg: S, + ///Key identifier for the signing key + pub kid: S, + ///Unique random nonce to prevent replay + pub nonce: S, + ///Base64-encoded ES256 signature + pub sig: S, + ///When the record was signed + pub signed_at: Datetime, + ///Signature schema version + pub version: i64, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +/// Per-device progress bucket. Buckets are summed across devices (not max-merged) so in-app activity spread over multiple devices is fully counted. + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic, Default)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct DeviceProgress { + #[serde(skip_serializing_if = "Option::is_none")] + pub counts: Option>, + ///Random per-install device id from userScopedStorage. No fingerprinting. + #[serde(skip_serializing_if = "Option::is_none")] + pub device_id: Option, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +/// Light state at heartbeat time + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic, Default)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct HeartbeatLight { + ///Current light level + #[serde(skip_serializing_if = "Option::is_none")] + pub current: Option, + ///Whether drain is actively ticking (true while exploring, false while resting or camping). Walks have no frozen state. + #[serde(skip_serializing_if = "Option::is_none")] + pub drain_active: Option, + ///Current drain rate as percentage + #[serde(skip_serializing_if = "Option::is_none")] + pub drain_rate: Option, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +/// Session progress counters at heartbeat time (per-device bucket contents) + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic, Default)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct HeartbeatProgress { + #[serde(skip_serializing_if = "Option::is_none")] + pub items_count: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub likes_sent: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub moths_seen_count: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub posts_created: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub posts_read: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub reposts_sent: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub specimens_count: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub xp_gained: Option, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +/// Walk record. Created with status 'active' at first engagement (first tracked action on the feed), kept current with putRecord, and updated to 'completed' when the walk closes (idle auto-close, light depletion, or a manual wrap-up). rkey is a TID. Walks are the everyday unit and are never numbered; identity is the record key and display identity is the walk's time. Tracks the full lifecycle of a walk including camps, gathered findings, light consumption, and conditions. + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + rename = "net.anisota.chronicle.walk", + tag = "$type", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct Walk { + ///Active exploring time in minutes (excludes camp/rest time) + #[serde(skip_serializing_if = "Option::is_none")] + pub active_duration: Option, + ///Number of camps made during the walk + #[serde(skip_serializing_if = "Option::is_none")] + pub camps_count: Option, + ///How the walk closed. Known values: 'user' (manual 'that's enough for now' tap), 'auto' (idle auto-close after the inactivity window), and 'lamp' (light depleted). Free string with no enum so future close reasons need no lexicon change. Unset while the walk is active. + #[serde(skip_serializing_if = "Option::is_none")] + pub closed_by: Option, + ///When the walk ended. For idle auto-closes this is the last tracked activity, clamped to be no earlier than startedAt. + #[serde(skip_serializing_if = "Option::is_none")] + pub completed_at: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub conditions: Option>, + ///When the record was created + pub created_at: Datetime, + ///Total walk duration in minutes + #[serde(skip_serializing_if = "Option::is_none")] + pub duration: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub elsewhere_activity: Option>, + #[serde(skip_serializing_if = "Option::is_none")] + pub findings: Option>, + #[serde(skip_serializing_if = "Option::is_none")] + pub heartbeat: Option>, + #[serde(skip_serializing_if = "Option::is_none")] + pub light: Option>, + ///Total camp/rest time in minutes + #[serde(skip_serializing_if = "Option::is_none")] + pub rest_duration: Option, + pub signature: walk::ChronicleSignature, + ///When the walk started (first engagement) + #[serde(skip_serializing_if = "Option::is_none")] + pub started_at: Option, + ///Current walk status. A walk is 'active' while open and 'completed' once it closes; there is no 'abandoned' state because a walk never fails. + pub status: S, + ///When the record was last updated + #[serde(skip_serializing_if = "Option::is_none")] + pub updated_at: 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 WalkGetRecordOutput { + #[serde(skip_serializing_if = "Option::is_none")] + pub cid: Option>, + pub uri: AtUri, + pub value: Walk, +} + +/// Environmental conditions during the walk + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic, Default)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct WalkConditions { + ///Forest biome type + #[serde(skip_serializing_if = "Option::is_none")] + pub biome: Option, + ///Time-of-day light condition at walk start + #[serde(skip_serializing_if = "Option::is_none")] + pub light_level: Option, + ///Moon phase condition (nighttime only) + #[serde(skip_serializing_if = "Option::is_none")] + pub moon_phase: Option, + ///User fatigue state at walk start + #[serde(skip_serializing_if = "Option::is_none")] + pub user_state: Option, + ///Weather condition during the walk + #[serde(skip_serializing_if = "Option::is_none")] + pub weather: Option, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +/// Cross-client activity during the walk window that did NOT happen in anisota: the PDS scan of app.bsky posts/likes/reposts in the walk window minus the in-app per-device summed totals, floored at 0 per field. Because likes and reposts carry no client marker this is a subtraction estimate, so the elsewhere panel labels it 'at least'. This block NEVER earns XP or findings; it is data for the panel only. Optional; unset when there was no elsewhere activity or the scan was unavailable. + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic, Default)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct WalkElsewhereActivity { + ///Likes sent elsewhere during the walk window (scan minus in-app; at-least estimate) + #[serde(skip_serializing_if = "Option::is_none")] + pub likes_sent: Option, + ///Posts created elsewhere during the walk window (scan minus in-app) + #[serde(skip_serializing_if = "Option::is_none")] + pub posts_created: Option, + ///Reposts sent elsewhere during the walk window (scan minus in-app; at-least estimate) + #[serde(skip_serializing_if = "Option::is_none")] + pub reposts_sent: Option, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +/// What was found/gathered during the walk + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic, Default)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct WalkFindings { + ///Number of items collected + #[serde(skip_serializing_if = "Option::is_none")] + pub items_collected: Option, + ///Likes sent during the walk + #[serde(skip_serializing_if = "Option::is_none")] + pub likes_sent: Option, + ///Total moth encounters (caught + escaped) + #[serde(skip_serializing_if = "Option::is_none")] + pub moths_seen: Option, + ///Posts created during the walk + #[serde(skip_serializing_if = "Option::is_none")] + pub posts_created: Option, + ///Posts read during the walk + #[serde(skip_serializing_if = "Option::is_none")] + pub posts_read: Option, + ///Reposts sent during the walk + #[serde(skip_serializing_if = "Option::is_none")] + pub reposts_sent: Option, + ///Number of specimens successfully caught + #[serde(skip_serializing_if = "Option::is_none")] + pub specimens_found: Option, + ///XP gained from the walk + #[serde(skip_serializing_if = "Option::is_none")] + pub xp_gained: Option, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +/// Periodic snapshot of walk progress for cross-device sync + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic, Default)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct WalkHeartbeat { + ///Timestamp of the last tracked activity. Drives the idle clock and is max-merged across devices (heartbeats themselves fire on a timer, so idle detection must key on this field, not updatedAt). + #[serde(skip_serializing_if = "Option::is_none")] + pub last_activity_at: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub light: Option>, + ///Per-device progress buckets, one entry per device that has contributed to this walk. In-app totals are the SUM across buckets, not a max-merge: per-device buckets exist deliberately so multi-device in-app activity is never undercounted (an undercount would falsely inflate the elsewhere figure). + #[serde(skip_serializing_if = "Option::is_none")] + pub progress: Option>>, + ///When this heartbeat was written + #[serde(skip_serializing_if = "Option::is_none")] + pub updated_at: Option, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +/// Light resource tracking for the walk + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic, Default)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct WalkLight { + ///Light level when the walk ended (in minutes) + #[serde(skip_serializing_if = "Option::is_none")] + pub at_end: Option, + ///Light level when the walk started (in minutes) + #[serde(skip_serializing_if = "Option::is_none")] + pub at_start: Option, + ///Total light consumed during the walk + #[serde(skip_serializing_if = "Option::is_none")] + pub consumed: Option, + ///Effective drain rate as a percentage (80 = 0.8x drain). Multiply by 0.01 to get the float multiplier. + #[serde(skip_serializing_if = "Option::is_none")] + pub drain_rate: Option, + ///Total light regenerated during the walk's camps + #[serde(skip_serializing_if = "Option::is_none")] + pub regenerated: Option, + ///Light status at start of the walk + #[serde(skip_serializing_if = "Option::is_none")] + pub status: Option, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +impl Walk { + pub fn uri(uri: S) -> Result, UriError> { + RecordUri::try_from_uri(AtUri::new(uri)?) + } +} + +impl LexiconSchema for ChronicleSignature { + fn nsid() -> &'static str { + "net.anisota.chronicle.walk" + } + fn def_name() -> &'static str { + "chronicleSignature" + } + fn lexicon_doc() -> LexiconDoc<'static> { + lexicon_doc_net_anisota_chronicle_walk() + } + fn validate(&self) -> Result<(), ConstraintError> { + Ok(()) + } +} + +impl LexiconSchema for DeviceProgress { + fn nsid() -> &'static str { + "net.anisota.chronicle.walk" + } + fn def_name() -> &'static str { + "deviceProgress" + } + fn lexicon_doc() -> LexiconDoc<'static> { + lexicon_doc_net_anisota_chronicle_walk() + } + fn validate(&self) -> Result<(), ConstraintError> { + Ok(()) + } +} + +impl LexiconSchema for HeartbeatLight { + fn nsid() -> &'static str { + "net.anisota.chronicle.walk" + } + fn def_name() -> &'static str { + "heartbeatLight" + } + fn lexicon_doc() -> LexiconDoc<'static> { + lexicon_doc_net_anisota_chronicle_walk() + } + fn validate(&self) -> Result<(), ConstraintError> { + Ok(()) + } +} + +impl LexiconSchema for HeartbeatProgress { + fn nsid() -> &'static str { + "net.anisota.chronicle.walk" + } + fn def_name() -> &'static str { + "heartbeatProgress" + } + fn lexicon_doc() -> LexiconDoc<'static> { + lexicon_doc_net_anisota_chronicle_walk() + } + fn validate(&self) -> Result<(), ConstraintError> { + if let Some(ref value) = self.items_count { + if *value < 0i64 { + return Err(ConstraintError::Minimum { + path: ValidationPath::from_field("items_count"), + min: 0i64, + actual: *value, + }); + } + } + if let Some(ref value) = self.likes_sent { + if *value < 0i64 { + return Err(ConstraintError::Minimum { + path: ValidationPath::from_field("likes_sent"), + min: 0i64, + actual: *value, + }); + } + } + if let Some(ref value) = self.moths_seen_count { + if *value < 0i64 { + return Err(ConstraintError::Minimum { + path: ValidationPath::from_field("moths_seen_count"), + min: 0i64, + actual: *value, + }); + } + } + if let Some(ref value) = self.posts_created { + if *value < 0i64 { + return Err(ConstraintError::Minimum { + path: ValidationPath::from_field("posts_created"), + min: 0i64, + actual: *value, + }); + } + } + if let Some(ref value) = self.posts_read { + if *value < 0i64 { + return Err(ConstraintError::Minimum { + path: ValidationPath::from_field("posts_read"), + min: 0i64, + actual: *value, + }); + } + } + if let Some(ref value) = self.reposts_sent { + if *value < 0i64 { + return Err(ConstraintError::Minimum { + path: ValidationPath::from_field("reposts_sent"), + min: 0i64, + actual: *value, + }); + } + } + if let Some(ref value) = self.specimens_count { + if *value < 0i64 { + return Err(ConstraintError::Minimum { + path: ValidationPath::from_field("specimens_count"), + min: 0i64, + actual: *value, + }); + } + } + if let Some(ref value) = self.xp_gained { + if *value < 0i64 { + return Err(ConstraintError::Minimum { + path: ValidationPath::from_field("xp_gained"), + min: 0i64, + actual: *value, + }); + } + } + Ok(()) + } +} + +/// Marker type for deserializing records from this collection. + +#[derive(Debug, Serialize, Deserialize)] +pub struct WalkRecord; +impl XrpcResp for WalkRecord { + const NSID: &'static str = "net.anisota.chronicle.walk"; + const ENCODING: &'static str = "application/json"; + type Output = WalkGetRecordOutput; + type Err = RecordError; +} + +impl From> for Walk { + fn from(output: WalkGetRecordOutput) -> Self { + output.value + } +} + +impl Collection for Walk { + const NSID: &'static str = "net.anisota.chronicle.walk"; + type Record = WalkRecord; +} + +impl Collection for WalkRecord { + const NSID: &'static str = "net.anisota.chronicle.walk"; + type Record = WalkRecord; +} + +impl LexiconSchema for Walk { + fn nsid() -> &'static str { + "net.anisota.chronicle.walk" + } + fn def_name() -> &'static str { + "main" + } + fn lexicon_doc() -> LexiconDoc<'static> { + lexicon_doc_net_anisota_chronicle_walk() + } + fn validate(&self) -> Result<(), ConstraintError> { + if let Some(ref value) = self.active_duration { + if *value < 0i64 { + return Err(ConstraintError::Minimum { + path: ValidationPath::from_field("active_duration"), + min: 0i64, + actual: *value, + }); + } + } + if let Some(ref value) = self.camps_count { + if *value < 0i64 { + return Err(ConstraintError::Minimum { + path: ValidationPath::from_field("camps_count"), + min: 0i64, + actual: *value, + }); + } + } + if let Some(ref value) = self.duration { + if *value < 0i64 { + return Err(ConstraintError::Minimum { + path: ValidationPath::from_field("duration"), + min: 0i64, + actual: *value, + }); + } + } + if let Some(ref value) = self.rest_duration { + if *value < 0i64 { + return Err(ConstraintError::Minimum { + path: ValidationPath::from_field("rest_duration"), + min: 0i64, + actual: *value, + }); + } + } + Ok(()) + } +} + +impl LexiconSchema for WalkConditions { + fn nsid() -> &'static str { + "net.anisota.chronicle.walk" + } + fn def_name() -> &'static str { + "walkConditions" + } + fn lexicon_doc() -> LexiconDoc<'static> { + lexicon_doc_net_anisota_chronicle_walk() + } + fn validate(&self) -> Result<(), ConstraintError> { + Ok(()) + } +} + +impl LexiconSchema for WalkElsewhereActivity { + fn nsid() -> &'static str { + "net.anisota.chronicle.walk" + } + fn def_name() -> &'static str { + "walkElsewhereActivity" + } + fn lexicon_doc() -> LexiconDoc<'static> { + lexicon_doc_net_anisota_chronicle_walk() + } + fn validate(&self) -> Result<(), ConstraintError> { + if let Some(ref value) = self.likes_sent { + if *value < 0i64 { + return Err(ConstraintError::Minimum { + path: ValidationPath::from_field("likes_sent"), + min: 0i64, + actual: *value, + }); + } + } + if let Some(ref value) = self.posts_created { + if *value < 0i64 { + return Err(ConstraintError::Minimum { + path: ValidationPath::from_field("posts_created"), + min: 0i64, + actual: *value, + }); + } + } + if let Some(ref value) = self.reposts_sent { + if *value < 0i64 { + return Err(ConstraintError::Minimum { + path: ValidationPath::from_field("reposts_sent"), + min: 0i64, + actual: *value, + }); + } + } + Ok(()) + } +} + +impl LexiconSchema for WalkFindings { + fn nsid() -> &'static str { + "net.anisota.chronicle.walk" + } + fn def_name() -> &'static str { + "walkFindings" + } + fn lexicon_doc() -> LexiconDoc<'static> { + lexicon_doc_net_anisota_chronicle_walk() + } + fn validate(&self) -> Result<(), ConstraintError> { + if let Some(ref value) = self.items_collected { + if *value < 0i64 { + return Err(ConstraintError::Minimum { + path: ValidationPath::from_field("items_collected"), + min: 0i64, + actual: *value, + }); + } + } + if let Some(ref value) = self.likes_sent { + if *value < 0i64 { + return Err(ConstraintError::Minimum { + path: ValidationPath::from_field("likes_sent"), + min: 0i64, + actual: *value, + }); + } + } + if let Some(ref value) = self.moths_seen { + if *value < 0i64 { + return Err(ConstraintError::Minimum { + path: ValidationPath::from_field("moths_seen"), + min: 0i64, + actual: *value, + }); + } + } + if let Some(ref value) = self.posts_created { + if *value < 0i64 { + return Err(ConstraintError::Minimum { + path: ValidationPath::from_field("posts_created"), + min: 0i64, + actual: *value, + }); + } + } + if let Some(ref value) = self.posts_read { + if *value < 0i64 { + return Err(ConstraintError::Minimum { + path: ValidationPath::from_field("posts_read"), + min: 0i64, + actual: *value, + }); + } + } + if let Some(ref value) = self.reposts_sent { + if *value < 0i64 { + return Err(ConstraintError::Minimum { + path: ValidationPath::from_field("reposts_sent"), + min: 0i64, + actual: *value, + }); + } + } + if let Some(ref value) = self.specimens_found { + if *value < 0i64 { + return Err(ConstraintError::Minimum { + path: ValidationPath::from_field("specimens_found"), + min: 0i64, + actual: *value, + }); + } + } + if let Some(ref value) = self.xp_gained { + if *value < 0i64 { + return Err(ConstraintError::Minimum { + path: ValidationPath::from_field("xp_gained"), + min: 0i64, + actual: *value, + }); + } + } + Ok(()) + } +} + +impl LexiconSchema for WalkHeartbeat { + fn nsid() -> &'static str { + "net.anisota.chronicle.walk" + } + fn def_name() -> &'static str { + "walkHeartbeat" + } + fn lexicon_doc() -> LexiconDoc<'static> { + lexicon_doc_net_anisota_chronicle_walk() + } + fn validate(&self) -> Result<(), ConstraintError> { + Ok(()) + } +} + +impl LexiconSchema for WalkLight { + fn nsid() -> &'static str { + "net.anisota.chronicle.walk" + } + fn def_name() -> &'static str { + "walkLight" + } + fn lexicon_doc() -> LexiconDoc<'static> { + lexicon_doc_net_anisota_chronicle_walk() + } + fn validate(&self) -> Result<(), ConstraintError> { + if let Some(ref value) = self.at_end { + if *value < 0i64 { + return Err(ConstraintError::Minimum { + path: ValidationPath::from_field("at_end"), + min: 0i64, + actual: *value, + }); + } + } + if let Some(ref value) = self.at_start { + if *value < 0i64 { + return Err(ConstraintError::Minimum { + path: ValidationPath::from_field("at_start"), + min: 0i64, + actual: *value, + }); + } + } + if let Some(ref value) = self.consumed { + if *value < 0i64 { + return Err(ConstraintError::Minimum { + path: ValidationPath::from_field("consumed"), + min: 0i64, + actual: *value, + }); + } + } + if let Some(ref value) = self.regenerated { + if *value < 0i64 { + return Err(ConstraintError::Minimum { + path: ValidationPath::from_field("regenerated"), + min: 0i64, + actual: *value, + }); + } + } + Ok(()) + } +} + +pub mod chronicle_signature_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 Alg; + type Kid; + type Nonce; + type Sig; + type SignedAt; + type Version; + } + /// Empty state - all required fields are unset + pub struct Empty(()); + impl sealed::Sealed for Empty {} + impl State for Empty { + type Alg = Unset; + type Kid = Unset; + type Nonce = Unset; + type Sig = Unset; + type SignedAt = Unset; + type Version = Unset; + } + ///State transition - sets the `alg` field to Set + pub struct SetAlg(PhantomData St>); + impl sealed::Sealed for SetAlg {} + impl State for SetAlg { + type Alg = Set; + type Kid = St::Kid; + type Nonce = St::Nonce; + type Sig = St::Sig; + type SignedAt = St::SignedAt; + type Version = St::Version; + } + ///State transition - sets the `kid` field to Set + pub struct SetKid(PhantomData St>); + impl sealed::Sealed for SetKid {} + impl State for SetKid { + type Alg = St::Alg; + type Kid = Set; + type Nonce = St::Nonce; + type Sig = St::Sig; + type SignedAt = St::SignedAt; + type Version = St::Version; + } + ///State transition - sets the `nonce` field to Set + pub struct SetNonce(PhantomData St>); + impl sealed::Sealed for SetNonce {} + impl State for SetNonce { + type Alg = St::Alg; + type Kid = St::Kid; + type Nonce = Set; + type Sig = St::Sig; + type SignedAt = St::SignedAt; + type Version = St::Version; + } + ///State transition - sets the `sig` field to Set + pub struct SetSig(PhantomData St>); + impl sealed::Sealed for SetSig {} + impl State for SetSig { + type Alg = St::Alg; + type Kid = St::Kid; + type Nonce = St::Nonce; + type Sig = Set; + type SignedAt = St::SignedAt; + type Version = St::Version; + } + ///State transition - sets the `signed_at` field to Set + pub struct SetSignedAt(PhantomData St>); + impl sealed::Sealed for SetSignedAt {} + impl State for SetSignedAt { + type Alg = St::Alg; + type Kid = St::Kid; + type Nonce = St::Nonce; + type Sig = St::Sig; + type SignedAt = Set; + type Version = St::Version; + } + ///State transition - sets the `version` field to Set + pub struct SetVersion(PhantomData St>); + impl sealed::Sealed for SetVersion {} + impl State for SetVersion { + type Alg = St::Alg; + type Kid = St::Kid; + type Nonce = St::Nonce; + type Sig = St::Sig; + type SignedAt = St::SignedAt; + type Version = Set; + } + /// Marker types for field names + #[allow(non_camel_case_types)] + pub mod members { + ///Marker type for the `alg` field + pub struct alg(()); + ///Marker type for the `kid` field + pub struct kid(()); + ///Marker type for the `nonce` field + pub struct nonce(()); + ///Marker type for the `sig` field + pub struct sig(()); + ///Marker type for the `signed_at` field + pub struct signed_at(()); + ///Marker type for the `version` field + pub struct version(()); + } +} + +/// Builder for constructing an instance of this type. +pub struct ChronicleSignatureBuilder { + _state: PhantomData St>, + _fields: ( + Option, + Option, + Option, + Option, + Option, + Option, + ), + _type: PhantomData S>, +} + +impl ChronicleSignature { + /// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed + pub fn new() -> ChronicleSignatureBuilder { + ChronicleSignatureBuilder::new() + } +} + +impl ChronicleSignature { + /// Create a new builder for this type + pub fn builder() -> ChronicleSignatureBuilder { + ChronicleSignatureBuilder::builder() + } +} + +impl ChronicleSignatureBuilder { + /// Create a new builder with all fields unset, using the default string type, if needed + pub fn new() -> Self { + ChronicleSignatureBuilder { + _state: PhantomData, + _fields: (None, None, None, None, None, None), + _type: PhantomData, + } + } +} + +impl ChronicleSignatureBuilder { + /// Create a new builder with all fields unset + pub fn builder() -> Self { + ChronicleSignatureBuilder { + _state: PhantomData, + _fields: (None, None, None, None, None, None), + _type: PhantomData, + } + } +} + +impl ChronicleSignatureBuilder +where + St: chronicle_signature_state::State, + St::Alg: chronicle_signature_state::IsUnset, +{ + /// Set the `alg` field (required) + pub fn alg( + mut self, + value: impl Into, + ) -> ChronicleSignatureBuilder, S> { + self._fields.0 = Option::Some(value.into()); + ChronicleSignatureBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl ChronicleSignatureBuilder +where + St: chronicle_signature_state::State, + St::Kid: chronicle_signature_state::IsUnset, +{ + /// Set the `kid` field (required) + pub fn kid( + mut self, + value: impl Into, + ) -> ChronicleSignatureBuilder, S> { + self._fields.1 = Option::Some(value.into()); + ChronicleSignatureBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl ChronicleSignatureBuilder +where + St: chronicle_signature_state::State, + St::Nonce: chronicle_signature_state::IsUnset, +{ + /// Set the `nonce` field (required) + pub fn nonce( + mut self, + value: impl Into, + ) -> ChronicleSignatureBuilder, S> { + self._fields.2 = Option::Some(value.into()); + ChronicleSignatureBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl ChronicleSignatureBuilder +where + St: chronicle_signature_state::State, + St::Sig: chronicle_signature_state::IsUnset, +{ + /// Set the `sig` field (required) + pub fn sig( + mut self, + value: impl Into, + ) -> ChronicleSignatureBuilder, S> { + self._fields.3 = Option::Some(value.into()); + ChronicleSignatureBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl ChronicleSignatureBuilder +where + St: chronicle_signature_state::State, + St::SignedAt: chronicle_signature_state::IsUnset, +{ + /// Set the `signedAt` field (required) + pub fn signed_at( + mut self, + value: impl Into, + ) -> ChronicleSignatureBuilder, S> { + self._fields.4 = Option::Some(value.into()); + ChronicleSignatureBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl ChronicleSignatureBuilder +where + St: chronicle_signature_state::State, + St::Version: chronicle_signature_state::IsUnset, +{ + /// Set the `version` field (required) + pub fn version( + mut self, + value: impl Into, + ) -> ChronicleSignatureBuilder, S> { + self._fields.5 = Option::Some(value.into()); + ChronicleSignatureBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl ChronicleSignatureBuilder +where + St: chronicle_signature_state::State, + St::Alg: chronicle_signature_state::IsSet, + St::Kid: chronicle_signature_state::IsSet, + St::Nonce: chronicle_signature_state::IsSet, + St::Sig: chronicle_signature_state::IsSet, + St::SignedAt: chronicle_signature_state::IsSet, + St::Version: chronicle_signature_state::IsSet, +{ + /// Build the final struct. + pub fn build(self) -> ChronicleSignature { + ChronicleSignature { + alg: self._fields.0.unwrap(), + kid: self._fields.1.unwrap(), + nonce: self._fields.2.unwrap(), + sig: self._fields.3.unwrap(), + signed_at: self._fields.4.unwrap(), + version: self._fields.5.unwrap(), + extra_data: Default::default(), + } + } + /// Build the final struct with custom extra_data. + pub fn build_with_data(self, extra_data: BTreeMap>) -> ChronicleSignature { + ChronicleSignature { + alg: self._fields.0.unwrap(), + kid: self._fields.1.unwrap(), + nonce: self._fields.2.unwrap(), + sig: self._fields.3.unwrap(), + signed_at: self._fields.4.unwrap(), + version: self._fields.5.unwrap(), + extra_data: Some(extra_data), + } + } +} + +fn lexicon_doc_net_anisota_chronicle_walk() -> 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("net.anisota.chronicle.walk"), + defs: { + let mut map = BTreeMap::new(); + map.insert( + SmolStr::new_static("chronicleSignature"), + LexUserType::Object(LexObject { + description: Some(CowStr::new_static( + "ES256 cryptographic signature proving record authenticity", + )), + required: Some(vec![ + SmolStr::new_static("sig"), + SmolStr::new_static("alg"), + SmolStr::new_static("kid"), + SmolStr::new_static("signedAt"), + SmolStr::new_static("nonce"), + SmolStr::new_static("version"), + ]), + properties: { + #[allow(unused_mut)] + let mut map = BTreeMap::new(); + map.insert( + SmolStr::new_static("alg"), + LexObjectProperty::String(LexString { + description: Some(CowStr::new_static("Signing algorithm (ES256)")), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("kid"), + LexObjectProperty::String(LexString { + description: Some(CowStr::new_static( + "Key identifier for the signing key", + )), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("nonce"), + LexObjectProperty::String(LexString { + description: Some(CowStr::new_static( + "Unique random nonce to prevent replay", + )), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("sig"), + LexObjectProperty::String(LexString { + description: Some(CowStr::new_static( + "Base64-encoded ES256 signature", + )), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("signedAt"), + LexObjectProperty::String(LexString { + description: Some(CowStr::new_static("When the record was signed")), + format: Some(LexStringFormat::Datetime), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("version"), + LexObjectProperty::Integer(LexInteger { + ..Default::default() + }), + ); + map + }, + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("deviceProgress"), + LexUserType::Object(LexObject { + description: Some( + CowStr::new_static( + "Per-device progress bucket. Buckets are summed across devices (not max-merged) so in-app activity spread over multiple devices is fully counted.", + ), + ), + properties: { + #[allow(unused_mut)] + let mut map = BTreeMap::new(); + map.insert( + SmolStr::new_static("counts"), + LexObjectProperty::Ref(LexRef { + r#ref: CowStr::new_static("#heartbeatProgress"), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("deviceId"), + LexObjectProperty::String(LexString { + description: Some( + CowStr::new_static( + "Random per-install device id from userScopedStorage. No fingerprinting.", + ), + ), + ..Default::default() + }), + ); + map + }, + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("heartbeatLight"), + LexUserType::Object(LexObject { + description: Some(CowStr::new_static("Light state at heartbeat time")), + properties: { + #[allow(unused_mut)] + let mut map = BTreeMap::new(); + map.insert( + SmolStr::new_static("current"), + LexObjectProperty::Integer(LexInteger { + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("drainActive"), + LexObjectProperty::Boolean(LexBoolean { + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("drainRate"), + LexObjectProperty::Integer(LexInteger { + ..Default::default() + }), + ); + map + }, + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("heartbeatProgress"), + LexUserType::Object(LexObject { + description: Some(CowStr::new_static( + "Session progress counters at heartbeat time (per-device bucket contents)", + )), + properties: { + #[allow(unused_mut)] + let mut map = BTreeMap::new(); + map.insert( + SmolStr::new_static("itemsCount"), + LexObjectProperty::Integer(LexInteger { + minimum: Some(0i64), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("likesSent"), + LexObjectProperty::Integer(LexInteger { + minimum: Some(0i64), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("mothsSeenCount"), + LexObjectProperty::Integer(LexInteger { + minimum: Some(0i64), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("postsCreated"), + LexObjectProperty::Integer(LexInteger { + minimum: Some(0i64), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("postsRead"), + LexObjectProperty::Integer(LexInteger { + minimum: Some(0i64), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("repostsSent"), + LexObjectProperty::Integer(LexInteger { + minimum: Some(0i64), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("specimensCount"), + LexObjectProperty::Integer(LexInteger { + minimum: Some(0i64), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("xpGained"), + LexObjectProperty::Integer(LexInteger { + minimum: Some(0i64), + ..Default::default() + }), + ); + map + }, + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("main"), + LexUserType::Record(LexRecord { + description: Some( + CowStr::new_static( + "Walk record. Created with status 'active' at first engagement (first tracked action on the feed), kept current with putRecord, and updated to 'completed' when the walk closes (idle auto-close, light depletion, or a manual wrap-up). rkey is a TID. Walks are the everyday unit and are never numbered; identity is the record key and display identity is the walk's time. Tracks the full lifecycle of a walk including camps, gathered findings, light consumption, and conditions.", + ), + ), + key: Some(CowStr::new_static("tid")), + record: LexRecordRecord::Object(LexObject { + required: Some( + vec![ + SmolStr::new_static("status"), + SmolStr::new_static("signature"), + SmolStr::new_static("createdAt") + ], + ), + properties: { + #[allow(unused_mut)] + let mut map = BTreeMap::new(); + map.insert( + SmolStr::new_static("activeDuration"), + LexObjectProperty::Integer(LexInteger { + minimum: Some(0i64), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("campsCount"), + LexObjectProperty::Integer(LexInteger { + minimum: Some(0i64), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("closedBy"), + LexObjectProperty::String(LexString { + description: Some( + CowStr::new_static( + "How the walk closed. Known values: 'user' (manual 'that's enough for now' tap), 'auto' (idle auto-close after the inactivity window), and 'lamp' (light depleted). Free string with no enum so future close reasons need no lexicon change. Unset while the walk is active.", + ), + ), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("completedAt"), + LexObjectProperty::String(LexString { + description: Some( + CowStr::new_static( + "When the walk ended. For idle auto-closes this is the last tracked activity, clamped to be no earlier than startedAt.", + ), + ), + format: Some(LexStringFormat::Datetime), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("conditions"), + LexObjectProperty::Ref(LexRef { + r#ref: CowStr::new_static("#walkConditions"), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("createdAt"), + LexObjectProperty::String(LexString { + description: Some( + CowStr::new_static("When the record was created"), + ), + format: Some(LexStringFormat::Datetime), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("duration"), + LexObjectProperty::Integer(LexInteger { + minimum: Some(0i64), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("elsewhereActivity"), + LexObjectProperty::Ref(LexRef { + r#ref: CowStr::new_static("#walkElsewhereActivity"), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("findings"), + LexObjectProperty::Ref(LexRef { + r#ref: CowStr::new_static("#walkFindings"), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("heartbeat"), + LexObjectProperty::Ref(LexRef { + r#ref: CowStr::new_static("#walkHeartbeat"), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("light"), + LexObjectProperty::Ref(LexRef { + r#ref: CowStr::new_static("#walkLight"), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("restDuration"), + LexObjectProperty::Integer(LexInteger { + minimum: Some(0i64), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("signature"), + LexObjectProperty::Ref(LexRef { + r#ref: CowStr::new_static("#chronicleSignature"), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("startedAt"), + LexObjectProperty::String(LexString { + description: Some( + CowStr::new_static( + "When the walk started (first engagement)", + ), + ), + format: Some(LexStringFormat::Datetime), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("status"), + LexObjectProperty::String(LexString { + description: Some( + CowStr::new_static( + "Current walk status. A walk is 'active' while open and 'completed' once it closes; there is no 'abandoned' state because a walk never fails.", + ), + ), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("updatedAt"), + LexObjectProperty::String(LexString { + description: Some( + CowStr::new_static("When the record was last updated"), + ), + format: Some(LexStringFormat::Datetime), + ..Default::default() + }), + ); + map + }, + ..Default::default() + }), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("walkConditions"), + LexUserType::Object(LexObject { + description: Some(CowStr::new_static( + "Environmental conditions during the walk", + )), + properties: { + #[allow(unused_mut)] + let mut map = BTreeMap::new(); + map.insert( + SmolStr::new_static("biome"), + LexObjectProperty::String(LexString { + description: Some(CowStr::new_static("Forest biome type")), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("lightLevel"), + LexObjectProperty::String(LexString { + description: Some(CowStr::new_static( + "Time-of-day light condition at walk start", + )), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("moonPhase"), + LexObjectProperty::String(LexString { + description: Some(CowStr::new_static( + "Moon phase condition (nighttime only)", + )), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("userState"), + LexObjectProperty::String(LexString { + description: Some(CowStr::new_static( + "User fatigue state at walk start", + )), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("weather"), + LexObjectProperty::String(LexString { + description: Some(CowStr::new_static( + "Weather condition during the walk", + )), + ..Default::default() + }), + ); + map + }, + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("walkElsewhereActivity"), + LexUserType::Object(LexObject { + description: Some( + CowStr::new_static( + "Cross-client activity during the walk window that did NOT happen in anisota: the PDS scan of app.bsky posts/likes/reposts in the walk window minus the in-app per-device summed totals, floored at 0 per field. Because likes and reposts carry no client marker this is a subtraction estimate, so the elsewhere panel labels it 'at least'. This block NEVER earns XP or findings; it is data for the panel only. Optional; unset when there was no elsewhere activity or the scan was unavailable.", + ), + ), + properties: { + #[allow(unused_mut)] + let mut map = BTreeMap::new(); + map.insert( + SmolStr::new_static("likesSent"), + LexObjectProperty::Integer(LexInteger { + minimum: Some(0i64), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("postsCreated"), + LexObjectProperty::Integer(LexInteger { + minimum: Some(0i64), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("repostsSent"), + LexObjectProperty::Integer(LexInteger { + minimum: Some(0i64), + ..Default::default() + }), + ); + map + }, + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("walkFindings"), + LexUserType::Object(LexObject { + description: Some(CowStr::new_static( + "What was found/gathered during the walk", + )), + properties: { + #[allow(unused_mut)] + let mut map = BTreeMap::new(); + map.insert( + SmolStr::new_static("itemsCollected"), + LexObjectProperty::Integer(LexInteger { + minimum: Some(0i64), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("likesSent"), + LexObjectProperty::Integer(LexInteger { + minimum: Some(0i64), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("mothsSeen"), + LexObjectProperty::Integer(LexInteger { + minimum: Some(0i64), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("postsCreated"), + LexObjectProperty::Integer(LexInteger { + minimum: Some(0i64), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("postsRead"), + LexObjectProperty::Integer(LexInteger { + minimum: Some(0i64), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("repostsSent"), + LexObjectProperty::Integer(LexInteger { + minimum: Some(0i64), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("specimensFound"), + LexObjectProperty::Integer(LexInteger { + minimum: Some(0i64), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("xpGained"), + LexObjectProperty::Integer(LexInteger { + minimum: Some(0i64), + ..Default::default() + }), + ); + map + }, + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("walkHeartbeat"), + LexUserType::Object(LexObject { + description: Some( + CowStr::new_static( + "Periodic snapshot of walk progress for cross-device sync", + ), + ), + properties: { + #[allow(unused_mut)] + let mut map = BTreeMap::new(); + map.insert( + SmolStr::new_static("lastActivityAt"), + LexObjectProperty::String(LexString { + description: Some( + CowStr::new_static( + "Timestamp of the last tracked activity. Drives the idle clock and is max-merged across devices (heartbeats themselves fire on a timer, so idle detection must key on this field, not updatedAt).", + ), + ), + format: Some(LexStringFormat::Datetime), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("light"), + LexObjectProperty::Ref(LexRef { + r#ref: CowStr::new_static("#heartbeatLight"), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("progress"), + LexObjectProperty::Array(LexArray { + description: Some( + CowStr::new_static( + "Per-device progress buckets, one entry per device that has contributed to this walk. In-app totals are the SUM across buckets, not a max-merge: per-device buckets exist deliberately so multi-device in-app activity is never undercounted (an undercount would falsely inflate the elsewhere figure).", + ), + ), + items: LexArrayItem::Ref(LexRef { + r#ref: CowStr::new_static("#deviceProgress"), + ..Default::default() + }), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("updatedAt"), + LexObjectProperty::String(LexString { + description: Some( + CowStr::new_static("When this heartbeat was written"), + ), + format: Some(LexStringFormat::Datetime), + ..Default::default() + }), + ); + map + }, + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("walkLight"), + LexUserType::Object(LexObject { + description: Some(CowStr::new_static("Light resource tracking for the walk")), + properties: { + #[allow(unused_mut)] + let mut map = BTreeMap::new(); + map.insert( + SmolStr::new_static("atEnd"), + LexObjectProperty::Integer(LexInteger { + minimum: Some(0i64), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("atStart"), + LexObjectProperty::Integer(LexInteger { + minimum: Some(0i64), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("consumed"), + LexObjectProperty::Integer(LexInteger { + minimum: Some(0i64), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("drainRate"), + LexObjectProperty::Integer(LexInteger { + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("regenerated"), + LexObjectProperty::Integer(LexInteger { + minimum: Some(0i64), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("status"), + LexObjectProperty::String(LexString { + description: Some(CowStr::new_static( + "Light status at start of the walk", + )), + ..Default::default() + }), + ); + map + }, + ..Default::default() + }), + ); + map + }, + ..Default::default() + } +} + +pub mod walk_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 Signature; + type Status; + } + /// Empty state - all required fields are unset + pub struct Empty(()); + impl sealed::Sealed for Empty {} + impl State for Empty { + type CreatedAt = Unset; + type Signature = Unset; + type Status = 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 Signature = St::Signature; + type Status = St::Status; + } + ///State transition - sets the `signature` field to Set + pub struct SetSignature(PhantomData St>); + impl sealed::Sealed for SetSignature {} + impl State for SetSignature { + type CreatedAt = St::CreatedAt; + type Signature = Set; + type Status = St::Status; + } + ///State transition - sets the `status` field to Set + pub struct SetStatus(PhantomData St>); + impl sealed::Sealed for SetStatus {} + impl State for SetStatus { + type CreatedAt = St::CreatedAt; + type Signature = St::Signature; + type Status = 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 `signature` field + pub struct signature(()); + ///Marker type for the `status` field + pub struct status(()); + } +} + +/// Builder for constructing an instance of this type. +pub struct WalkBuilder { + _state: PhantomData St>, + _fields: ( + Option, + Option, + Option, + Option, + Option>, + Option, + Option, + Option>, + Option>, + Option>, + Option>, + Option, + Option>, + Option, + Option, + Option, + ), + _type: PhantomData S>, +} + +impl Walk { + /// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed + pub fn new() -> WalkBuilder { + WalkBuilder::new() + } +} + +impl Walk { + /// Create a new builder for this type + pub fn builder() -> WalkBuilder { + WalkBuilder::builder() + } +} + +impl WalkBuilder { + /// Create a new builder with all fields unset, using the default string type, if needed + pub fn new() -> Self { + WalkBuilder { + _state: PhantomData, + _fields: ( + None, None, None, None, None, None, None, None, None, None, None, None, None, None, + None, None, + ), + _type: PhantomData, + } + } +} + +impl WalkBuilder { + /// Create a new builder with all fields unset + pub fn builder() -> Self { + WalkBuilder { + _state: PhantomData, + _fields: ( + None, None, None, None, None, None, None, None, None, None, None, None, None, None, + None, None, + ), + _type: PhantomData, + } + } +} + +impl WalkBuilder { + /// Set the `activeDuration` field (optional) + pub fn active_duration(mut self, value: impl Into>) -> Self { + self._fields.0 = value.into(); + self + } + /// Set the `activeDuration` field to an Option value (optional) + pub fn maybe_active_duration(mut self, value: Option) -> Self { + self._fields.0 = value; + self + } +} + +impl WalkBuilder { + /// Set the `campsCount` field (optional) + pub fn camps_count(mut self, value: impl Into>) -> Self { + self._fields.1 = value.into(); + self + } + /// Set the `campsCount` field to an Option value (optional) + pub fn maybe_camps_count(mut self, value: Option) -> Self { + self._fields.1 = value; + self + } +} + +impl WalkBuilder { + /// Set the `closedBy` field (optional) + pub fn closed_by(mut self, value: impl Into>) -> Self { + self._fields.2 = value.into(); + self + } + /// Set the `closedBy` field to an Option value (optional) + pub fn maybe_closed_by(mut self, value: Option) -> Self { + self._fields.2 = value; + self + } +} + +impl WalkBuilder { + /// Set the `completedAt` field (optional) + pub fn completed_at(mut self, value: impl Into>) -> Self { + self._fields.3 = value.into(); + self + } + /// Set the `completedAt` field to an Option value (optional) + pub fn maybe_completed_at(mut self, value: Option) -> Self { + self._fields.3 = value; + self + } +} + +impl WalkBuilder { + /// Set the `conditions` field (optional) + pub fn conditions(mut self, value: impl Into>>) -> Self { + self._fields.4 = value.into(); + self + } + /// Set the `conditions` field to an Option value (optional) + pub fn maybe_conditions(mut self, value: Option>) -> Self { + self._fields.4 = value; + self + } +} + +impl WalkBuilder +where + St: walk_state::State, + St::CreatedAt: walk_state::IsUnset, +{ + /// Set the `createdAt` field (required) + pub fn created_at( + mut self, + value: impl Into, + ) -> WalkBuilder, S> { + self._fields.5 = Option::Some(value.into()); + WalkBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl WalkBuilder { + /// Set the `duration` field (optional) + pub fn duration(mut self, value: impl Into>) -> Self { + self._fields.6 = value.into(); + self + } + /// Set the `duration` field to an Option value (optional) + pub fn maybe_duration(mut self, value: Option) -> Self { + self._fields.6 = value; + self + } +} + +impl WalkBuilder { + /// Set the `elsewhereActivity` field (optional) + pub fn elsewhere_activity( + mut self, + value: impl Into>>, + ) -> Self { + self._fields.7 = value.into(); + self + } + /// Set the `elsewhereActivity` field to an Option value (optional) + pub fn maybe_elsewhere_activity( + mut self, + value: Option>, + ) -> Self { + self._fields.7 = value; + self + } +} + +impl WalkBuilder { + /// Set the `findings` field (optional) + pub fn findings(mut self, value: impl Into>>) -> Self { + self._fields.8 = value.into(); + self + } + /// Set the `findings` field to an Option value (optional) + pub fn maybe_findings(mut self, value: Option>) -> Self { + self._fields.8 = value; + self + } +} + +impl WalkBuilder { + /// Set the `heartbeat` field (optional) + pub fn heartbeat(mut self, value: impl Into>>) -> Self { + self._fields.9 = value.into(); + self + } + /// Set the `heartbeat` field to an Option value (optional) + pub fn maybe_heartbeat(mut self, value: Option>) -> Self { + self._fields.9 = value; + self + } +} + +impl WalkBuilder { + /// Set the `light` field (optional) + pub fn light(mut self, value: impl Into>>) -> Self { + self._fields.10 = value.into(); + self + } + /// Set the `light` field to an Option value (optional) + pub fn maybe_light(mut self, value: Option>) -> Self { + self._fields.10 = value; + self + } +} + +impl WalkBuilder { + /// Set the `restDuration` field (optional) + pub fn rest_duration(mut self, value: impl Into>) -> Self { + self._fields.11 = value.into(); + self + } + /// Set the `restDuration` field to an Option value (optional) + pub fn maybe_rest_duration(mut self, value: Option) -> Self { + self._fields.11 = value; + self + } +} + +impl WalkBuilder +where + St: walk_state::State, + St::Signature: walk_state::IsUnset, +{ + /// Set the `signature` field (required) + pub fn signature( + mut self, + value: impl Into>, + ) -> WalkBuilder, S> { + self._fields.12 = Option::Some(value.into()); + WalkBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl WalkBuilder { + /// Set the `startedAt` field (optional) + pub fn started_at(mut self, value: impl Into>) -> Self { + self._fields.13 = value.into(); + self + } + /// Set the `startedAt` field to an Option value (optional) + pub fn maybe_started_at(mut self, value: Option) -> Self { + self._fields.13 = value; + self + } +} + +impl WalkBuilder +where + St: walk_state::State, + St::Status: walk_state::IsUnset, +{ + /// Set the `status` field (required) + pub fn status(mut self, value: impl Into) -> WalkBuilder, S> { + self._fields.14 = Option::Some(value.into()); + WalkBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl WalkBuilder { + /// Set the `updatedAt` field (optional) + pub fn updated_at(mut self, value: impl Into>) -> Self { + self._fields.15 = value.into(); + self + } + /// Set the `updatedAt` field to an Option value (optional) + pub fn maybe_updated_at(mut self, value: Option) -> Self { + self._fields.15 = value; + self + } +} + +impl WalkBuilder +where + St: walk_state::State, + St::CreatedAt: walk_state::IsSet, + St::Signature: walk_state::IsSet, + St::Status: walk_state::IsSet, +{ + /// Build the final struct. + pub fn build(self) -> Walk { + Walk { + active_duration: self._fields.0, + camps_count: self._fields.1, + closed_by: self._fields.2, + completed_at: self._fields.3, + conditions: self._fields.4, + created_at: self._fields.5.unwrap(), + duration: self._fields.6, + elsewhere_activity: self._fields.7, + findings: self._fields.8, + heartbeat: self._fields.9, + light: self._fields.10, + rest_duration: self._fields.11, + signature: self._fields.12.unwrap(), + started_at: self._fields.13, + status: self._fields.14.unwrap(), + updated_at: self._fields.15, + extra_data: Default::default(), + } + } + /// Build the final struct with custom extra_data. + pub fn build_with_data(self, extra_data: BTreeMap>) -> Walk { + Walk { + active_duration: self._fields.0, + camps_count: self._fields.1, + closed_by: self._fields.2, + completed_at: self._fields.3, + conditions: self._fields.4, + created_at: self._fields.5.unwrap(), + duration: self._fields.6, + elsewhere_activity: self._fields.7, + findings: self._fields.8, + heartbeat: self._fields.9, + light: self._fields.10, + rest_duration: self._fields.11, + signature: self._fields.12.unwrap(), + started_at: self._fields.13, + status: self._fields.14.unwrap(), + updated_at: self._fields.15, + extra_data: Some(extra_data), + } + } +} diff --git a/crates/jacquard-api/src/net_anisota/chronicle/walk/camp.rs b/crates/jacquard-api/src/net_anisota/chronicle/walk/camp.rs new file mode 100644 index 000000000..c9b78c309 --- /dev/null +++ b/crates/jacquard-api/src/net_anisota/chronicle/walk/camp.rs @@ -0,0 +1,1290 @@ +// @generated by jacquard-lexicon. DO NOT EDIT. +// +// Lexicon: net.anisota.chronicle.walk.camp +// +// 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; + +use crate::net_anisota::chronicle::walk::camp; +#[allow(unused_imports)] +use jacquard_lexicon::validation::{ConstraintError, ValidationPath}; +use serde::{Deserialize, Serialize}; +/// Environmental conditions when camp was made + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic, Default)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct CampConditions { + ///Time-of-day light condition when camp was made + #[serde(skip_serializing_if = "Option::is_none")] + pub light_level: Option, + ///Weather condition when camp was made + #[serde(skip_serializing_if = "Option::is_none")] + pub weather: Option, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +/// Light levels at camp start/end + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic, Default)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct CampLight { + ///Light level when camp was broken (in minutes) + #[serde(skip_serializing_if = "Option::is_none")] + pub at_break: Option, + ///Light level when camp was made (in minutes) + #[serde(skip_serializing_if = "Option::is_none")] + pub at_camp: Option, + ///Light regenerated during camp + #[serde(skip_serializing_if = "Option::is_none")] + pub regenerated: Option, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +/// ES256 cryptographic signature proving record authenticity + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct ChronicleSignature { + ///Signing algorithm (ES256) + pub alg: S, + ///Key identifier for the signing key + pub kid: S, + ///Unique random nonce to prevent replay + pub nonce: S, + ///Base64-encoded ES256 signature + pub sig: S, + ///When the record was signed + pub signed_at: Datetime, + ///Signature schema version + pub version: i64, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +/// Camp record. Created when a user makes camp during a walk. Updated when camp is broken. References the parent walk record via AT URI. + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + rename = "net.anisota.chronicle.walk.camp", + tag = "$type", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct Camp { + ///When camp was broken (only set when status is 'completed') + #[serde(skip_serializing_if = "Option::is_none")] + pub broke_at: Option, + ///Sequential camp number within the parent walk (1, 2, 3...) + #[serde(skip_serializing_if = "Option::is_none")] + pub camp_number: Option, + ///When camp was set up + pub camped_at: Datetime, + #[serde(skip_serializing_if = "Option::is_none")] + pub conditions: Option>, + ///When the record was created + pub created_at: Datetime, + ///Total camp duration in minutes (only set when status is 'completed'). Minutes throughout the walk system, unlike the legacy expedition camp lexicon's milliseconds. + #[serde(skip_serializing_if = "Option::is_none")] + pub duration: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub light: Option>, + ///Why camp was made + pub reason: S, + pub signature: camp::ChronicleSignature, + ///Whether the camp is currently active or has been broken + pub status: S, + ///When the record was last updated (set on break camp) + #[serde(skip_serializing_if = "Option::is_none")] + pub updated_at: Option, + ///AT URI of the parent walk record (net.anisota.chronicle.walk) + pub walk_ref: AtUri, + #[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 CampGetRecordOutput { + #[serde(skip_serializing_if = "Option::is_none")] + pub cid: Option>, + pub uri: AtUri, + pub value: Camp, +} + +impl Camp { + pub fn uri(uri: S) -> Result, UriError> { + RecordUri::try_from_uri(AtUri::new(uri)?) + } +} + +impl LexiconSchema for CampConditions { + fn nsid() -> &'static str { + "net.anisota.chronicle.walk.camp" + } + fn def_name() -> &'static str { + "campConditions" + } + fn lexicon_doc() -> LexiconDoc<'static> { + lexicon_doc_net_anisota_chronicle_walk_camp() + } + fn validate(&self) -> Result<(), ConstraintError> { + Ok(()) + } +} + +impl LexiconSchema for CampLight { + fn nsid() -> &'static str { + "net.anisota.chronicle.walk.camp" + } + fn def_name() -> &'static str { + "campLight" + } + fn lexicon_doc() -> LexiconDoc<'static> { + lexicon_doc_net_anisota_chronicle_walk_camp() + } + fn validate(&self) -> Result<(), ConstraintError> { + if let Some(ref value) = self.at_break { + if *value < 0i64 { + return Err(ConstraintError::Minimum { + path: ValidationPath::from_field("at_break"), + min: 0i64, + actual: *value, + }); + } + } + if let Some(ref value) = self.at_camp { + if *value < 0i64 { + return Err(ConstraintError::Minimum { + path: ValidationPath::from_field("at_camp"), + min: 0i64, + actual: *value, + }); + } + } + if let Some(ref value) = self.regenerated { + if *value < 0i64 { + return Err(ConstraintError::Minimum { + path: ValidationPath::from_field("regenerated"), + min: 0i64, + actual: *value, + }); + } + } + Ok(()) + } +} + +impl LexiconSchema for ChronicleSignature { + fn nsid() -> &'static str { + "net.anisota.chronicle.walk.camp" + } + fn def_name() -> &'static str { + "chronicleSignature" + } + fn lexicon_doc() -> LexiconDoc<'static> { + lexicon_doc_net_anisota_chronicle_walk_camp() + } + fn validate(&self) -> Result<(), ConstraintError> { + Ok(()) + } +} + +/// Marker type for deserializing records from this collection. + +#[derive(Debug, Serialize, Deserialize)] +pub struct CampRecord; +impl XrpcResp for CampRecord { + const NSID: &'static str = "net.anisota.chronicle.walk.camp"; + const ENCODING: &'static str = "application/json"; + type Output = CampGetRecordOutput; + type Err = RecordError; +} + +impl From> for Camp { + fn from(output: CampGetRecordOutput) -> Self { + output.value + } +} + +impl Collection for Camp { + const NSID: &'static str = "net.anisota.chronicle.walk.camp"; + type Record = CampRecord; +} + +impl Collection for CampRecord { + const NSID: &'static str = "net.anisota.chronicle.walk.camp"; + type Record = CampRecord; +} + +impl LexiconSchema for Camp { + fn nsid() -> &'static str { + "net.anisota.chronicle.walk.camp" + } + fn def_name() -> &'static str { + "main" + } + fn lexicon_doc() -> LexiconDoc<'static> { + lexicon_doc_net_anisota_chronicle_walk_camp() + } + fn validate(&self) -> Result<(), ConstraintError> { + if let Some(ref value) = self.camp_number { + if *value < 1i64 { + return Err(ConstraintError::Minimum { + path: ValidationPath::from_field("camp_number"), + min: 1i64, + actual: *value, + }); + } + } + if let Some(ref value) = self.duration { + if *value < 0i64 { + return Err(ConstraintError::Minimum { + path: ValidationPath::from_field("duration"), + min: 0i64, + actual: *value, + }); + } + } + Ok(()) + } +} + +fn lexicon_doc_net_anisota_chronicle_walk_camp() -> 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("net.anisota.chronicle.walk.camp"), + defs: { + let mut map = BTreeMap::new(); + map.insert( + SmolStr::new_static("campConditions"), + LexUserType::Object(LexObject { + description: Some(CowStr::new_static( + "Environmental conditions when camp was made", + )), + properties: { + #[allow(unused_mut)] + let mut map = BTreeMap::new(); + map.insert( + SmolStr::new_static("lightLevel"), + LexObjectProperty::String(LexString { + description: Some(CowStr::new_static( + "Time-of-day light condition when camp was made", + )), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("weather"), + LexObjectProperty::String(LexString { + description: Some(CowStr::new_static( + "Weather condition when camp was made", + )), + ..Default::default() + }), + ); + map + }, + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("campLight"), + LexUserType::Object(LexObject { + description: Some(CowStr::new_static("Light levels at camp start/end")), + properties: { + #[allow(unused_mut)] + let mut map = BTreeMap::new(); + map.insert( + SmolStr::new_static("atBreak"), + LexObjectProperty::Integer(LexInteger { + minimum: Some(0i64), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("atCamp"), + LexObjectProperty::Integer(LexInteger { + minimum: Some(0i64), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("regenerated"), + LexObjectProperty::Integer(LexInteger { + minimum: Some(0i64), + ..Default::default() + }), + ); + map + }, + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("chronicleSignature"), + LexUserType::Object(LexObject { + description: Some(CowStr::new_static( + "ES256 cryptographic signature proving record authenticity", + )), + required: Some(vec![ + SmolStr::new_static("sig"), + SmolStr::new_static("alg"), + SmolStr::new_static("kid"), + SmolStr::new_static("signedAt"), + SmolStr::new_static("nonce"), + SmolStr::new_static("version"), + ]), + properties: { + #[allow(unused_mut)] + let mut map = BTreeMap::new(); + map.insert( + SmolStr::new_static("alg"), + LexObjectProperty::String(LexString { + description: Some(CowStr::new_static("Signing algorithm (ES256)")), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("kid"), + LexObjectProperty::String(LexString { + description: Some(CowStr::new_static( + "Key identifier for the signing key", + )), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("nonce"), + LexObjectProperty::String(LexString { + description: Some(CowStr::new_static( + "Unique random nonce to prevent replay", + )), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("sig"), + LexObjectProperty::String(LexString { + description: Some(CowStr::new_static( + "Base64-encoded ES256 signature", + )), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("signedAt"), + LexObjectProperty::String(LexString { + description: Some(CowStr::new_static("When the record was signed")), + format: Some(LexStringFormat::Datetime), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("version"), + LexObjectProperty::Integer(LexInteger { + ..Default::default() + }), + ); + map + }, + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("main"), + LexUserType::Record(LexRecord { + description: Some( + CowStr::new_static( + "Camp record. Created when a user makes camp during a walk. Updated when camp is broken. References the parent walk record via AT URI.", + ), + ), + key: Some(CowStr::new_static("tid")), + record: LexRecordRecord::Object(LexObject { + required: Some( + vec![ + SmolStr::new_static("walkRef"), + SmolStr::new_static("status"), + SmolStr::new_static("campedAt"), + SmolStr::new_static("reason"), + SmolStr::new_static("signature"), + SmolStr::new_static("createdAt") + ], + ), + properties: { + #[allow(unused_mut)] + let mut map = BTreeMap::new(); + map.insert( + SmolStr::new_static("brokeAt"), + LexObjectProperty::String(LexString { + description: Some( + CowStr::new_static( + "When camp was broken (only set when status is 'completed')", + ), + ), + format: Some(LexStringFormat::Datetime), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("campNumber"), + LexObjectProperty::Integer(LexInteger { + minimum: Some(1i64), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("campedAt"), + LexObjectProperty::String(LexString { + description: Some( + CowStr::new_static("When camp was set up"), + ), + format: Some(LexStringFormat::Datetime), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("conditions"), + LexObjectProperty::Ref(LexRef { + r#ref: CowStr::new_static("#campConditions"), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("createdAt"), + LexObjectProperty::String(LexString { + description: Some( + CowStr::new_static("When the record was created"), + ), + format: Some(LexStringFormat::Datetime), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("duration"), + LexObjectProperty::Integer(LexInteger { + minimum: Some(0i64), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("light"), + LexObjectProperty::Ref(LexRef { + r#ref: CowStr::new_static("#campLight"), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("reason"), + LexObjectProperty::String(LexString { + description: Some(CowStr::new_static("Why camp was made")), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("signature"), + LexObjectProperty::Ref(LexRef { + r#ref: CowStr::new_static("#chronicleSignature"), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("status"), + LexObjectProperty::String(LexString { + description: Some( + CowStr::new_static( + "Whether the camp is currently active or has been broken", + ), + ), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("updatedAt"), + LexObjectProperty::String(LexString { + description: Some( + CowStr::new_static( + "When the record was last updated (set on break camp)", + ), + ), + format: Some(LexStringFormat::Datetime), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("walkRef"), + LexObjectProperty::String(LexString { + description: Some( + CowStr::new_static( + "AT URI of the parent walk record (net.anisota.chronicle.walk)", + ), + ), + format: Some(LexStringFormat::AtUri), + ..Default::default() + }), + ); + map + }, + ..Default::default() + }), + ..Default::default() + }), + ); + map + }, + ..Default::default() + } +} + +pub mod chronicle_signature_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 Alg; + type Kid; + type Nonce; + type Sig; + type SignedAt; + type Version; + } + /// Empty state - all required fields are unset + pub struct Empty(()); + impl sealed::Sealed for Empty {} + impl State for Empty { + type Alg = Unset; + type Kid = Unset; + type Nonce = Unset; + type Sig = Unset; + type SignedAt = Unset; + type Version = Unset; + } + ///State transition - sets the `alg` field to Set + pub struct SetAlg(PhantomData St>); + impl sealed::Sealed for SetAlg {} + impl State for SetAlg { + type Alg = Set; + type Kid = St::Kid; + type Nonce = St::Nonce; + type Sig = St::Sig; + type SignedAt = St::SignedAt; + type Version = St::Version; + } + ///State transition - sets the `kid` field to Set + pub struct SetKid(PhantomData St>); + impl sealed::Sealed for SetKid {} + impl State for SetKid { + type Alg = St::Alg; + type Kid = Set; + type Nonce = St::Nonce; + type Sig = St::Sig; + type SignedAt = St::SignedAt; + type Version = St::Version; + } + ///State transition - sets the `nonce` field to Set + pub struct SetNonce(PhantomData St>); + impl sealed::Sealed for SetNonce {} + impl State for SetNonce { + type Alg = St::Alg; + type Kid = St::Kid; + type Nonce = Set; + type Sig = St::Sig; + type SignedAt = St::SignedAt; + type Version = St::Version; + } + ///State transition - sets the `sig` field to Set + pub struct SetSig(PhantomData St>); + impl sealed::Sealed for SetSig {} + impl State for SetSig { + type Alg = St::Alg; + type Kid = St::Kid; + type Nonce = St::Nonce; + type Sig = Set; + type SignedAt = St::SignedAt; + type Version = St::Version; + } + ///State transition - sets the `signed_at` field to Set + pub struct SetSignedAt(PhantomData St>); + impl sealed::Sealed for SetSignedAt {} + impl State for SetSignedAt { + type Alg = St::Alg; + type Kid = St::Kid; + type Nonce = St::Nonce; + type Sig = St::Sig; + type SignedAt = Set; + type Version = St::Version; + } + ///State transition - sets the `version` field to Set + pub struct SetVersion(PhantomData St>); + impl sealed::Sealed for SetVersion {} + impl State for SetVersion { + type Alg = St::Alg; + type Kid = St::Kid; + type Nonce = St::Nonce; + type Sig = St::Sig; + type SignedAt = St::SignedAt; + type Version = Set; + } + /// Marker types for field names + #[allow(non_camel_case_types)] + pub mod members { + ///Marker type for the `alg` field + pub struct alg(()); + ///Marker type for the `kid` field + pub struct kid(()); + ///Marker type for the `nonce` field + pub struct nonce(()); + ///Marker type for the `sig` field + pub struct sig(()); + ///Marker type for the `signed_at` field + pub struct signed_at(()); + ///Marker type for the `version` field + pub struct version(()); + } +} + +/// Builder for constructing an instance of this type. +pub struct ChronicleSignatureBuilder { + _state: PhantomData St>, + _fields: ( + Option, + Option, + Option, + Option, + Option, + Option, + ), + _type: PhantomData S>, +} + +impl ChronicleSignature { + /// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed + pub fn new() -> ChronicleSignatureBuilder { + ChronicleSignatureBuilder::new() + } +} + +impl ChronicleSignature { + /// Create a new builder for this type + pub fn builder() -> ChronicleSignatureBuilder { + ChronicleSignatureBuilder::builder() + } +} + +impl ChronicleSignatureBuilder { + /// Create a new builder with all fields unset, using the default string type, if needed + pub fn new() -> Self { + ChronicleSignatureBuilder { + _state: PhantomData, + _fields: (None, None, None, None, None, None), + _type: PhantomData, + } + } +} + +impl ChronicleSignatureBuilder { + /// Create a new builder with all fields unset + pub fn builder() -> Self { + ChronicleSignatureBuilder { + _state: PhantomData, + _fields: (None, None, None, None, None, None), + _type: PhantomData, + } + } +} + +impl ChronicleSignatureBuilder +where + St: chronicle_signature_state::State, + St::Alg: chronicle_signature_state::IsUnset, +{ + /// Set the `alg` field (required) + pub fn alg( + mut self, + value: impl Into, + ) -> ChronicleSignatureBuilder, S> { + self._fields.0 = Option::Some(value.into()); + ChronicleSignatureBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl ChronicleSignatureBuilder +where + St: chronicle_signature_state::State, + St::Kid: chronicle_signature_state::IsUnset, +{ + /// Set the `kid` field (required) + pub fn kid( + mut self, + value: impl Into, + ) -> ChronicleSignatureBuilder, S> { + self._fields.1 = Option::Some(value.into()); + ChronicleSignatureBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl ChronicleSignatureBuilder +where + St: chronicle_signature_state::State, + St::Nonce: chronicle_signature_state::IsUnset, +{ + /// Set the `nonce` field (required) + pub fn nonce( + mut self, + value: impl Into, + ) -> ChronicleSignatureBuilder, S> { + self._fields.2 = Option::Some(value.into()); + ChronicleSignatureBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl ChronicleSignatureBuilder +where + St: chronicle_signature_state::State, + St::Sig: chronicle_signature_state::IsUnset, +{ + /// Set the `sig` field (required) + pub fn sig( + mut self, + value: impl Into, + ) -> ChronicleSignatureBuilder, S> { + self._fields.3 = Option::Some(value.into()); + ChronicleSignatureBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl ChronicleSignatureBuilder +where + St: chronicle_signature_state::State, + St::SignedAt: chronicle_signature_state::IsUnset, +{ + /// Set the `signedAt` field (required) + pub fn signed_at( + mut self, + value: impl Into, + ) -> ChronicleSignatureBuilder, S> { + self._fields.4 = Option::Some(value.into()); + ChronicleSignatureBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl ChronicleSignatureBuilder +where + St: chronicle_signature_state::State, + St::Version: chronicle_signature_state::IsUnset, +{ + /// Set the `version` field (required) + pub fn version( + mut self, + value: impl Into, + ) -> ChronicleSignatureBuilder, S> { + self._fields.5 = Option::Some(value.into()); + ChronicleSignatureBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl ChronicleSignatureBuilder +where + St: chronicle_signature_state::State, + St::Alg: chronicle_signature_state::IsSet, + St::Kid: chronicle_signature_state::IsSet, + St::Nonce: chronicle_signature_state::IsSet, + St::Sig: chronicle_signature_state::IsSet, + St::SignedAt: chronicle_signature_state::IsSet, + St::Version: chronicle_signature_state::IsSet, +{ + /// Build the final struct. + pub fn build(self) -> ChronicleSignature { + ChronicleSignature { + alg: self._fields.0.unwrap(), + kid: self._fields.1.unwrap(), + nonce: self._fields.2.unwrap(), + sig: self._fields.3.unwrap(), + signed_at: self._fields.4.unwrap(), + version: self._fields.5.unwrap(), + extra_data: Default::default(), + } + } + /// Build the final struct with custom extra_data. + pub fn build_with_data(self, extra_data: BTreeMap>) -> ChronicleSignature { + ChronicleSignature { + alg: self._fields.0.unwrap(), + kid: self._fields.1.unwrap(), + nonce: self._fields.2.unwrap(), + sig: self._fields.3.unwrap(), + signed_at: self._fields.4.unwrap(), + version: self._fields.5.unwrap(), + extra_data: Some(extra_data), + } + } +} + +pub mod camp_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 CampedAt; + type CreatedAt; + type Reason; + type Signature; + type Status; + type WalkRef; + } + /// Empty state - all required fields are unset + pub struct Empty(()); + impl sealed::Sealed for Empty {} + impl State for Empty { + type CampedAt = Unset; + type CreatedAt = Unset; + type Reason = Unset; + type Signature = Unset; + type Status = Unset; + type WalkRef = Unset; + } + ///State transition - sets the `camped_at` field to Set + pub struct SetCampedAt(PhantomData St>); + impl sealed::Sealed for SetCampedAt {} + impl State for SetCampedAt { + type CampedAt = Set; + type CreatedAt = St::CreatedAt; + type Reason = St::Reason; + type Signature = St::Signature; + type Status = St::Status; + type WalkRef = St::WalkRef; + } + ///State transition - sets the `created_at` field to Set + pub struct SetCreatedAt(PhantomData St>); + impl sealed::Sealed for SetCreatedAt {} + impl State for SetCreatedAt { + type CampedAt = St::CampedAt; + type CreatedAt = Set; + type Reason = St::Reason; + type Signature = St::Signature; + type Status = St::Status; + type WalkRef = St::WalkRef; + } + ///State transition - sets the `reason` field to Set + pub struct SetReason(PhantomData St>); + impl sealed::Sealed for SetReason {} + impl State for SetReason { + type CampedAt = St::CampedAt; + type CreatedAt = St::CreatedAt; + type Reason = Set; + type Signature = St::Signature; + type Status = St::Status; + type WalkRef = St::WalkRef; + } + ///State transition - sets the `signature` field to Set + pub struct SetSignature(PhantomData St>); + impl sealed::Sealed for SetSignature {} + impl State for SetSignature { + type CampedAt = St::CampedAt; + type CreatedAt = St::CreatedAt; + type Reason = St::Reason; + type Signature = Set; + type Status = St::Status; + type WalkRef = St::WalkRef; + } + ///State transition - sets the `status` field to Set + pub struct SetStatus(PhantomData St>); + impl sealed::Sealed for SetStatus {} + impl State for SetStatus { + type CampedAt = St::CampedAt; + type CreatedAt = St::CreatedAt; + type Reason = St::Reason; + type Signature = St::Signature; + type Status = Set; + type WalkRef = St::WalkRef; + } + ///State transition - sets the `walk_ref` field to Set + pub struct SetWalkRef(PhantomData St>); + impl sealed::Sealed for SetWalkRef {} + impl State for SetWalkRef { + type CampedAt = St::CampedAt; + type CreatedAt = St::CreatedAt; + type Reason = St::Reason; + type Signature = St::Signature; + type Status = St::Status; + type WalkRef = Set; + } + /// Marker types for field names + #[allow(non_camel_case_types)] + pub mod members { + ///Marker type for the `camped_at` field + pub struct camped_at(()); + ///Marker type for the `created_at` field + pub struct created_at(()); + ///Marker type for the `reason` field + pub struct reason(()); + ///Marker type for the `signature` field + pub struct signature(()); + ///Marker type for the `status` field + pub struct status(()); + ///Marker type for the `walk_ref` field + pub struct walk_ref(()); + } +} + +/// Builder for constructing an instance of this type. +pub struct CampBuilder { + _state: PhantomData St>, + _fields: ( + Option, + Option, + Option, + Option>, + Option, + Option, + Option>, + Option, + Option>, + Option, + Option, + Option>, + ), + _type: PhantomData S>, +} + +impl Camp { + /// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed + pub fn new() -> CampBuilder { + CampBuilder::new() + } +} + +impl Camp { + /// Create a new builder for this type + pub fn builder() -> CampBuilder { + CampBuilder::builder() + } +} + +impl CampBuilder { + /// Create a new builder with all fields unset, using the default string type, if needed + pub fn new() -> Self { + CampBuilder { + _state: PhantomData, + _fields: ( + None, None, None, None, None, None, None, None, None, None, None, None, + ), + _type: PhantomData, + } + } +} + +impl CampBuilder { + /// Create a new builder with all fields unset + pub fn builder() -> Self { + CampBuilder { + _state: PhantomData, + _fields: ( + None, None, None, None, None, None, None, None, None, None, None, None, + ), + _type: PhantomData, + } + } +} + +impl CampBuilder { + /// Set the `brokeAt` field (optional) + pub fn broke_at(mut self, value: impl Into>) -> Self { + self._fields.0 = value.into(); + self + } + /// Set the `brokeAt` field to an Option value (optional) + pub fn maybe_broke_at(mut self, value: Option) -> Self { + self._fields.0 = value; + self + } +} + +impl CampBuilder { + /// Set the `campNumber` field (optional) + pub fn camp_number(mut self, value: impl Into>) -> Self { + self._fields.1 = value.into(); + self + } + /// Set the `campNumber` field to an Option value (optional) + pub fn maybe_camp_number(mut self, value: Option) -> Self { + self._fields.1 = value; + self + } +} + +impl CampBuilder +where + St: camp_state::State, + St::CampedAt: camp_state::IsUnset, +{ + /// Set the `campedAt` field (required) + pub fn camped_at( + mut self, + value: impl Into, + ) -> CampBuilder, S> { + self._fields.2 = Option::Some(value.into()); + CampBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl CampBuilder { + /// Set the `conditions` field (optional) + pub fn conditions(mut self, value: impl Into>>) -> Self { + self._fields.3 = value.into(); + self + } + /// Set the `conditions` field to an Option value (optional) + pub fn maybe_conditions(mut self, value: Option>) -> Self { + self._fields.3 = value; + self + } +} + +impl CampBuilder +where + St: camp_state::State, + St::CreatedAt: camp_state::IsUnset, +{ + /// Set the `createdAt` field (required) + pub fn created_at( + mut self, + value: impl Into, + ) -> CampBuilder, S> { + self._fields.4 = Option::Some(value.into()); + CampBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl CampBuilder { + /// Set the `duration` field (optional) + pub fn duration(mut self, value: impl Into>) -> Self { + self._fields.5 = value.into(); + self + } + /// Set the `duration` field to an Option value (optional) + pub fn maybe_duration(mut self, value: Option) -> Self { + self._fields.5 = value; + self + } +} + +impl CampBuilder { + /// Set the `light` field (optional) + pub fn light(mut self, value: impl Into>>) -> Self { + self._fields.6 = value.into(); + self + } + /// Set the `light` field to an Option value (optional) + pub fn maybe_light(mut self, value: Option>) -> Self { + self._fields.6 = value; + self + } +} + +impl CampBuilder +where + St: camp_state::State, + St::Reason: camp_state::IsUnset, +{ + /// Set the `reason` field (required) + pub fn reason(mut self, value: impl Into) -> CampBuilder, S> { + self._fields.7 = Option::Some(value.into()); + CampBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl CampBuilder +where + St: camp_state::State, + St::Signature: camp_state::IsUnset, +{ + /// Set the `signature` field (required) + pub fn signature( + mut self, + value: impl Into>, + ) -> CampBuilder, S> { + self._fields.8 = Option::Some(value.into()); + CampBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl CampBuilder +where + St: camp_state::State, + St::Status: camp_state::IsUnset, +{ + /// Set the `status` field (required) + pub fn status(mut self, value: impl Into) -> CampBuilder, S> { + self._fields.9 = Option::Some(value.into()); + CampBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl CampBuilder { + /// Set the `updatedAt` field (optional) + pub fn updated_at(mut self, value: impl Into>) -> Self { + self._fields.10 = value.into(); + self + } + /// Set the `updatedAt` field to an Option value (optional) + pub fn maybe_updated_at(mut self, value: Option) -> Self { + self._fields.10 = value; + self + } +} + +impl CampBuilder +where + St: camp_state::State, + St::WalkRef: camp_state::IsUnset, +{ + /// Set the `walkRef` field (required) + pub fn walk_ref( + mut self, + value: impl Into>, + ) -> CampBuilder, S> { + self._fields.11 = Option::Some(value.into()); + CampBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl CampBuilder +where + St: camp_state::State, + St::CampedAt: camp_state::IsSet, + St::CreatedAt: camp_state::IsSet, + St::Reason: camp_state::IsSet, + St::Signature: camp_state::IsSet, + St::Status: camp_state::IsSet, + St::WalkRef: camp_state::IsSet, +{ + /// Build the final struct. + pub fn build(self) -> Camp { + Camp { + broke_at: self._fields.0, + camp_number: self._fields.1, + camped_at: self._fields.2.unwrap(), + conditions: self._fields.3, + created_at: self._fields.4.unwrap(), + duration: self._fields.5, + light: self._fields.6, + reason: self._fields.7.unwrap(), + signature: self._fields.8.unwrap(), + status: self._fields.9.unwrap(), + updated_at: self._fields.10, + walk_ref: self._fields.11.unwrap(), + extra_data: Default::default(), + } + } + /// Build the final struct with custom extra_data. + pub fn build_with_data(self, extra_data: BTreeMap>) -> Camp { + Camp { + broke_at: self._fields.0, + camp_number: self._fields.1, + camped_at: self._fields.2.unwrap(), + conditions: self._fields.3, + created_at: self._fields.4.unwrap(), + duration: self._fields.5, + light: self._fields.6, + reason: self._fields.7.unwrap(), + signature: self._fields.8.unwrap(), + status: self._fields.9.unwrap(), + updated_at: self._fields.10, + walk_ref: self._fields.11.unwrap(), + extra_data: Some(extra_data), + } + } +} diff --git a/crates/jacquard-api/src/net_anisota/feed/draft.rs b/crates/jacquard-api/src/net_anisota/feed/draft.rs index 01d943fe6..990590e47 100644 --- a/crates/jacquard-api/src/net_anisota/feed/draft.rs +++ b/crates/jacquard-api/src/net_anisota/feed/draft.rs @@ -179,6 +179,32 @@ impl LexiconSchema for Draft { }); } } + if let Some(values) = &self.tags { + for value in values { + #[allow(unused_comparisons)] + if ::len(value.as_ref()) > 640usize { + return Err(ConstraintError::MaxLength { + path: ValidationPath::from_field("tags"), + max: 640usize, + actual: ::len(value.as_ref()), + }); + } + } + } + if let Some(values) = &self.tags { + for value in values { + { + let count = UnicodeSegmentation::graphemes(value.as_ref(), true).count(); + if count > 64usize { + return Err(ConstraintError::MaxGraphemes { + path: ValidationPath::from_field("tags"), + max: 64usize, + actual: count, + }); + } + } + } + } { let value = &self.text; #[allow(unused_comparisons)] diff --git a/crates/jacquard-api/src/net_anisota/feed/list.rs b/crates/jacquard-api/src/net_anisota/feed/list.rs index 1ba8bda77..c1509693b 100644 --- a/crates/jacquard-api/src/net_anisota/feed/list.rs +++ b/crates/jacquard-api/src/net_anisota/feed/list.rs @@ -176,6 +176,18 @@ impl LexiconSchema for List { }); } } + if let Some(values) = &self.tags { + for value in values { + #[allow(unused_comparisons)] + if ::len(value.as_ref()) > 32usize { + return Err(ConstraintError::MaxLength { + path: ValidationPath::from_field("tags"), + max: 32usize, + actual: ::len(value.as_ref()), + }); + } + } + } Ok(()) } } diff --git a/crates/jacquard-api/src/net_anisota/feed/post.rs b/crates/jacquard-api/src/net_anisota/feed/post.rs index 3263298ce..79bbdcc5b 100644 --- a/crates/jacquard-api/src/net_anisota/feed/post.rs +++ b/crates/jacquard-api/src/net_anisota/feed/post.rs @@ -176,6 +176,32 @@ impl LexiconSchema for Post { }); } } + if let Some(values) = &self.tags { + for value in values { + #[allow(unused_comparisons)] + if ::len(value.as_ref()) > 640usize { + return Err(ConstraintError::MaxLength { + path: ValidationPath::from_field("tags"), + max: 640usize, + actual: ::len(value.as_ref()), + }); + } + } + } + if let Some(values) = &self.tags { + for value in values { + { + let count = UnicodeSegmentation::graphemes(value.as_ref(), true).count(); + if count > 64usize { + return Err(ConstraintError::MaxGraphemes { + path: ValidationPath::from_field("tags"), + max: 64usize, + actual: count, + }); + } + } + } + } { let value = &self.text; #[allow(unused_comparisons)] diff --git a/crates/jacquard-api/src/net_anisota/fieldwork.rs b/crates/jacquard-api/src/net_anisota/fieldwork.rs new file mode 100644 index 000000000..93d9b1b40 --- /dev/null +++ b/crates/jacquard-api/src/net_anisota/fieldwork.rs @@ -0,0 +1,7 @@ +// @generated by jacquard-lexicon. DO NOT EDIT. +// +// This file was automatically generated from Lexicon schemas. +// Any manual changes will be overwritten on the next regeneration. + +//! Generated bindings for the `net.anisota.fieldwork` Lexicon namespace/module. +pub mod state; diff --git a/crates/jacquard-api/src/net_anisota/fieldwork/state.rs b/crates/jacquard-api/src/net_anisota/fieldwork/state.rs new file mode 100644 index 000000000..9933cb3fb --- /dev/null +++ b/crates/jacquard-api/src/net_anisota/fieldwork/state.rs @@ -0,0 +1,518 @@ +// @generated by jacquard-lexicon. DO NOT EDIT. +// +// Lexicon: net.anisota.fieldwork.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}; +/// Quest system state for cross-device sync (dismissals, nudge timing, visited routes). Singleton record (rkey: self), overwritten via putRecord. Client-written (no backend signing). Distinct from net.anisota.chronicle.fieldwork (immutable, backend-signed completion records). + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + rename = "net.anisota.fieldwork.state", + tag = "$type", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct State { + ///Reserved for future quest progress counters. Object mapping counter ids to values. + #[serde(skip_serializing_if = "Option::is_none")] + pub counters: Option>, + ///Object mapping dismissed quest ids to the ISO datetime they were dismissed. Dismissed quests are excluded from recommendations and nudges until undismissed. + #[serde(skip_serializing_if = "Option::is_none")] + pub dismissed: Option>, + ///When a quest nudge was last shown (nudges are spaced at least a day apart) + #[serde(skip_serializing_if = "Option::is_none")] + pub last_nudge_at: Option, + ///Which quest the most recent nudge was about + #[serde(skip_serializing_if = "Option::is_none")] + pub last_nudge_quest_id: Option, + ///Quest the player has pinned to keep in view + #[serde(skip_serializing_if = "Option::is_none")] + pub pinned_quest_id: Option, + ///When the retroactive completion sweep last ran (throttles the sweep to once per day) + #[serde(skip_serializing_if = "Option::is_none")] + pub retro_sweep_at: Option, + ///Version of the retroactive sweep that armed retroSweepAt. When it doesn't match the client's current sweep version the throttle is treated as stale and the sweep runs once more, so a throttle armed by an earlier (buggy) sweep can't lock out backfill. + #[serde(skip_serializing_if = "Option::is_none")] + pub retro_sweep_version: Option, + ///Suppress quest nudges until this time + #[serde(skip_serializing_if = "Option::is_none")] + pub snoozed_until: Option, + ///When this state snapshot was taken + pub updated_at: Datetime, + ///Object mapping visited app routes (e.g. '/chronicle') to the ISO datetime of the first tracked visit. Drives route-based quest detection. + #[serde(skip_serializing_if = "Option::is_none")] + pub visited_routes: 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 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 = "net.anisota.fieldwork.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 = "net.anisota.fieldwork.state"; + type Record = StateRecord; +} + +impl Collection for StateRecord { + const NSID: &'static str = "net.anisota.fieldwork.state"; + type Record = StateRecord; +} + +impl LexiconSchema for State { + fn nsid() -> &'static str { + "net.anisota.fieldwork.state" + } + fn def_name() -> &'static str { + "main" + } + fn lexicon_doc() -> LexiconDoc<'static> { + lexicon_doc_net_anisota_fieldwork_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 UpdatedAt; + } + /// Empty state - all required fields are unset + pub struct Empty(()); + impl sealed::Sealed for Empty {} + impl State for Empty { + type UpdatedAt = Unset; + } + ///State transition - sets the `updated_at` field to Set + pub struct SetUpdatedAt(PhantomData St>); + impl sealed::Sealed for SetUpdatedAt {} + impl State for SetUpdatedAt { + type UpdatedAt = Set; + } + /// Marker types for field names + #[allow(non_camel_case_types)] + pub mod members { + ///Marker type for the `updated_at` field + pub struct updated_at(()); + } +} + +/// Builder for constructing an instance of this type. +pub struct StateBuilder { + _state: PhantomData St>, + _fields: ( + Option>, + Option>, + Option, + Option, + Option, + Option, + Option, + 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, None, None, None, None, 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, None, None, None, None, None, None, None), + _type: PhantomData, + } + } +} + +impl StateBuilder { + /// Set the `counters` field (optional) + pub fn counters(mut self, value: impl Into>>) -> Self { + self._fields.0 = value.into(); + self + } + /// Set the `counters` field to an Option value (optional) + pub fn maybe_counters(mut self, value: Option>) -> Self { + self._fields.0 = value; + self + } +} + +impl StateBuilder { + /// Set the `dismissed` field (optional) + pub fn dismissed(mut self, value: impl Into>>) -> Self { + self._fields.1 = value.into(); + self + } + /// Set the `dismissed` field to an Option value (optional) + pub fn maybe_dismissed(mut self, value: Option>) -> Self { + self._fields.1 = value; + self + } +} + +impl StateBuilder { + /// Set the `lastNudgeAt` field (optional) + pub fn last_nudge_at(mut self, value: impl Into>) -> Self { + self._fields.2 = value.into(); + self + } + /// Set the `lastNudgeAt` field to an Option value (optional) + pub fn maybe_last_nudge_at(mut self, value: Option) -> Self { + self._fields.2 = value; + self + } +} + +impl StateBuilder { + /// Set the `lastNudgeQuestId` field (optional) + pub fn last_nudge_quest_id(mut self, value: impl Into>) -> Self { + self._fields.3 = value.into(); + self + } + /// Set the `lastNudgeQuestId` field to an Option value (optional) + pub fn maybe_last_nudge_quest_id(mut self, value: Option) -> Self { + self._fields.3 = value; + self + } +} + +impl StateBuilder { + /// Set the `pinnedQuestId` field (optional) + pub fn pinned_quest_id(mut self, value: impl Into>) -> Self { + self._fields.4 = value.into(); + self + } + /// Set the `pinnedQuestId` field to an Option value (optional) + pub fn maybe_pinned_quest_id(mut self, value: Option) -> Self { + self._fields.4 = value; + self + } +} + +impl StateBuilder { + /// Set the `retroSweepAt` field (optional) + pub fn retro_sweep_at(mut self, value: impl Into>) -> Self { + self._fields.5 = value.into(); + self + } + /// Set the `retroSweepAt` field to an Option value (optional) + pub fn maybe_retro_sweep_at(mut self, value: Option) -> Self { + self._fields.5 = value; + self + } +} + +impl StateBuilder { + /// Set the `retroSweepVersion` field (optional) + pub fn retro_sweep_version(mut self, value: impl Into>) -> Self { + self._fields.6 = value.into(); + self + } + /// Set the `retroSweepVersion` field to an Option value (optional) + pub fn maybe_retro_sweep_version(mut self, value: Option) -> Self { + self._fields.6 = value; + self + } +} + +impl StateBuilder { + /// Set the `snoozedUntil` field (optional) + pub fn snoozed_until(mut self, value: impl Into>) -> Self { + self._fields.7 = value.into(); + self + } + /// Set the `snoozedUntil` field to an Option value (optional) + pub fn maybe_snoozed_until(mut self, value: Option) -> Self { + self._fields.7 = value; + self + } +} + +impl StateBuilder +where + St: state_state::State, + St::UpdatedAt: state_state::IsUnset, +{ + /// Set the `updatedAt` field (required) + pub fn updated_at( + mut self, + value: impl Into, + ) -> StateBuilder, S> { + self._fields.8 = Option::Some(value.into()); + StateBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl StateBuilder { + /// Set the `visitedRoutes` field (optional) + pub fn visited_routes(mut self, value: impl Into>>) -> Self { + self._fields.9 = value.into(); + self + } + /// Set the `visitedRoutes` field to an Option value (optional) + pub fn maybe_visited_routes(mut self, value: Option>) -> Self { + self._fields.9 = value; + self + } +} + +impl StateBuilder +where + St: state_state::State, + St::UpdatedAt: state_state::IsSet, +{ + /// Build the final struct. + pub fn build(self) -> State { + State { + counters: self._fields.0, + dismissed: self._fields.1, + last_nudge_at: self._fields.2, + last_nudge_quest_id: self._fields.3, + pinned_quest_id: self._fields.4, + retro_sweep_at: self._fields.5, + retro_sweep_version: self._fields.6, + snoozed_until: self._fields.7, + updated_at: self._fields.8.unwrap(), + visited_routes: self._fields.9, + extra_data: Default::default(), + } + } + /// Build the final struct with custom extra_data. + pub fn build_with_data(self, extra_data: BTreeMap>) -> State { + State { + counters: self._fields.0, + dismissed: self._fields.1, + last_nudge_at: self._fields.2, + last_nudge_quest_id: self._fields.3, + pinned_quest_id: self._fields.4, + retro_sweep_at: self._fields.5, + retro_sweep_version: self._fields.6, + snoozed_until: self._fields.7, + updated_at: self._fields.8.unwrap(), + visited_routes: self._fields.9, + extra_data: Some(extra_data), + } + } +} + +fn lexicon_doc_net_anisota_fieldwork_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("net.anisota.fieldwork.state"), + defs: { + let mut map = BTreeMap::new(); + map.insert( + SmolStr::new_static("main"), + LexUserType::Record(LexRecord { + description: Some( + CowStr::new_static( + "Quest system state for cross-device sync (dismissals, nudge timing, visited routes). Singleton record (rkey: self), overwritten via putRecord. Client-written (no backend signing). Distinct from net.anisota.chronicle.fieldwork (immutable, backend-signed completion records).", + ), + ), + key: Some(CowStr::new_static("any")), + record: LexRecordRecord::Object(LexObject { + required: Some(vec![SmolStr::new_static("updatedAt")]), + properties: { + #[allow(unused_mut)] + let mut map = BTreeMap::new(); + map.insert( + SmolStr::new_static("counters"), + LexObjectProperty::Unknown(LexUnknown { + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("dismissed"), + LexObjectProperty::Unknown(LexUnknown { + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("lastNudgeAt"), + LexObjectProperty::String(LexString { + description: Some( + CowStr::new_static( + "When a quest nudge was last shown (nudges are spaced at least a day apart)", + ), + ), + format: Some(LexStringFormat::Datetime), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("lastNudgeQuestId"), + LexObjectProperty::String(LexString { + description: Some( + CowStr::new_static( + "Which quest the most recent nudge was about", + ), + ), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("pinnedQuestId"), + LexObjectProperty::String(LexString { + description: Some( + CowStr::new_static( + "Quest the player has pinned to keep in view", + ), + ), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("retroSweepAt"), + LexObjectProperty::String(LexString { + description: Some( + CowStr::new_static( + "When the retroactive completion sweep last ran (throttles the sweep to once per day)", + ), + ), + format: Some(LexStringFormat::Datetime), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("retroSweepVersion"), + LexObjectProperty::Integer(LexInteger { + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("snoozedUntil"), + LexObjectProperty::String(LexString { + description: Some( + CowStr::new_static("Suppress quest nudges until this time"), + ), + format: Some(LexStringFormat::Datetime), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("updatedAt"), + LexObjectProperty::String(LexString { + description: Some( + CowStr::new_static("When this state snapshot was taken"), + ), + format: Some(LexStringFormat::Datetime), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("visitedRoutes"), + LexObjectProperty::Unknown(LexUnknown { + ..Default::default() + }), + ); + map + }, + ..Default::default() + }), + ..Default::default() + }), + ); + map + }, + ..Default::default() + } +} diff --git a/crates/jacquard-api/src/net_anisota/graph.rs b/crates/jacquard-api/src/net_anisota/graph.rs index 9630e301b..7493799b6 100644 --- a/crates/jacquard-api/src/net_anisota/graph.rs +++ b/crates/jacquard-api/src/net_anisota/graph.rs @@ -6,3 +6,5 @@ //! Generated bindings for the `net.anisota.graph` Lexicon namespace/module. pub mod list_mute; pub mod mute; +pub mod scoped_mute; +pub mod wordlist; diff --git a/crates/jacquard-api/src/net_anisota/graph/list_mute.rs b/crates/jacquard-api/src/net_anisota/graph/list_mute.rs index e8b70487b..ff50c1d53 100644 --- a/crates/jacquard-api/src/net_anisota/graph/list_mute.rs +++ b/crates/jacquard-api/src/net_anisota/graph/list_mute.rs @@ -79,9 +79,9 @@ pub struct ListMute { pub reason: Option, ///AT-URI of the list to mute (app.bsky.graph.list record) pub subject: AtUri, - ///Specific feeds where this mute should apply. If empty, applies to all feeds + ///Specific feeds where this mute should apply: feed generator / list at-uris, or the literal sentinel 'following' for the home timeline (which has no at-uri). Empty or absent applies everywhere. Matches net.anisota.graph.wordlist#targetFeeds. #[serde(skip_serializing_if = "Option::is_none")] - pub target_feeds: Option>>, + pub target_feeds: Option>, #[serde(flatten, default, skip_serializing_if = "Option::is_none")] pub extra_data: Option>>, } @@ -176,6 +176,18 @@ impl LexiconSchema for ListMute { }); } } + if let Some(values) = &self.target_feeds { + for value in values { + #[allow(unused_comparisons)] + if ::len(value.as_ref()) > 512usize { + return Err(ConstraintError::MaxLength { + path: ValidationPath::from_field("target_feeds"), + max: 512usize, + actual: ::len(value.as_ref()), + }); + } + } + } Ok(()) } } @@ -331,11 +343,11 @@ fn lexicon_doc_net_anisota_graph_listMute() -> LexiconDoc<'static> { LexObjectProperty::Array(LexArray { description: Some( CowStr::new_static( - "Specific feeds where this mute should apply. If empty, applies to all feeds", + "Specific feeds where this mute should apply: feed generator / list at-uris, or the literal sentinel 'following' for the home timeline (which has no at-uri). Empty or absent applies everywhere. Matches net.anisota.graph.wordlist#targetFeeds.", ), ), items: LexArrayItem::String(LexString { - format: Some(LexStringFormat::AtUri), + max_length: Some(512usize), ..Default::default() }), max_length: Some(50usize), @@ -408,7 +420,7 @@ pub struct ListMuteBuilder { Option, Option, Option>, - Option>>, + Option>, ), _type: PhantomData S>, } @@ -528,12 +540,12 @@ where impl ListMuteBuilder { /// Set the `targetFeeds` field (optional) - pub fn target_feeds(mut self, value: impl Into>>>) -> Self { + pub fn target_feeds(mut self, value: impl Into>>) -> Self { self._fields.5 = value.into(); self } /// Set the `targetFeeds` field to an Option value (optional) - pub fn maybe_target_feeds(mut self, value: Option>>) -> Self { + pub fn maybe_target_feeds(mut self, value: Option>) -> Self { self._fields.5 = value; self } diff --git a/crates/jacquard-api/src/net_anisota/graph/mute.rs b/crates/jacquard-api/src/net_anisota/graph/mute.rs index b703e954b..c7e453273 100644 --- a/crates/jacquard-api/src/net_anisota/graph/mute.rs +++ b/crates/jacquard-api/src/net_anisota/graph/mute.rs @@ -79,9 +79,9 @@ pub struct Mute { pub reason: Option, ///DID of the account to mute pub subject: Did, - ///Specific feeds where this mute should apply. If empty, applies to all feeds + ///Specific feeds where this mute should apply: feed generator / list at-uris, or the literal sentinel 'following' for the home timeline (which has no at-uri). Empty or absent applies everywhere. Matches net.anisota.graph.wordlist#targetFeeds. #[serde(skip_serializing_if = "Option::is_none")] - pub target_feeds: Option>>, + pub target_feeds: Option>, #[serde(flatten, default, skip_serializing_if = "Option::is_none")] pub extra_data: Option>>, } @@ -176,6 +176,18 @@ impl LexiconSchema for Mute { }); } } + if let Some(values) = &self.target_feeds { + for value in values { + #[allow(unused_comparisons)] + if ::len(value.as_ref()) > 512usize { + return Err(ConstraintError::MaxLength { + path: ValidationPath::from_field("target_feeds"), + max: 512usize, + actual: ::len(value.as_ref()), + }); + } + } + } Ok(()) } } @@ -331,11 +343,11 @@ fn lexicon_doc_net_anisota_graph_mute() -> LexiconDoc<'static> { LexObjectProperty::Array(LexArray { description: Some( CowStr::new_static( - "Specific feeds where this mute should apply. If empty, applies to all feeds", + "Specific feeds where this mute should apply: feed generator / list at-uris, or the literal sentinel 'following' for the home timeline (which has no at-uri). Empty or absent applies everywhere. Matches net.anisota.graph.wordlist#targetFeeds.", ), ), items: LexArrayItem::String(LexString { - format: Some(LexStringFormat::AtUri), + max_length: Some(512usize), ..Default::default() }), max_length: Some(50usize), @@ -408,7 +420,7 @@ pub struct MuteBuilder { Option, Option, Option>, - Option>>, + Option>, ), _type: PhantomData S>, } @@ -528,12 +540,12 @@ where impl MuteBuilder { /// Set the `targetFeeds` field (optional) - pub fn target_feeds(mut self, value: impl Into>>>) -> Self { + pub fn target_feeds(mut self, value: impl Into>>) -> Self { self._fields.5 = value.into(); self } /// Set the `targetFeeds` field to an Option value (optional) - pub fn maybe_target_feeds(mut self, value: Option>>) -> Self { + pub fn maybe_target_feeds(mut self, value: Option>) -> Self { self._fields.5 = value; self } diff --git a/crates/jacquard-api/src/net_anisota/graph/scoped_mute.rs b/crates/jacquard-api/src/net_anisota/graph/scoped_mute.rs new file mode 100644 index 000000000..1c7870a4f --- /dev/null +++ b/crates/jacquard-api/src/net_anisota/graph/scoped_mute.rs @@ -0,0 +1,627 @@ +// @generated by jacquard-lexicon. DO NOT EDIT. +// +// Lexicon: net.anisota.graph.scopedMute +// +// 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; + +use crate::net_anisota::graph::scoped_mute; +#[allow(unused_imports)] +use jacquard_lexicon::validation::{ConstraintError, ValidationPath}; +use serde::{Deserialize, Serialize}; +/// An index of the accounts whose reposts or quote posts the viewer has muted through Bluesky's native scoped mute (app.bsky.graph.muteActor with onlyReposts / onlyQuoteposts). Bluesky stores the mute itself, but app.bsky.graph.getMutes returns only fully muted accounts, so a scoped mute is otherwise discoverable only by loading each profile. This record lets Anisota list and undo them, and enforce them client-side on unauthenticated reads where no viewer state comes back. It is a cache, not the source of truth: entries are reconciled against viewerState.mutedOnlyReposts / mutedOnlyQuoteposts and dropped when the server disagrees. + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + rename = "net.anisota.graph.scopedMute", + tag = "$type", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct ScopedMute { + ///When this index was first written + pub created_at: Datetime, + ///The accounts currently carrying a native scoped mute. + pub subjects: Vec>, + ///When this index was last reconciled or edited + #[serde(skip_serializing_if = "Option::is_none")] + pub updated_at: 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 ScopedMuteGetRecordOutput { + #[serde(skip_serializing_if = "Option::is_none")] + pub cid: Option>, + pub uri: AtUri, + pub value: ScopedMute, +} + +/// One account's native scoped mute. At least one scope flag is true — an entry with neither is a full mute or no mute at all, and does not belong here. + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct ScopedMuteEntry { + ///When this scoped mute was set from Anisota + #[serde(skip_serializing_if = "Option::is_none")] + pub created_at: Option, + ///Their quote posts are muted Defaults to `false`. + #[serde(skip_serializing_if = "Option::is_none")] + #[serde(default = "_default_scoped_mute_entry_only_quoteposts")] + pub only_quoteposts: Option, + ///Their reposts are muted Defaults to `false`. + #[serde(skip_serializing_if = "Option::is_none")] + #[serde(default = "_default_scoped_mute_entry_only_reposts")] + pub only_reposts: Option, + ///DID of the scope-muted account + pub subject: Did, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +impl ScopedMute { + 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 ScopedMuteRecord; +impl XrpcResp for ScopedMuteRecord { + const NSID: &'static str = "net.anisota.graph.scopedMute"; + const ENCODING: &'static str = "application/json"; + type Output = ScopedMuteGetRecordOutput; + type Err = RecordError; +} + +impl From> for ScopedMute { + fn from(output: ScopedMuteGetRecordOutput) -> Self { + output.value + } +} + +impl Collection for ScopedMute { + const NSID: &'static str = "net.anisota.graph.scopedMute"; + type Record = ScopedMuteRecord; +} + +impl Collection for ScopedMuteRecord { + const NSID: &'static str = "net.anisota.graph.scopedMute"; + type Record = ScopedMuteRecord; +} + +impl LexiconSchema for ScopedMute { + fn nsid() -> &'static str { + "net.anisota.graph.scopedMute" + } + fn def_name() -> &'static str { + "main" + } + fn lexicon_doc() -> LexiconDoc<'static> { + lexicon_doc_net_anisota_graph_scopedMute() + } + fn validate(&self) -> Result<(), ConstraintError> { + { + let value = &self.subjects; + #[allow(unused_comparisons)] + if value.len() > 1000usize { + return Err(ConstraintError::MaxLength { + path: ValidationPath::from_field("subjects"), + max: 1000usize, + actual: value.len(), + }); + } + } + Ok(()) + } +} + +impl LexiconSchema for ScopedMuteEntry { + fn nsid() -> &'static str { + "net.anisota.graph.scopedMute" + } + fn def_name() -> &'static str { + "scopedMuteEntry" + } + fn lexicon_doc() -> LexiconDoc<'static> { + lexicon_doc_net_anisota_graph_scopedMute() + } + fn validate(&self) -> Result<(), ConstraintError> { + Ok(()) + } +} + +pub mod scoped_mute_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 Subjects; + } + /// Empty state - all required fields are unset + pub struct Empty(()); + impl sealed::Sealed for Empty {} + impl State for Empty { + type CreatedAt = Unset; + type Subjects = 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 Subjects = St::Subjects; + } + ///State transition - sets the `subjects` field to Set + pub struct SetSubjects(PhantomData St>); + impl sealed::Sealed for SetSubjects {} + impl State for SetSubjects { + type CreatedAt = St::CreatedAt; + type Subjects = 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 `subjects` field + pub struct subjects(()); + } +} + +/// Builder for constructing an instance of this type. +pub struct ScopedMuteBuilder { + _state: PhantomData St>, + _fields: ( + Option, + Option>>, + Option, + ), + _type: PhantomData S>, +} + +impl ScopedMute { + /// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed + pub fn new() -> ScopedMuteBuilder { + ScopedMuteBuilder::new() + } +} + +impl ScopedMute { + /// Create a new builder for this type + pub fn builder() -> ScopedMuteBuilder { + ScopedMuteBuilder::builder() + } +} + +impl ScopedMuteBuilder { + /// Create a new builder with all fields unset, using the default string type, if needed + pub fn new() -> Self { + ScopedMuteBuilder { + _state: PhantomData, + _fields: (None, None, None), + _type: PhantomData, + } + } +} + +impl ScopedMuteBuilder { + /// Create a new builder with all fields unset + pub fn builder() -> Self { + ScopedMuteBuilder { + _state: PhantomData, + _fields: (None, None, None), + _type: PhantomData, + } + } +} + +impl ScopedMuteBuilder +where + St: scoped_mute_state::State, + St::CreatedAt: scoped_mute_state::IsUnset, +{ + /// Set the `createdAt` field (required) + pub fn created_at( + mut self, + value: impl Into, + ) -> ScopedMuteBuilder, S> { + self._fields.0 = Option::Some(value.into()); + ScopedMuteBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl ScopedMuteBuilder +where + St: scoped_mute_state::State, + St::Subjects: scoped_mute_state::IsUnset, +{ + /// Set the `subjects` field (required) + pub fn subjects( + mut self, + value: impl Into>>, + ) -> ScopedMuteBuilder, S> { + self._fields.1 = Option::Some(value.into()); + ScopedMuteBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl ScopedMuteBuilder { + /// Set the `updatedAt` field (optional) + pub fn updated_at(mut self, value: impl Into>) -> Self { + self._fields.2 = value.into(); + self + } + /// Set the `updatedAt` field to an Option value (optional) + pub fn maybe_updated_at(mut self, value: Option) -> Self { + self._fields.2 = value; + self + } +} + +impl ScopedMuteBuilder +where + St: scoped_mute_state::State, + St::CreatedAt: scoped_mute_state::IsSet, + St::Subjects: scoped_mute_state::IsSet, +{ + /// Build the final struct. + pub fn build(self) -> ScopedMute { + ScopedMute { + created_at: self._fields.0.unwrap(), + subjects: self._fields.1.unwrap(), + updated_at: self._fields.2, + extra_data: Default::default(), + } + } + /// Build the final struct with custom extra_data. + pub fn build_with_data(self, extra_data: BTreeMap>) -> ScopedMute { + ScopedMute { + created_at: self._fields.0.unwrap(), + subjects: self._fields.1.unwrap(), + updated_at: self._fields.2, + extra_data: Some(extra_data), + } + } +} + +fn lexicon_doc_net_anisota_graph_scopedMute() -> 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("net.anisota.graph.scopedMute"), + defs: { + let mut map = BTreeMap::new(); + map.insert( + SmolStr::new_static("main"), + LexUserType::Record(LexRecord { + description: Some( + CowStr::new_static( + "An index of the accounts whose reposts or quote posts the viewer has muted through Bluesky's native scoped mute (app.bsky.graph.muteActor with onlyReposts / onlyQuoteposts). Bluesky stores the mute itself, but app.bsky.graph.getMutes returns only fully muted accounts, so a scoped mute is otherwise discoverable only by loading each profile. This record lets Anisota list and undo them, and enforce them client-side on unauthenticated reads where no viewer state comes back. It is a cache, not the source of truth: entries are reconciled against viewerState.mutedOnlyReposts / mutedOnlyQuoteposts and dropped when the server disagrees.", + ), + ), + key: Some(CowStr::new_static("literal:self")), + record: LexRecordRecord::Object(LexObject { + required: Some( + vec![ + SmolStr::new_static("subjects"), + SmolStr::new_static("createdAt") + ], + ), + properties: { + #[allow(unused_mut)] + let mut map = BTreeMap::new(); + map.insert( + SmolStr::new_static("createdAt"), + LexObjectProperty::String(LexString { + description: Some( + CowStr::new_static("When this index was first written"), + ), + format: Some(LexStringFormat::Datetime), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("subjects"), + LexObjectProperty::Array(LexArray { + description: Some( + CowStr::new_static( + "The accounts currently carrying a native scoped mute.", + ), + ), + items: LexArrayItem::Ref(LexRef { + r#ref: CowStr::new_static("#scopedMuteEntry"), + ..Default::default() + }), + max_length: Some(1000usize), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("updatedAt"), + LexObjectProperty::String(LexString { + description: Some( + CowStr::new_static( + "When this index was last reconciled or edited", + ), + ), + format: Some(LexStringFormat::Datetime), + ..Default::default() + }), + ); + map + }, + ..Default::default() + }), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("scopedMuteEntry"), + LexUserType::Object(LexObject { + description: Some( + CowStr::new_static( + "One account's native scoped mute. At least one scope flag is true — an entry with neither is a full mute or no mute at all, and does not belong here.", + ), + ), + required: Some(vec![SmolStr::new_static("subject")]), + properties: { + #[allow(unused_mut)] + let mut map = BTreeMap::new(); + map.insert( + SmolStr::new_static("createdAt"), + LexObjectProperty::String(LexString { + description: Some( + CowStr::new_static( + "When this scoped mute was set from Anisota", + ), + ), + format: Some(LexStringFormat::Datetime), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("onlyQuoteposts"), + LexObjectProperty::Boolean(LexBoolean { + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("onlyReposts"), + LexObjectProperty::Boolean(LexBoolean { + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("subject"), + LexObjectProperty::String(LexString { + description: Some( + CowStr::new_static("DID of the scope-muted account"), + ), + format: Some(LexStringFormat::Did), + ..Default::default() + }), + ); + map + }, + ..Default::default() + }), + ); + map + }, + ..Default::default() + } +} + +fn _default_scoped_mute_entry_only_quoteposts() -> Option { + Some(false) +} + +fn _default_scoped_mute_entry_only_reposts() -> Option { + Some(false) +} + +pub mod scoped_mute_entry_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 Subject; + } + /// Empty state - all required fields are unset + pub struct Empty(()); + impl sealed::Sealed for Empty {} + impl State for Empty { + type Subject = Unset; + } + ///State transition - sets the `subject` field to Set + pub struct SetSubject(PhantomData St>); + impl sealed::Sealed for SetSubject {} + impl State for SetSubject { + type Subject = Set; + } + /// Marker types for field names + #[allow(non_camel_case_types)] + pub mod members { + ///Marker type for the `subject` field + pub struct subject(()); + } +} + +/// Builder for constructing an instance of this type. +pub struct ScopedMuteEntryBuilder { + _state: PhantomData St>, + _fields: (Option, Option, Option, Option>), + _type: PhantomData S>, +} + +impl ScopedMuteEntry { + /// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed + pub fn new() -> ScopedMuteEntryBuilder { + ScopedMuteEntryBuilder::new() + } +} + +impl ScopedMuteEntry { + /// Create a new builder for this type + pub fn builder() -> ScopedMuteEntryBuilder { + ScopedMuteEntryBuilder::builder() + } +} + +impl ScopedMuteEntryBuilder { + /// Create a new builder with all fields unset, using the default string type, if needed + pub fn new() -> Self { + ScopedMuteEntryBuilder { + _state: PhantomData, + _fields: (None, None, None, None), + _type: PhantomData, + } + } +} + +impl ScopedMuteEntryBuilder { + /// Create a new builder with all fields unset + pub fn builder() -> Self { + ScopedMuteEntryBuilder { + _state: PhantomData, + _fields: (None, None, None, None), + _type: PhantomData, + } + } +} + +impl ScopedMuteEntryBuilder { + /// Set the `createdAt` field (optional) + pub fn created_at(mut self, value: impl Into>) -> Self { + self._fields.0 = value.into(); + self + } + /// Set the `createdAt` field to an Option value (optional) + pub fn maybe_created_at(mut self, value: Option) -> Self { + self._fields.0 = value; + self + } +} + +impl ScopedMuteEntryBuilder { + /// Set the `onlyQuoteposts` field (optional) + pub fn only_quoteposts(mut self, value: impl Into>) -> Self { + self._fields.1 = value.into(); + self + } + /// Set the `onlyQuoteposts` field to an Option value (optional) + pub fn maybe_only_quoteposts(mut self, value: Option) -> Self { + self._fields.1 = value; + self + } +} + +impl ScopedMuteEntryBuilder { + /// Set the `onlyReposts` field (optional) + pub fn only_reposts(mut self, value: impl Into>) -> Self { + self._fields.2 = value.into(); + self + } + /// Set the `onlyReposts` field to an Option value (optional) + pub fn maybe_only_reposts(mut self, value: Option) -> Self { + self._fields.2 = value; + self + } +} + +impl ScopedMuteEntryBuilder +where + St: scoped_mute_entry_state::State, + St::Subject: scoped_mute_entry_state::IsUnset, +{ + /// Set the `subject` field (required) + pub fn subject( + mut self, + value: impl Into>, + ) -> ScopedMuteEntryBuilder, S> { + self._fields.3 = Option::Some(value.into()); + ScopedMuteEntryBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl ScopedMuteEntryBuilder +where + St: scoped_mute_entry_state::State, + St::Subject: scoped_mute_entry_state::IsSet, +{ + /// Build the final struct. + pub fn build(self) -> ScopedMuteEntry { + ScopedMuteEntry { + created_at: self._fields.0, + only_quoteposts: self._fields.1.or_else(|| Some(false)), + only_reposts: self._fields.2.or_else(|| Some(false)), + subject: self._fields.3.unwrap(), + extra_data: Default::default(), + } + } + /// Build the final struct with custom extra_data. + pub fn build_with_data(self, extra_data: BTreeMap>) -> ScopedMuteEntry { + ScopedMuteEntry { + created_at: self._fields.0, + only_quoteposts: self._fields.1.or_else(|| Some(false)), + only_reposts: self._fields.2.or_else(|| Some(false)), + subject: self._fields.3.unwrap(), + extra_data: Some(extra_data), + } + } +} diff --git a/crates/jacquard-api/src/net_anisota/graph/wordlist.rs b/crates/jacquard-api/src/net_anisota/graph/wordlist.rs new file mode 100644 index 000000000..eeb3897e7 --- /dev/null +++ b/crates/jacquard-api/src/net_anisota/graph/wordlist.rs @@ -0,0 +1,1294 @@ +// @generated by jacquard-lexicon. DO NOT EDIT. +// +// Lexicon: net.anisota.graph.wordlist +// +// 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; + +use crate::net_anisota::graph::wordlist; +#[allow(unused_imports)] +use jacquard_lexicon::validation::{ConstraintError, ValidationPath}; +use serde::{Deserialize, Serialize}; +/// A named, shareable list of muted words/phrases — Anisota's managed layer on top of Bluesky's flat muted-words preference. Each list is a complete, self-contained record so it can be shared by URL and saved (copied) into another user's PDS, mirroring the net.anisota.spell.custom architecture. Muting is applied client-side by the moderation pipeline: multiple enabled lists combine, a list can be scoped to specific feeds, restricted to a time-of-day/day-of-week window, and softened with a strength percentage (mute only that share of matching posts, deterministically per post). A list can optionally be projected into Bluesky's native mutedWordsPref for parity with other clients. + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + rename = "net.anisota.graph.wordlist", + tag = "$type", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct Wordlist { + ///When this list was created + pub created_at: Datetime, + ///Optional description of what this list covers + #[serde(skip_serializing_if = "Option::is_none")] + pub description: Option, + ///Whether this list is currently active. Scheduling and spell effects further gate an enabled list. Defaults to `false`. + #[serde(skip_serializing_if = "Option::is_none")] + #[serde(default = "_default_wordlist_enabled")] + pub enabled: Option, + ///Display name for this word list + pub name: S, + ///Optional active window. Absent means the list applies at all times while enabled. + #[serde(skip_serializing_if = "Option::is_none")] + pub schedule: Option>, + #[serde(skip_serializing_if = "Option::is_none")] + pub source: Option>, + ///Mute strength percentage: the share of matching posts this list mutes. Which posts fill that share is decided by match confidence — how many of the list's words hit, whether they landed in the post's own text, a hashtag, or only a quoted post, and how much of the post they account for — so a softened list keeps the squarest matches muted and lets the marginal ones through. Deterministic per post, so a post never flickers. Absent means 100 (mute everything it matches). + #[serde(skip_serializing_if = "Option::is_none")] + pub strength: Option, + ///Whether this list's words are also projected into Bluesky's native mutedWordsPref (managed entries, removed when the list is disabled or deleted). Defaults to `false`. + #[serde(skip_serializing_if = "Option::is_none")] + #[serde(default = "_default_wordlist_sync_to_bluesky")] + pub sync_to_bluesky: Option, + ///Feeds where this list applies: feed generator / list at-uris, or the literal sentinel 'following' for the home timeline. Empty or absent applies everywhere. + #[serde(skip_serializing_if = "Option::is_none")] + pub target_feeds: Option>, + ///What this list does to a post it mutes, overriding the app-wide muted-words handling: 'hide' removes it from feeds, 'warn' collapses it behind a notice, 'show' leaves it visible and only counts it toward impact. Absent inherits the global setting. + #[serde(skip_serializing_if = "Option::is_none")] + pub treatment: Option>, + ///When this list was last modified + #[serde(skip_serializing_if = "Option::is_none")] + pub updated_at: Option, + ///The muted words/phrases in this list + pub words: Vec>, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +/// What this list does to a post it mutes, overriding the app-wide muted-words handling: 'hide' removes it from feeds, 'warn' collapses it behind a notice, 'show' leaves it visible and only counts it toward impact. Absent inherits the global setting. + +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub enum WordlistTreatment { + Hide, + Warn, + Show, + Other(S), +} + +impl WordlistTreatment { + pub fn as_str(&self) -> &str { + match self { + Self::Hide => "hide", + Self::Warn => "warn", + Self::Show => "show", + 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() { + "hide" => Self::Hide, + "warn" => Self::Warn, + "show" => Self::Show, + _ => Self::Other(s), + } + } +} + +impl core::fmt::Display for WordlistTreatment { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!(f, "{}", self.as_str()) + } +} + +impl AsRef for WordlistTreatment { + fn as_ref(&self) -> &str { + self.as_str() + } +} + +impl Serialize for WordlistTreatment { + 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 WordlistTreatment { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = S::deserialize(deserializer)?; + Ok(Self::from_value(s)) + } +} + +impl Default for WordlistTreatment { + fn default() -> Self { + Self::Other(Default::default()) + } +} + +impl jacquard_common::IntoStatic for WordlistTreatment +where + S: BosStr + jacquard_common::IntoStatic, + S::Output: BosStr, +{ + type Output = WordlistTreatment; + fn into_static(self) -> Self::Output { + match self { + WordlistTreatment::Hide => WordlistTreatment::Hide, + WordlistTreatment::Warn => WordlistTreatment::Warn, + WordlistTreatment::Show => WordlistTreatment::Show, + WordlistTreatment::Other(v) => WordlistTreatment::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 WordlistGetRecordOutput { + #[serde(skip_serializing_if = "Option::is_none")] + pub cid: Option>, + pub uri: AtUri, + pub value: Wordlist, +} + +/// A recurring active window. Days and time window combine: the list applies only on the listed days (absent/empty = every day) and only inside the time window (absent = all day). A window whose end is at or before its start wraps past midnight. + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic, Default)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct Schedule { + ///Days of week the list is active (0 = Sunday … 6 = Saturday) + #[serde(skip_serializing_if = "Option::is_none")] + pub days: Option>, + ///Window end as 'HH:MM' local time + #[serde(skip_serializing_if = "Option::is_none")] + pub end_time: Option, + ///Window start as 'HH:MM' local time + #[serde(skip_serializing_if = "Option::is_none")] + pub start_time: Option, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +/// Provenance. An 'original' list was created here; a 'learned' list was saved from another user, carrying a backlink to its immediate parent (originalUri/originalDid) and to the top of its lineage (rootUri/rootDid), modelled on net.anisota.spell.custom so save counts can aggregate across re-shares. + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic, Default)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct Source { + ///DID of the user this list was saved from. + #[serde(skip_serializing_if = "Option::is_none")] + pub original_did: Option>, + ///AT URI of the list this copy was saved from (its immediate parent). + #[serde(skip_serializing_if = "Option::is_none")] + pub original_uri: Option>, + ///DID of the original author at the top of the lineage. + #[serde(skip_serializing_if = "Option::is_none")] + pub root_did: Option>, + ///AT URI of the first author's list — the top of the lineage — propagated to every descendant. + #[serde(skip_serializing_if = "Option::is_none")] + pub root_uri: Option>, + #[serde(skip_serializing_if = "Option::is_none")] + pub r#type: Option>, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub enum SourceType { + Original, + Learned, + Other(S), +} + +impl SourceType { + pub fn as_str(&self) -> &str { + match self { + Self::Original => "original", + Self::Learned => "learned", + 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() { + "original" => Self::Original, + "learned" => Self::Learned, + _ => Self::Other(s), + } + } +} + +impl core::fmt::Display for SourceType { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!(f, "{}", self.as_str()) + } +} + +impl AsRef for SourceType { + fn as_ref(&self) -> &str { + self.as_str() + } +} + +impl Serialize for SourceType { + 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 SourceType { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = S::deserialize(deserializer)?; + Ok(Self::from_value(s)) + } +} + +impl Default for SourceType { + fn default() -> Self { + Self::Other(Default::default()) + } +} + +impl jacquard_common::IntoStatic for SourceType +where + S: BosStr + jacquard_common::IntoStatic, + S::Output: BosStr, +{ + type Output = SourceType; + fn into_static(self) -> Self::Output { + match self { + SourceType::Original => SourceType::Original, + SourceType::Learned => SourceType::Learned, + SourceType::Other(v) => SourceType::Other(v.into_static()), + } + } +} + +/// One muted word or phrase, matching the shape of Bluesky's mutedWord items so a list can be projected into the native preference losslessly. + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic, Default)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct Word { + ///Whose posts to apply this word to. Absent means 'all'. + #[serde(skip_serializing_if = "Option::is_none")] + pub actor_target: Option>, + ///What to match against: post text ('content') and/or hashtags ('tag'). Absent means both. + #[serde(skip_serializing_if = "Option::is_none")] + pub targets: Option>, + ///The word or phrase to mute + pub value: S, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +/// Whose posts to apply this word to. Absent means 'all'. + +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub enum WordActorTarget { + All, + ExcludeFollowing, + Other(S), +} + +impl WordActorTarget { + pub fn as_str(&self) -> &str { + match self { + Self::All => "all", + Self::ExcludeFollowing => "exclude-following", + 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() { + "all" => Self::All, + "exclude-following" => Self::ExcludeFollowing, + _ => Self::Other(s), + } + } +} + +impl core::fmt::Display for WordActorTarget { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!(f, "{}", self.as_str()) + } +} + +impl AsRef for WordActorTarget { + fn as_ref(&self) -> &str { + self.as_str() + } +} + +impl Serialize for WordActorTarget { + 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 WordActorTarget { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = S::deserialize(deserializer)?; + Ok(Self::from_value(s)) + } +} + +impl Default for WordActorTarget { + fn default() -> Self { + Self::Other(Default::default()) + } +} + +impl jacquard_common::IntoStatic for WordActorTarget +where + S: BosStr + jacquard_common::IntoStatic, + S::Output: BosStr, +{ + type Output = WordActorTarget; + fn into_static(self) -> Self::Output { + match self { + WordActorTarget::All => WordActorTarget::All, + WordActorTarget::ExcludeFollowing => WordActorTarget::ExcludeFollowing, + WordActorTarget::Other(v) => WordActorTarget::Other(v.into_static()), + } + } +} + +impl Wordlist { + 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 WordlistRecord; +impl XrpcResp for WordlistRecord { + const NSID: &'static str = "net.anisota.graph.wordlist"; + const ENCODING: &'static str = "application/json"; + type Output = WordlistGetRecordOutput; + type Err = RecordError; +} + +impl From> for Wordlist { + fn from(output: WordlistGetRecordOutput) -> Self { + output.value + } +} + +impl Collection for Wordlist { + const NSID: &'static str = "net.anisota.graph.wordlist"; + type Record = WordlistRecord; +} + +impl Collection for WordlistRecord { + const NSID: &'static str = "net.anisota.graph.wordlist"; + type Record = WordlistRecord; +} + +impl LexiconSchema for Wordlist { + fn nsid() -> &'static str { + "net.anisota.graph.wordlist" + } + fn def_name() -> &'static str { + "main" + } + fn lexicon_doc() -> LexiconDoc<'static> { + lexicon_doc_net_anisota_graph_wordlist() + } + fn validate(&self) -> Result<(), ConstraintError> { + if let Some(ref value) = self.description { + #[allow(unused_comparisons)] + if ::len(value.as_ref()) > 300usize { + return Err(ConstraintError::MaxLength { + path: ValidationPath::from_field("description"), + max: 300usize, + actual: ::len(value.as_ref()), + }); + } + } + { + let value = &self.name; + #[allow(unused_comparisons)] + if ::len(value.as_ref()) > 64usize { + return Err(ConstraintError::MaxLength { + path: ValidationPath::from_field("name"), + max: 64usize, + actual: ::len(value.as_ref()), + }); + } + } + if let Some(ref value) = self.strength { + if *value > 100i64 { + return Err(ConstraintError::Maximum { + path: ValidationPath::from_field("strength"), + max: 100i64, + actual: *value, + }); + } + } + if let Some(ref value) = self.strength { + if *value < 0i64 { + return Err(ConstraintError::Minimum { + path: ValidationPath::from_field("strength"), + min: 0i64, + actual: *value, + }); + } + } + if let Some(ref value) = self.target_feeds { + #[allow(unused_comparisons)] + if value.len() > 50usize { + return Err(ConstraintError::MaxLength { + path: ValidationPath::from_field("target_feeds"), + max: 50usize, + actual: value.len(), + }); + } + } + if let Some(values) = &self.target_feeds { + for value in values { + #[allow(unused_comparisons)] + if ::len(value.as_ref()) > 512usize { + return Err(ConstraintError::MaxLength { + path: ValidationPath::from_field("target_feeds"), + max: 512usize, + actual: ::len(value.as_ref()), + }); + } + } + } + { + let value = &self.words; + #[allow(unused_comparisons)] + if value.len() > 500usize { + return Err(ConstraintError::MaxLength { + path: ValidationPath::from_field("words"), + max: 500usize, + actual: value.len(), + }); + } + } + Ok(()) + } +} + +impl LexiconSchema for Schedule { + fn nsid() -> &'static str { + "net.anisota.graph.wordlist" + } + fn def_name() -> &'static str { + "schedule" + } + fn lexicon_doc() -> LexiconDoc<'static> { + lexicon_doc_net_anisota_graph_wordlist() + } + fn validate(&self) -> Result<(), ConstraintError> { + if let Some(ref value) = self.days { + #[allow(unused_comparisons)] + if value.len() > 7usize { + return Err(ConstraintError::MaxLength { + path: ValidationPath::from_field("days"), + max: 7usize, + actual: value.len(), + }); + } + } + if let Some(values) = &self.days { + for value in values { + if *value > 6i64 { + return Err(ConstraintError::Maximum { + path: ValidationPath::from_field("days"), + max: 6i64, + actual: *value, + }); + } + } + } + if let Some(values) = &self.days { + for value in values { + if *value < 0i64 { + return Err(ConstraintError::Minimum { + path: ValidationPath::from_field("days"), + min: 0i64, + actual: *value, + }); + } + } + } + if let Some(ref value) = self.end_time { + #[allow(unused_comparisons)] + if ::len(value.as_ref()) > 5usize { + return Err(ConstraintError::MaxLength { + path: ValidationPath::from_field("end_time"), + max: 5usize, + actual: ::len(value.as_ref()), + }); + } + } + if let Some(ref value) = self.start_time { + #[allow(unused_comparisons)] + if ::len(value.as_ref()) > 5usize { + return Err(ConstraintError::MaxLength { + path: ValidationPath::from_field("start_time"), + max: 5usize, + actual: ::len(value.as_ref()), + }); + } + } + Ok(()) + } +} + +impl LexiconSchema for Source { + fn nsid() -> &'static str { + "net.anisota.graph.wordlist" + } + fn def_name() -> &'static str { + "source" + } + fn lexicon_doc() -> LexiconDoc<'static> { + lexicon_doc_net_anisota_graph_wordlist() + } + fn validate(&self) -> Result<(), ConstraintError> { + Ok(()) + } +} + +impl LexiconSchema for Word { + fn nsid() -> &'static str { + "net.anisota.graph.wordlist" + } + fn def_name() -> &'static str { + "word" + } + fn lexicon_doc() -> LexiconDoc<'static> { + lexicon_doc_net_anisota_graph_wordlist() + } + fn validate(&self) -> Result<(), ConstraintError> { + { + let value = &self.value; + #[allow(unused_comparisons)] + if ::len(value.as_ref()) > 100usize { + return Err(ConstraintError::MaxLength { + path: ValidationPath::from_field("value"), + max: 100usize, + actual: ::len(value.as_ref()), + }); + } + } + Ok(()) + } +} + +fn _default_wordlist_enabled() -> Option { + Some(false) +} + +fn _default_wordlist_sync_to_bluesky() -> Option { + Some(false) +} + +pub mod wordlist_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 Name; + type Words; + } + /// Empty state - all required fields are unset + pub struct Empty(()); + impl sealed::Sealed for Empty {} + impl State for Empty { + type CreatedAt = Unset; + type Name = Unset; + type Words = 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 Name = St::Name; + type Words = St::Words; + } + ///State transition - sets the `name` field to Set + pub struct SetName(PhantomData St>); + impl sealed::Sealed for SetName {} + impl State for SetName { + type CreatedAt = St::CreatedAt; + type Name = Set; + type Words = St::Words; + } + ///State transition - sets the `words` field to Set + pub struct SetWords(PhantomData St>); + impl sealed::Sealed for SetWords {} + impl State for SetWords { + type CreatedAt = St::CreatedAt; + type Name = St::Name; + type Words = 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 `name` field + pub struct name(()); + ///Marker type for the `words` field + pub struct words(()); + } +} + +/// Builder for constructing an instance of this type. +pub struct WordlistBuilder { + _state: PhantomData St>, + _fields: ( + Option, + Option, + Option, + Option, + Option>, + Option>, + Option, + Option, + Option>, + Option>, + Option, + Option>>, + ), + _type: PhantomData S>, +} + +impl Wordlist { + /// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed + pub fn new() -> WordlistBuilder { + WordlistBuilder::new() + } +} + +impl Wordlist { + /// Create a new builder for this type + pub fn builder() -> WordlistBuilder { + WordlistBuilder::builder() + } +} + +impl WordlistBuilder { + /// Create a new builder with all fields unset, using the default string type, if needed + pub fn new() -> Self { + WordlistBuilder { + _state: PhantomData, + _fields: ( + None, None, None, None, None, None, None, None, None, None, None, None, + ), + _type: PhantomData, + } + } +} + +impl WordlistBuilder { + /// Create a new builder with all fields unset + pub fn builder() -> Self { + WordlistBuilder { + _state: PhantomData, + _fields: ( + None, None, None, None, None, None, None, None, None, None, None, None, + ), + _type: PhantomData, + } + } +} + +impl WordlistBuilder +where + St: wordlist_state::State, + St::CreatedAt: wordlist_state::IsUnset, +{ + /// Set the `createdAt` field (required) + pub fn created_at( + mut self, + value: impl Into, + ) -> WordlistBuilder, S> { + self._fields.0 = Option::Some(value.into()); + WordlistBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl WordlistBuilder { + /// Set the `description` field (optional) + pub fn description(mut self, value: impl Into>) -> Self { + self._fields.1 = value.into(); + self + } + /// Set the `description` field to an Option value (optional) + pub fn maybe_description(mut self, value: Option) -> Self { + self._fields.1 = value; + self + } +} + +impl WordlistBuilder { + /// Set the `enabled` field (optional) + pub fn enabled(mut self, value: impl Into>) -> Self { + self._fields.2 = value.into(); + self + } + /// Set the `enabled` field to an Option value (optional) + pub fn maybe_enabled(mut self, value: Option) -> Self { + self._fields.2 = value; + self + } +} + +impl WordlistBuilder +where + St: wordlist_state::State, + St::Name: wordlist_state::IsUnset, +{ + /// Set the `name` field (required) + pub fn name(mut self, value: impl Into) -> WordlistBuilder, S> { + self._fields.3 = Option::Some(value.into()); + WordlistBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl WordlistBuilder { + /// Set the `schedule` field (optional) + pub fn schedule(mut self, value: impl Into>>) -> Self { + self._fields.4 = value.into(); + self + } + /// Set the `schedule` field to an Option value (optional) + pub fn maybe_schedule(mut self, value: Option>) -> Self { + self._fields.4 = value; + self + } +} + +impl WordlistBuilder { + /// Set the `source` field (optional) + pub fn source(mut self, value: impl Into>>) -> Self { + self._fields.5 = value.into(); + self + } + /// Set the `source` field to an Option value (optional) + pub fn maybe_source(mut self, value: Option>) -> Self { + self._fields.5 = value; + self + } +} + +impl WordlistBuilder { + /// Set the `strength` field (optional) + pub fn strength(mut self, value: impl Into>) -> Self { + self._fields.6 = value.into(); + self + } + /// Set the `strength` field to an Option value (optional) + pub fn maybe_strength(mut self, value: Option) -> Self { + self._fields.6 = value; + self + } +} + +impl WordlistBuilder { + /// Set the `syncToBluesky` field (optional) + pub fn sync_to_bluesky(mut self, value: impl Into>) -> Self { + self._fields.7 = value.into(); + self + } + /// Set the `syncToBluesky` field to an Option value (optional) + pub fn maybe_sync_to_bluesky(mut self, value: Option) -> Self { + self._fields.7 = value; + self + } +} + +impl WordlistBuilder { + /// Set the `targetFeeds` field (optional) + pub fn target_feeds(mut self, value: impl Into>>) -> Self { + self._fields.8 = value.into(); + self + } + /// Set the `targetFeeds` field to an Option value (optional) + pub fn maybe_target_feeds(mut self, value: Option>) -> Self { + self._fields.8 = value; + self + } +} + +impl WordlistBuilder { + /// Set the `treatment` field (optional) + pub fn treatment(mut self, value: impl Into>>) -> Self { + self._fields.9 = value.into(); + self + } + /// Set the `treatment` field to an Option value (optional) + pub fn maybe_treatment(mut self, value: Option>) -> Self { + self._fields.9 = value; + self + } +} + +impl WordlistBuilder { + /// Set the `updatedAt` field (optional) + pub fn updated_at(mut self, value: impl Into>) -> Self { + self._fields.10 = value.into(); + self + } + /// Set the `updatedAt` field to an Option value (optional) + pub fn maybe_updated_at(mut self, value: Option) -> Self { + self._fields.10 = value; + self + } +} + +impl WordlistBuilder +where + St: wordlist_state::State, + St::Words: wordlist_state::IsUnset, +{ + /// Set the `words` field (required) + pub fn words( + mut self, + value: impl Into>>, + ) -> WordlistBuilder, S> { + self._fields.11 = Option::Some(value.into()); + WordlistBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl WordlistBuilder +where + St: wordlist_state::State, + St::CreatedAt: wordlist_state::IsSet, + St::Name: wordlist_state::IsSet, + St::Words: wordlist_state::IsSet, +{ + /// Build the final struct. + pub fn build(self) -> Wordlist { + Wordlist { + created_at: self._fields.0.unwrap(), + description: self._fields.1, + enabled: self._fields.2.or_else(|| Some(false)), + name: self._fields.3.unwrap(), + schedule: self._fields.4, + source: self._fields.5, + strength: self._fields.6, + sync_to_bluesky: self._fields.7.or_else(|| Some(false)), + target_feeds: self._fields.8, + treatment: self._fields.9, + updated_at: self._fields.10, + words: self._fields.11.unwrap(), + extra_data: Default::default(), + } + } + /// Build the final struct with custom extra_data. + pub fn build_with_data(self, extra_data: BTreeMap>) -> Wordlist { + Wordlist { + created_at: self._fields.0.unwrap(), + description: self._fields.1, + enabled: self._fields.2.or_else(|| Some(false)), + name: self._fields.3.unwrap(), + schedule: self._fields.4, + source: self._fields.5, + strength: self._fields.6, + sync_to_bluesky: self._fields.7.or_else(|| Some(false)), + target_feeds: self._fields.8, + treatment: self._fields.9, + updated_at: self._fields.10, + words: self._fields.11.unwrap(), + extra_data: Some(extra_data), + } + } +} + +fn lexicon_doc_net_anisota_graph_wordlist() -> 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("net.anisota.graph.wordlist"), + defs: { + let mut map = BTreeMap::new(); + map.insert( + SmolStr::new_static("main"), + LexUserType::Record(LexRecord { + description: Some( + CowStr::new_static( + "A named, shareable list of muted words/phrases — Anisota's managed layer on top of Bluesky's flat muted-words preference. Each list is a complete, self-contained record so it can be shared by URL and saved (copied) into another user's PDS, mirroring the net.anisota.spell.custom architecture. Muting is applied client-side by the moderation pipeline: multiple enabled lists combine, a list can be scoped to specific feeds, restricted to a time-of-day/day-of-week window, and softened with a strength percentage (mute only that share of matching posts, deterministically per post). A list can optionally be projected into Bluesky's native mutedWordsPref for parity with other clients.", + ), + ), + key: Some(CowStr::new_static("tid")), + record: LexRecordRecord::Object(LexObject { + required: Some( + vec![ + SmolStr::new_static("name"), SmolStr::new_static("words"), + SmolStr::new_static("createdAt") + ], + ), + properties: { + #[allow(unused_mut)] + let mut map = BTreeMap::new(); + map.insert( + SmolStr::new_static("createdAt"), + LexObjectProperty::String(LexString { + description: Some( + CowStr::new_static("When this list was created"), + ), + format: Some(LexStringFormat::Datetime), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("description"), + LexObjectProperty::String(LexString { + description: Some( + CowStr::new_static( + "Optional description of what this list covers", + ), + ), + max_length: Some(300usize), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("enabled"), + LexObjectProperty::Boolean(LexBoolean { + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("name"), + LexObjectProperty::String(LexString { + description: Some( + CowStr::new_static("Display name for this word list"), + ), + max_length: Some(64usize), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("schedule"), + LexObjectProperty::Ref(LexRef { + r#ref: CowStr::new_static("#schedule"), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("source"), + LexObjectProperty::Ref(LexRef { + r#ref: CowStr::new_static("#source"), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("strength"), + LexObjectProperty::Integer(LexInteger { + minimum: Some(0i64), + maximum: Some(100i64), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("syncToBluesky"), + LexObjectProperty::Boolean(LexBoolean { + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("targetFeeds"), + LexObjectProperty::Array(LexArray { + description: Some( + CowStr::new_static( + "Feeds where this list applies: feed generator / list at-uris, or the literal sentinel 'following' for the home timeline. Empty or absent applies everywhere.", + ), + ), + items: LexArrayItem::String(LexString { + max_length: Some(512usize), + ..Default::default() + }), + max_length: Some(50usize), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("treatment"), + LexObjectProperty::String(LexString { + description: Some( + CowStr::new_static( + "What this list does to a post it mutes, overriding the app-wide muted-words handling: 'hide' removes it from feeds, 'warn' collapses it behind a notice, 'show' leaves it visible and only counts it toward impact. Absent inherits the global setting.", + ), + ), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("updatedAt"), + LexObjectProperty::String(LexString { + description: Some( + CowStr::new_static("When this list was last modified"), + ), + format: Some(LexStringFormat::Datetime), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("words"), + LexObjectProperty::Array(LexArray { + description: Some( + CowStr::new_static("The muted words/phrases in this list"), + ), + items: LexArrayItem::Ref(LexRef { + r#ref: CowStr::new_static("#word"), + ..Default::default() + }), + max_length: Some(500usize), + ..Default::default() + }), + ); + map + }, + ..Default::default() + }), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("schedule"), + LexUserType::Object(LexObject { + description: Some( + CowStr::new_static( + "A recurring active window. Days and time window combine: the list applies only on the listed days (absent/empty = every day) and only inside the time window (absent = all day). A window whose end is at or before its start wraps past midnight.", + ), + ), + properties: { + #[allow(unused_mut)] + let mut map = BTreeMap::new(); + map.insert( + SmolStr::new_static("days"), + LexObjectProperty::Array(LexArray { + description: Some( + CowStr::new_static( + "Days of week the list is active (0 = Sunday … 6 = Saturday)", + ), + ), + items: LexArrayItem::Integer(LexInteger { + ..Default::default() + }), + max_length: Some(7usize), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("endTime"), + LexObjectProperty::String(LexString { + description: Some( + CowStr::new_static("Window end as 'HH:MM' local time"), + ), + max_length: Some(5usize), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("startTime"), + LexObjectProperty::String(LexString { + description: Some( + CowStr::new_static("Window start as 'HH:MM' local time"), + ), + max_length: Some(5usize), + ..Default::default() + }), + ); + map + }, + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("source"), + LexUserType::Object(LexObject { + description: Some( + CowStr::new_static( + "Provenance. An 'original' list was created here; a 'learned' list was saved from another user, carrying a backlink to its immediate parent (originalUri/originalDid) and to the top of its lineage (rootUri/rootDid), modelled on net.anisota.spell.custom so save counts can aggregate across re-shares.", + ), + ), + properties: { + #[allow(unused_mut)] + let mut map = BTreeMap::new(); + map.insert( + SmolStr::new_static("originalDid"), + LexObjectProperty::String(LexString { + description: Some( + CowStr::new_static( + "DID of the user this list was saved from.", + ), + ), + format: Some(LexStringFormat::Did), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("originalUri"), + LexObjectProperty::String(LexString { + description: Some( + CowStr::new_static( + "AT URI of the list this copy was saved from (its immediate parent).", + ), + ), + format: Some(LexStringFormat::AtUri), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("rootDid"), + LexObjectProperty::String(LexString { + description: Some( + CowStr::new_static( + "DID of the original author at the top of the lineage.", + ), + ), + format: Some(LexStringFormat::Did), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("rootUri"), + LexObjectProperty::String(LexString { + description: Some( + CowStr::new_static( + "AT URI of the first author's list — the top of the lineage — propagated to every descendant.", + ), + ), + format: Some(LexStringFormat::AtUri), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("type"), + LexObjectProperty::String(LexString { ..Default::default() }), + ); + map + }, + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("word"), + LexUserType::Object(LexObject { + description: Some( + CowStr::new_static( + "One muted word or phrase, matching the shape of Bluesky's mutedWord items so a list can be projected into the native preference losslessly.", + ), + ), + required: Some(vec![SmolStr::new_static("value")]), + properties: { + #[allow(unused_mut)] + let mut map = BTreeMap::new(); + map.insert( + SmolStr::new_static("actorTarget"), + LexObjectProperty::String(LexString { + description: Some( + CowStr::new_static( + "Whose posts to apply this word to. Absent means 'all'.", + ), + ), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("targets"), + LexObjectProperty::Array(LexArray { + description: Some( + CowStr::new_static( + "What to match against: post text ('content') and/or hashtags ('tag'). Absent means both.", + ), + ), + items: LexArrayItem::String(LexString { + ..Default::default() + }), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("value"), + LexObjectProperty::String(LexString { + description: Some( + CowStr::new_static("The word or phrase to mute"), + ), + max_length: Some(100usize), + ..Default::default() + }), + ); + map + }, + ..Default::default() + }), + ); + map + }, + ..Default::default() + } +} diff --git a/crates/jacquard-api/src/net_anisota/lab.rs b/crates/jacquard-api/src/net_anisota/lab.rs index 1a38a74e6..1b8af20a0 100644 --- a/crates/jacquard-api/src/net_anisota/lab.rs +++ b/crates/jacquard-api/src/net_anisota/lab.rs @@ -8,6 +8,7 @@ pub mod carving; pub mod inkblot; pub mod nightsky; pub mod petri; +pub mod plasmodium; pub mod poetry; pub mod redaction; pub mod sigil; diff --git a/crates/jacquard-api/src/net_anisota/lab/inkblot.rs b/crates/jacquard-api/src/net_anisota/lab/inkblot.rs index 8260cf132..5fc16a9fc 100644 --- a/crates/jacquard-api/src/net_anisota/lab/inkblot.rs +++ b/crates/jacquard-api/src/net_anisota/lab/inkblot.rs @@ -42,7 +42,7 @@ use serde::{Deserialize, Serialize}; pub struct Inkblot { ///When the inkblot was saved pub created_at: Datetime, - ///A rendered PNG of the blot as a data URL, for display + ///A rendered still of the blot as an image data URL (PNG, or WebP when a denser blot needs the more compact encoding to stay sharp within the size cap), for display #[serde(skip_serializing_if = "Option::is_none")] pub image: Option, ///Ink palette id (classic, sepia, indigo, blood, moss) @@ -398,7 +398,7 @@ fn lexicon_doc_net_anisota_lab_inkblot() -> LexiconDoc<'static> { LexObjectProperty::String(LexString { description: Some( CowStr::new_static( - "A rendered PNG of the blot as a data URL, for display", + "A rendered still of the blot as an image data URL (PNG, or WebP when a denser blot needs the more compact encoding to stay sharp within the size cap), for display", ), ), max_length: Some(200000usize), diff --git a/crates/jacquard-api/src/net_anisota/lab/plasmodium.rs b/crates/jacquard-api/src/net_anisota/lab/plasmodium.rs new file mode 100644 index 000000000..e575a0b22 --- /dev/null +++ b/crates/jacquard-api/src/net_anisota/lab/plasmodium.rs @@ -0,0 +1,1207 @@ +// @generated by jacquard-lexicon. DO NOT EDIT. +// +// Lexicon: net.anisota.lab.plasmodium +// +// 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}; +/// A Physarum (slime-mould) organism grown in the Anisota Lab's Plasmodium workbench and saved to the owner's collection. Stored as its recipe rather than its pixels: a 'seed', the simulation 'gridSize', a 'genome' of behavioural parameters (all continuous 0..1 tunables scaled to integers 0..1000, since atproto lexicons have no float type), and the ordered 'foods' and 'inoculations' the grower placed. Because the GPU agent simulation is deterministic given the same seed, genome and placements, replaying the recipe regrows the organism. A small PNG thumbnail is kept for display. + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + rename = "net.anisota.lab.plasmodium", + tag = "$type", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct Plasmodium { + ///Agent-count tier that grew it (0=small, 1=medium, 2=large). A reopen may cap lower on a weaker device. + #[serde(skip_serializing_if = "Option::is_none")] + pub agent_tier: Option, + ///When the organism was saved + pub created_at: Datetime, + ///Ordered food drops the grower placed; each replayed at its step so growth rebuilds identically. + #[serde(skip_serializing_if = "Option::is_none")] + pub foods: Option>>, + ///Behavioural parameters. Global tunables plus one species entry (two when multiSpecies). Continuous values are scaled to integers 0..1000; enumerated traits (spawn, interMode, renderMode) are small raw integer indices. + pub genome: PlasmodiumGenome, + ///Trail-field grid resolution in cells (square) + pub grid_size: i64, + ///A PNG data URL thumbnail of the organism + #[serde(skip_serializing_if = "Option::is_none")] + pub image: Option, + ///Ordered inoculation taps (respawned agent patches). + #[serde(skip_serializing_if = "Option::is_none")] + pub inoculations: Option>>, + ///When the organism last advanced, used to grow it forward on reopen + #[serde(skip_serializing_if = "Option::is_none")] + pub last_tick_at: Option, + ///Whether a second agent population was active + #[serde(skip_serializing_if = "Option::is_none")] + pub multi_species: Option, + ///Display name for the organism + pub name: S, + ///Colour palette id (amber, ember, lichen, frost, mono) + #[serde(skip_serializing_if = "Option::is_none")] + pub palette: Option, + ///PRNG seed the simulation and genome were initialised with + pub seed: i64, + ///How many simulation steps the organism had grown when saved + #[serde(skip_serializing_if = "Option::is_none")] + pub steps: Option, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +/// Behavioural parameters. Global tunables plus one species entry (two when multiSpecies). Continuous values are scaled to integers 0..1000; enumerated traits (spawn, interMode, renderMode) are small raw integer indices. + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct PlasmodiumGenome { + ///Diffusion (3x3 blur) strength, 0..1000 + #[serde(skip_serializing_if = "Option::is_none")] + pub blur: Option, + ///How strongly agents are drawn to the food channel, 0..1000 + #[serde(skip_serializing_if = "Option::is_none")] + pub food_weight: Option, + ///Cross-species interaction index: 0 ignore, 1 attract, 2 repel, 3 predator/prey, 4 symbiosis, 5 competition + #[serde(skip_serializing_if = "Option::is_none")] + pub inter_mode: Option, + ///Cross-species coupling strength, 0..1000 + #[serde(skip_serializing_if = "Option::is_none")] + pub inter_strength: Option, + ///Initial spawn pattern index: 0 scatter, 1 ring, 2 spore, 3 colonies, 4 poles, 5 spiral + #[serde(skip_serializing_if = "Option::is_none")] + pub spawn: Option, + ///One entry per agent population + pub species: Vec>, + #[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 PlasmodiumGetRecordOutput { + #[serde(skip_serializing_if = "Option::is_none")] + pub cid: Option>, + pub uri: AtUri, + pub value: Plasmodium, +} + +impl Plasmodium { + 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 PlasmodiumRecord; +impl XrpcResp for PlasmodiumRecord { + const NSID: &'static str = "net.anisota.lab.plasmodium"; + const ENCODING: &'static str = "application/json"; + type Output = PlasmodiumGetRecordOutput; + type Err = RecordError; +} + +impl From> for Plasmodium { + fn from(output: PlasmodiumGetRecordOutput) -> Self { + output.value + } +} + +impl Collection for Plasmodium { + const NSID: &'static str = "net.anisota.lab.plasmodium"; + type Record = PlasmodiumRecord; +} + +impl Collection for PlasmodiumRecord { + const NSID: &'static str = "net.anisota.lab.plasmodium"; + type Record = PlasmodiumRecord; +} + +impl LexiconSchema for Plasmodium { + fn nsid() -> &'static str { + "net.anisota.lab.plasmodium" + } + fn def_name() -> &'static str { + "main" + } + fn lexicon_doc() -> LexiconDoc<'static> { + lexicon_doc_net_anisota_lab_plasmodium() + } + fn validate(&self) -> Result<(), ConstraintError> { + if let Some(ref value) = self.foods { + #[allow(unused_comparisons)] + if value.len() > 256usize { + return Err(ConstraintError::MaxLength { + path: ValidationPath::from_field("foods"), + max: 256usize, + actual: value.len(), + }); + } + } + if let Some(ref value) = self.image { + #[allow(unused_comparisons)] + if ::len(value.as_ref()) > 120000usize { + return Err(ConstraintError::MaxLength { + path: ValidationPath::from_field("image"), + max: 120000usize, + actual: ::len(value.as_ref()), + }); + } + } + if let Some(ref value) = self.inoculations { + #[allow(unused_comparisons)] + if value.len() > 256usize { + return Err(ConstraintError::MaxLength { + path: ValidationPath::from_field("inoculations"), + max: 256usize, + actual: value.len(), + }); + } + } + { + let value = &self.name; + #[allow(unused_comparisons)] + if ::len(value.as_ref()) > 800usize { + return Err(ConstraintError::MaxLength { + path: ValidationPath::from_field("name"), + max: 800usize, + actual: ::len(value.as_ref()), + }); + } + } + { + let value = &self.name; + { + let count = UnicodeSegmentation::graphemes(value.as_ref(), true).count(); + if count > 100usize { + return Err(ConstraintError::MaxGraphemes { + path: ValidationPath::from_field("name"), + max: 100usize, + actual: count, + }); + } + } + } + if let Some(ref value) = self.palette { + #[allow(unused_comparisons)] + if ::len(value.as_ref()) > 40usize { + return Err(ConstraintError::MaxLength { + path: ValidationPath::from_field("palette"), + max: 40usize, + actual: ::len(value.as_ref()), + }); + } + } + Ok(()) + } +} + +impl LexiconSchema for PlasmodiumGenome { + fn nsid() -> &'static str { + "net.anisota.lab.plasmodium" + } + fn def_name() -> &'static str { + "PlasmodiumGenome" + } + fn lexicon_doc() -> LexiconDoc<'static> { + lexicon_doc_net_anisota_lab_plasmodium() + } + fn validate(&self) -> Result<(), ConstraintError> { + Ok(()) + } +} + +pub mod plasmodium_genome_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 Species; + } + /// Empty state - all required fields are unset + pub struct Empty(()); + impl sealed::Sealed for Empty {} + impl State for Empty { + type Species = Unset; + } + ///State transition - sets the `species` field to Set + pub struct SetSpecies(PhantomData St>); + impl sealed::Sealed for SetSpecies {} + impl State for SetSpecies { + type Species = Set; + } + /// Marker types for field names + #[allow(non_camel_case_types)] + pub mod members { + ///Marker type for the `species` field + pub struct species(()); + } +} + +/// Builder for constructing an instance of this type. +pub struct PlasmodiumGenomeBuilder { + _state: PhantomData St>, + _fields: ( + Option, + Option, + Option, + Option, + Option, + Option>>, + ), + _type: PhantomData S>, +} + +impl PlasmodiumGenome { + /// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed + pub fn new() -> PlasmodiumGenomeBuilder { + PlasmodiumGenomeBuilder::new() + } +} + +impl PlasmodiumGenome { + /// Create a new builder for this type + pub fn builder() -> PlasmodiumGenomeBuilder { + PlasmodiumGenomeBuilder::builder() + } +} + +impl PlasmodiumGenomeBuilder { + /// Create a new builder with all fields unset, using the default string type, if needed + pub fn new() -> Self { + PlasmodiumGenomeBuilder { + _state: PhantomData, + _fields: (None, None, None, None, None, None), + _type: PhantomData, + } + } +} + +impl PlasmodiumGenomeBuilder { + /// Create a new builder with all fields unset + pub fn builder() -> Self { + PlasmodiumGenomeBuilder { + _state: PhantomData, + _fields: (None, None, None, None, None, None), + _type: PhantomData, + } + } +} + +impl PlasmodiumGenomeBuilder { + /// Set the `blur` field (optional) + pub fn blur(mut self, value: impl Into>) -> Self { + self._fields.0 = value.into(); + self + } + /// Set the `blur` field to an Option value (optional) + pub fn maybe_blur(mut self, value: Option) -> Self { + self._fields.0 = value; + self + } +} + +impl PlasmodiumGenomeBuilder { + /// Set the `foodWeight` field (optional) + pub fn food_weight(mut self, value: impl Into>) -> Self { + self._fields.1 = value.into(); + self + } + /// Set the `foodWeight` field to an Option value (optional) + pub fn maybe_food_weight(mut self, value: Option) -> Self { + self._fields.1 = value; + self + } +} + +impl PlasmodiumGenomeBuilder { + /// Set the `interMode` field (optional) + pub fn inter_mode(mut self, value: impl Into>) -> Self { + self._fields.2 = value.into(); + self + } + /// Set the `interMode` field to an Option value (optional) + pub fn maybe_inter_mode(mut self, value: Option) -> Self { + self._fields.2 = value; + self + } +} + +impl PlasmodiumGenomeBuilder { + /// Set the `interStrength` field (optional) + pub fn inter_strength(mut self, value: impl Into>) -> Self { + self._fields.3 = value.into(); + self + } + /// Set the `interStrength` field to an Option value (optional) + pub fn maybe_inter_strength(mut self, value: Option) -> Self { + self._fields.3 = value; + self + } +} + +impl PlasmodiumGenomeBuilder { + /// Set the `spawn` field (optional) + pub fn spawn(mut self, value: impl Into>) -> Self { + self._fields.4 = value.into(); + self + } + /// Set the `spawn` field to an Option value (optional) + pub fn maybe_spawn(mut self, value: Option) -> Self { + self._fields.4 = value; + self + } +} + +impl PlasmodiumGenomeBuilder +where + St: plasmodium_genome_state::State, + St::Species: plasmodium_genome_state::IsUnset, +{ + /// Set the `species` field (required) + pub fn species( + mut self, + value: impl Into>>, + ) -> PlasmodiumGenomeBuilder, S> { + self._fields.5 = Option::Some(value.into()); + PlasmodiumGenomeBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl PlasmodiumGenomeBuilder +where + St: plasmodium_genome_state::State, + St::Species: plasmodium_genome_state::IsSet, +{ + /// Build the final struct. + pub fn build(self) -> PlasmodiumGenome { + PlasmodiumGenome { + blur: self._fields.0, + food_weight: self._fields.1, + inter_mode: self._fields.2, + inter_strength: self._fields.3, + spawn: self._fields.4, + species: self._fields.5.unwrap(), + extra_data: Default::default(), + } + } + /// Build the final struct with custom extra_data. + pub fn build_with_data(self, extra_data: BTreeMap>) -> PlasmodiumGenome { + PlasmodiumGenome { + blur: self._fields.0, + food_weight: self._fields.1, + inter_mode: self._fields.2, + inter_strength: self._fields.3, + spawn: self._fields.4, + species: self._fields.5.unwrap(), + extra_data: Some(extra_data), + } + } +} + +fn lexicon_doc_net_anisota_lab_plasmodium() -> 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("net.anisota.lab.plasmodium"), + defs: { + let mut map = BTreeMap::new(); + map.insert( + SmolStr::new_static("main"), + LexUserType::Record(LexRecord { + description: Some( + CowStr::new_static( + "A Physarum (slime-mould) organism grown in the Anisota Lab's Plasmodium workbench and saved to the owner's collection. Stored as its recipe rather than its pixels: a 'seed', the simulation 'gridSize', a 'genome' of behavioural parameters (all continuous 0..1 tunables scaled to integers 0..1000, since atproto lexicons have no float type), and the ordered 'foods' and 'inoculations' the grower placed. Because the GPU agent simulation is deterministic given the same seed, genome and placements, replaying the recipe regrows the organism. A small PNG thumbnail is kept for display.", + ), + ), + key: Some(CowStr::new_static("any")), + record: LexRecordRecord::Object(LexObject { + required: Some( + vec![ + SmolStr::new_static("name"), SmolStr::new_static("seed"), + SmolStr::new_static("gridSize"), + SmolStr::new_static("genome"), + SmolStr::new_static("createdAt") + ], + ), + properties: { + #[allow(unused_mut)] + let mut map = BTreeMap::new(); + map.insert( + SmolStr::new_static("agentTier"), + LexObjectProperty::Integer(LexInteger { + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("createdAt"), + LexObjectProperty::String(LexString { + description: Some( + CowStr::new_static("When the organism was saved"), + ), + format: Some(LexStringFormat::Datetime), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("foods"), + LexObjectProperty::Array(LexArray { + description: Some( + CowStr::new_static( + "Ordered food drops the grower placed; each replayed at its step so growth rebuilds identically.", + ), + ), + items: LexArrayItem::Object(LexObject { + required: Some( + vec![ + SmolStr::new_static("x"), SmolStr::new_static("y"), + SmolStr::new_static("atStep") + ], + ), + properties: { + #[allow(unused_mut)] + let mut map = BTreeMap::new(); + map.insert( + SmolStr::new_static("atStep"), + LexObjectProperty::Integer(LexInteger { + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("r"), + LexObjectProperty::Integer(LexInteger { + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("x"), + LexObjectProperty::Integer(LexInteger { + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("y"), + LexObjectProperty::Integer(LexInteger { + ..Default::default() + }), + ); + map + }, + ..Default::default() + }), + max_length: Some(256usize), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("genome"), + LexObjectProperty::Object(LexObject { + description: Some( + CowStr::new_static( + "Behavioural parameters. Global tunables plus one species entry (two when multiSpecies). Continuous values are scaled to integers 0..1000; enumerated traits (spawn, interMode, renderMode) are small raw integer indices.", + ), + ), + required: Some(vec![SmolStr::new_static("species")]), + properties: { + #[allow(unused_mut)] + let mut map = BTreeMap::new(); + map.insert( + SmolStr::new_static("blur"), + LexObjectProperty::Integer(LexInteger { + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("foodWeight"), + LexObjectProperty::Integer(LexInteger { + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("interMode"), + LexObjectProperty::Integer(LexInteger { + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("interStrength"), + LexObjectProperty::Integer(LexInteger { + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("spawn"), + LexObjectProperty::Integer(LexInteger { + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("species"), + LexObjectProperty::Array(LexArray { + description: Some( + CowStr::new_static("One entry per agent population"), + ), + items: LexArrayItem::Object(LexObject { + required: Some( + vec![ + SmolStr::new_static("sensorAngle"), + SmolStr::new_static("rotationAngle"), + SmolStr::new_static("sensorOffset"), + SmolStr::new_static("step"), SmolStr::new_static("deposit"), + SmolStr::new_static("decay"), SmolStr::new_static("density") + ], + ), + properties: { + #[allow(unused_mut)] + let mut map = BTreeMap::new(); + map.insert( + SmolStr::new_static("decay"), + LexObjectProperty::Integer(LexInteger { + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("density"), + LexObjectProperty::Integer(LexInteger { + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("deposit"), + LexObjectProperty::Integer(LexInteger { + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("hue"), + LexObjectProperty::Integer(LexInteger { + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("renderMode"), + LexObjectProperty::Integer(LexInteger { + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("rotationAngle"), + LexObjectProperty::Integer(LexInteger { + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("sensorAngle"), + LexObjectProperty::Integer(LexInteger { + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("sensorOffset"), + LexObjectProperty::Integer(LexInteger { + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("step"), + LexObjectProperty::Integer(LexInteger { + ..Default::default() + }), + ); + map + }, + ..Default::default() + }), + max_length: Some(2usize), + ..Default::default() + }), + ); + map + }, + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("gridSize"), + LexObjectProperty::Integer(LexInteger { + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("image"), + LexObjectProperty::String(LexString { + description: Some( + CowStr::new_static( + "A PNG data URL thumbnail of the organism", + ), + ), + max_length: Some(120000usize), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("inoculations"), + LexObjectProperty::Array(LexArray { + description: Some( + CowStr::new_static( + "Ordered inoculation taps (respawned agent patches).", + ), + ), + items: LexArrayItem::Object(LexObject { + required: Some( + vec![ + SmolStr::new_static("x"), SmolStr::new_static("y"), + SmolStr::new_static("species"), + SmolStr::new_static("atStep") + ], + ), + properties: { + #[allow(unused_mut)] + let mut map = BTreeMap::new(); + map.insert( + SmolStr::new_static("atStep"), + LexObjectProperty::Integer(LexInteger { + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("r"), + LexObjectProperty::Integer(LexInteger { + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("species"), + LexObjectProperty::Integer(LexInteger { + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("x"), + LexObjectProperty::Integer(LexInteger { + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("y"), + LexObjectProperty::Integer(LexInteger { + ..Default::default() + }), + ); + map + }, + ..Default::default() + }), + max_length: Some(256usize), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("lastTickAt"), + LexObjectProperty::String(LexString { + description: Some( + CowStr::new_static( + "When the organism last advanced, used to grow it forward on reopen", + ), + ), + format: Some(LexStringFormat::Datetime), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("multiSpecies"), + LexObjectProperty::Boolean(LexBoolean { + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("name"), + LexObjectProperty::String(LexString { + description: Some( + CowStr::new_static("Display name for the organism"), + ), + max_length: Some(800usize), + max_graphemes: Some(100usize), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("palette"), + LexObjectProperty::String(LexString { + description: Some( + CowStr::new_static( + "Colour palette id (amber, ember, lichen, frost, mono)", + ), + ), + max_length: Some(40usize), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("seed"), + LexObjectProperty::Integer(LexInteger { + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("steps"), + LexObjectProperty::Integer(LexInteger { + ..Default::default() + }), + ); + map + }, + ..Default::default() + }), + ..Default::default() + }), + ); + map + }, + ..Default::default() + } +} + +pub mod plasmodium_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 Genome; + type GridSize; + type Name; + type Seed; + } + /// Empty state - all required fields are unset + pub struct Empty(()); + impl sealed::Sealed for Empty {} + impl State for Empty { + type CreatedAt = Unset; + type Genome = Unset; + type GridSize = Unset; + type Name = Unset; + type Seed = 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 Genome = St::Genome; + type GridSize = St::GridSize; + type Name = St::Name; + type Seed = St::Seed; + } + ///State transition - sets the `genome` field to Set + pub struct SetGenome(PhantomData St>); + impl sealed::Sealed for SetGenome {} + impl State for SetGenome { + type CreatedAt = St::CreatedAt; + type Genome = Set; + type GridSize = St::GridSize; + type Name = St::Name; + type Seed = St::Seed; + } + ///State transition - sets the `grid_size` field to Set + pub struct SetGridSize(PhantomData St>); + impl sealed::Sealed for SetGridSize {} + impl State for SetGridSize { + type CreatedAt = St::CreatedAt; + type Genome = St::Genome; + type GridSize = Set; + type Name = St::Name; + type Seed = St::Seed; + } + ///State transition - sets the `name` field to Set + pub struct SetName(PhantomData St>); + impl sealed::Sealed for SetName {} + impl State for SetName { + type CreatedAt = St::CreatedAt; + type Genome = St::Genome; + type GridSize = St::GridSize; + type Name = Set; + type Seed = St::Seed; + } + ///State transition - sets the `seed` field to Set + pub struct SetSeed(PhantomData St>); + impl sealed::Sealed for SetSeed {} + impl State for SetSeed { + type CreatedAt = St::CreatedAt; + type Genome = St::Genome; + type GridSize = St::GridSize; + type Name = St::Name; + type Seed = 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 `genome` field + pub struct genome(()); + ///Marker type for the `grid_size` field + pub struct grid_size(()); + ///Marker type for the `name` field + pub struct name(()); + ///Marker type for the `seed` field + pub struct seed(()); + } +} + +/// Builder for constructing an instance of this type. +pub struct PlasmodiumBuilder { + _state: PhantomData St>, + _fields: ( + Option, + Option, + Option>>, + Option>, + Option, + Option, + Option>>, + Option, + Option, + Option, + Option, + Option, + Option, + ), + _type: PhantomData S>, +} + +impl Plasmodium { + /// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed + pub fn new() -> PlasmodiumBuilder { + PlasmodiumBuilder::new() + } +} + +impl Plasmodium { + /// Create a new builder for this type + pub fn builder() -> PlasmodiumBuilder { + PlasmodiumBuilder::builder() + } +} + +impl PlasmodiumBuilder { + /// Create a new builder with all fields unset, using the default string type, if needed + pub fn new() -> Self { + PlasmodiumBuilder { + _state: PhantomData, + _fields: ( + None, None, None, None, None, None, None, None, None, None, None, None, None, + ), + _type: PhantomData, + } + } +} + +impl PlasmodiumBuilder { + /// Create a new builder with all fields unset + pub fn builder() -> Self { + PlasmodiumBuilder { + _state: PhantomData, + _fields: ( + None, None, None, None, None, None, None, None, None, None, None, None, None, + ), + _type: PhantomData, + } + } +} + +impl PlasmodiumBuilder { + /// Set the `agentTier` field (optional) + pub fn agent_tier(mut self, value: impl Into>) -> Self { + self._fields.0 = value.into(); + self + } + /// Set the `agentTier` field to an Option value (optional) + pub fn maybe_agent_tier(mut self, value: Option) -> Self { + self._fields.0 = value; + self + } +} + +impl PlasmodiumBuilder +where + St: plasmodium_state::State, + St::CreatedAt: plasmodium_state::IsUnset, +{ + /// Set the `createdAt` field (required) + pub fn created_at( + mut self, + value: impl Into, + ) -> PlasmodiumBuilder, S> { + self._fields.1 = Option::Some(value.into()); + PlasmodiumBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl PlasmodiumBuilder { + /// Set the `foods` field (optional) + pub fn foods(mut self, value: impl Into>>>) -> Self { + self._fields.2 = value.into(); + self + } + /// Set the `foods` field to an Option value (optional) + pub fn maybe_foods(mut self, value: Option>>) -> Self { + self._fields.2 = value; + self + } +} + +impl PlasmodiumBuilder +where + St: plasmodium_state::State, + St::Genome: plasmodium_state::IsUnset, +{ + /// Set the `genome` field (required) + pub fn genome( + mut self, + value: impl Into>, + ) -> PlasmodiumBuilder, S> { + self._fields.3 = Option::Some(value.into()); + PlasmodiumBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl PlasmodiumBuilder +where + St: plasmodium_state::State, + St::GridSize: plasmodium_state::IsUnset, +{ + /// Set the `gridSize` field (required) + pub fn grid_size( + mut self, + value: impl Into, + ) -> PlasmodiumBuilder, S> { + self._fields.4 = Option::Some(value.into()); + PlasmodiumBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl PlasmodiumBuilder { + /// Set the `image` field (optional) + pub fn image(mut self, value: impl Into>) -> Self { + self._fields.5 = value.into(); + self + } + /// Set the `image` field to an Option value (optional) + pub fn maybe_image(mut self, value: Option) -> Self { + self._fields.5 = value; + self + } +} + +impl PlasmodiumBuilder { + /// Set the `inoculations` field (optional) + pub fn inoculations(mut self, value: impl Into>>>) -> Self { + self._fields.6 = value.into(); + self + } + /// Set the `inoculations` field to an Option value (optional) + pub fn maybe_inoculations(mut self, value: Option>>) -> Self { + self._fields.6 = value; + self + } +} + +impl PlasmodiumBuilder { + /// Set the `lastTickAt` field (optional) + pub fn last_tick_at(mut self, value: impl Into>) -> Self { + self._fields.7 = value.into(); + self + } + /// Set the `lastTickAt` field to an Option value (optional) + pub fn maybe_last_tick_at(mut self, value: Option) -> Self { + self._fields.7 = value; + self + } +} + +impl PlasmodiumBuilder { + /// Set the `multiSpecies` field (optional) + pub fn multi_species(mut self, value: impl Into>) -> Self { + self._fields.8 = value.into(); + self + } + /// Set the `multiSpecies` field to an Option value (optional) + pub fn maybe_multi_species(mut self, value: Option) -> Self { + self._fields.8 = value; + self + } +} + +impl PlasmodiumBuilder +where + St: plasmodium_state::State, + St::Name: plasmodium_state::IsUnset, +{ + /// Set the `name` field (required) + pub fn name( + mut self, + value: impl Into, + ) -> PlasmodiumBuilder, S> { + self._fields.9 = Option::Some(value.into()); + PlasmodiumBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl PlasmodiumBuilder { + /// Set the `palette` field (optional) + pub fn palette(mut self, value: impl Into>) -> Self { + self._fields.10 = value.into(); + self + } + /// Set the `palette` field to an Option value (optional) + pub fn maybe_palette(mut self, value: Option) -> Self { + self._fields.10 = value; + self + } +} + +impl PlasmodiumBuilder +where + St: plasmodium_state::State, + St::Seed: plasmodium_state::IsUnset, +{ + /// Set the `seed` field (required) + pub fn seed( + mut self, + value: impl Into, + ) -> PlasmodiumBuilder, S> { + self._fields.11 = Option::Some(value.into()); + PlasmodiumBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl PlasmodiumBuilder { + /// Set the `steps` field (optional) + pub fn steps(mut self, value: impl Into>) -> Self { + self._fields.12 = value.into(); + self + } + /// Set the `steps` field to an Option value (optional) + pub fn maybe_steps(mut self, value: Option) -> Self { + self._fields.12 = value; + self + } +} + +impl PlasmodiumBuilder +where + St: plasmodium_state::State, + St::CreatedAt: plasmodium_state::IsSet, + St::Genome: plasmodium_state::IsSet, + St::GridSize: plasmodium_state::IsSet, + St::Name: plasmodium_state::IsSet, + St::Seed: plasmodium_state::IsSet, +{ + /// Build the final struct. + pub fn build(self) -> Plasmodium { + Plasmodium { + agent_tier: self._fields.0, + created_at: self._fields.1.unwrap(), + foods: self._fields.2, + genome: self._fields.3.unwrap(), + grid_size: self._fields.4.unwrap(), + image: self._fields.5, + inoculations: self._fields.6, + last_tick_at: self._fields.7, + multi_species: self._fields.8, + name: self._fields.9.unwrap(), + palette: self._fields.10, + seed: self._fields.11.unwrap(), + steps: self._fields.12, + extra_data: Default::default(), + } + } + /// Build the final struct with custom extra_data. + pub fn build_with_data(self, extra_data: BTreeMap>) -> Plasmodium { + Plasmodium { + agent_tier: self._fields.0, + created_at: self._fields.1.unwrap(), + foods: self._fields.2, + genome: self._fields.3.unwrap(), + grid_size: self._fields.4.unwrap(), + image: self._fields.5, + inoculations: self._fields.6, + last_tick_at: self._fields.7, + multi_species: self._fields.8, + name: self._fields.9.unwrap(), + palette: self._fields.10, + seed: self._fields.11.unwrap(), + steps: self._fields.12, + extra_data: Some(extra_data), + } + } +} diff --git a/crates/jacquard-api/src/net_anisota/observatory/layout.rs b/crates/jacquard-api/src/net_anisota/observatory/layout.rs index d09c007cd..9dfd0514f 100644 --- a/crates/jacquard-api/src/net_anisota/observatory/layout.rs +++ b/crates/jacquard-api/src/net_anisota/observatory/layout.rs @@ -137,7 +137,7 @@ pub struct Schedule { pub extra_data: Option>>, } -/// Provenance backlink for layouts learned from another user. +/// Provenance for this layout. 'original' was crafted here, 'learned' was saved from another user's shared layout (see originalUri/originalDid), and 'migrated' marks the layout the one-time unify migration captured from the user's live grid — that value is the migration's idempotency sentinel and must be preserved when a record is re-saved, or the migration will run again and duplicate the layout. #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic, Default)] #[serde( @@ -161,6 +161,7 @@ pub struct Source { pub enum SourceType { Original, Learned, + Migrated, Other(S), } @@ -169,6 +170,7 @@ impl SourceType { match self { Self::Original => "original", Self::Learned => "learned", + Self::Migrated => "migrated", Self::Other(s) => s.as_ref(), } } @@ -177,6 +179,7 @@ impl SourceType { match s.as_ref() { "original" => Self::Original, "learned" => Self::Learned, + "migrated" => Self::Migrated, _ => Self::Other(s), } } @@ -229,6 +232,7 @@ where match self { SourceType::Original => SourceType::Original, SourceType::Learned => SourceType::Learned, + SourceType::Migrated => SourceType::Migrated, SourceType::Other(v) => SourceType::Other(v.into_static()), } } @@ -266,6 +270,18 @@ impl LexiconSchema for Layout { lexicon_doc_net_anisota_observatory_layout() } fn validate(&self) -> Result<(), ConstraintError> { + if let Some(values) = &self.tile_order { + for value in values { + #[allow(unused_comparisons)] + if ::len(value.as_ref()) > 64usize { + return Err(ConstraintError::MaxLength { + path: ValidationPath::from_field("tile_order"), + max: 64usize, + actual: ::len(value.as_ref()), + }); + } + } + } Ok(()) } } @@ -354,6 +370,28 @@ impl LexiconSchema for Schedule { }); } } + if let Some(values) = &self.days_of_week { + for value in values { + if *value > 6i64 { + return Err(ConstraintError::Maximum { + path: ValidationPath::from_field("days_of_week"), + max: 6i64, + actual: *value, + }); + } + } + } + if let Some(values) = &self.days_of_week { + for value in values { + if *value < 0i64 { + return Err(ConstraintError::Minimum { + path: ValidationPath::from_field("days_of_week"), + min: 0i64, + actual: *value, + }); + } + } + } if let Some(ref value) = self.end_time { #[allow(unused_comparisons)] if ::len(value.as_ref()) > 5usize { @@ -655,18 +693,22 @@ fn lexicon_doc_net_anisota_observatory_layout() -> LexiconDoc<'static> { map.insert( SmolStr::new_static("source"), LexUserType::Object(LexObject { - description: Some(CowStr::new_static( - "Provenance backlink for layouts learned from another user.", - )), + description: Some( + CowStr::new_static( + "Provenance for this layout. 'original' was crafted here, 'learned' was saved from another user's shared layout (see originalUri/originalDid), and 'migrated' marks the layout the one-time unify migration captured from the user's live grid — that value is the migration's idempotency sentinel and must be preserved when a record is re-saved, or the migration will run again and duplicate the layout.", + ), + ), properties: { #[allow(unused_mut)] let mut map = BTreeMap::new(); map.insert( SmolStr::new_static("originalDid"), LexObjectProperty::String(LexString { - description: Some(CowStr::new_static( - "DID of the user this layout was learned from", - )), + description: Some( + CowStr::new_static( + "DID of the user this layout was learned from", + ), + ), format: Some(LexStringFormat::Did), ..Default::default() }), @@ -674,18 +716,18 @@ fn lexicon_doc_net_anisota_observatory_layout() -> LexiconDoc<'static> { map.insert( SmolStr::new_static("originalUri"), LexObjectProperty::String(LexString { - description: Some(CowStr::new_static( - "AT URI of the record this layout was learned from", - )), + description: Some( + CowStr::new_static( + "AT URI of the record this layout was learned from", + ), + ), format: Some(LexStringFormat::AtUri), ..Default::default() }), ); map.insert( SmolStr::new_static("type"), - LexObjectProperty::String(LexString { - ..Default::default() - }), + LexObjectProperty::String(LexString { ..Default::default() }), ); map }, diff --git a/crates/jacquard-api/src/net_anisota/player/state.rs b/crates/jacquard-api/src/net_anisota/player/state.rs index e77230501..31bc1f0e8 100644 --- a/crates/jacquard-api/src/net_anisota/player/state.rs +++ b/crates/jacquard-api/src/net_anisota/player/state.rs @@ -37,6 +37,12 @@ use serde::{Deserialize, Serialize}; bound(deserialize = "S: Deserialize<'de> + BosStr") )] pub struct State { + ///ISO datetime the player most recently accepted the Terms of Service / Privacy Policy. + #[serde(skip_serializing_if = "Option::is_none")] + pub accepted_terms_at: Option, + ///The highest Terms of Service / Privacy Policy version this player has accepted (see src/utils/termsVersion.js TERMS_VERSION). Drives the first-run acceptance gate; when this is below the current TERMS_VERSION the user is re-prompted to accept. + #[serde(skip_serializing_if = "Option::is_none")] + pub accepted_terms_version: Option, ///Target active blocks per day (decimal string, e.g. '6') #[serde(skip_serializing_if = "Option::is_none")] pub active_blocks_intention_daily: Option, @@ -55,6 +61,12 @@ pub struct State { ///Activity style intention Y position as grid percentage (0-100, creating axis) #[serde(skip_serializing_if = "Option::is_none")] pub activity_intention_y: Option, + ///Chosen app experience: 'story' (full immersive) or 'open' (simpler). Authoritative cross-device value for the mode picked during onboarding. + #[serde(skip_serializing_if = "Option::is_none")] + pub app_mode: Option, + ///Object mapping completed story/onboarding chapter ids (e.g. 'welcome') to the ISO datetime they were completed. Drives whether the onboarding/changelog overlays are shown. + #[serde(skip_serializing_if = "Option::is_none")] + pub completed_chapters: Option>, ///Current light charge in Wh (decimal string, e.g. '280.0') #[serde(skip_serializing_if = "Option::is_none")] pub current_light: Option, @@ -64,12 +76,24 @@ pub struct State { ///Equipment slots: object mapping slotId (hands, backpack, camp) to arrays of equipped item ID strings #[serde(skip_serializing_if = "Option::is_none")] pub equipped: Option>, + ///Whether the v2 inventory/equipment migration has been applied for this player. + #[serde(skip_serializing_if = "Option::is_none")] + pub inventory_migration_v2: Option, + ///Whether the v3 inventory/equipment migration (power-station id remap) has been applied for this player. + #[serde(skip_serializing_if = "Option::is_none")] + pub inventory_migration_v3: Option, ///When the current session started (for multi-device awareness) #[serde(skip_serializing_if = "Option::is_none")] pub last_session_start: Option, ///Whether light drain was active when state was saved #[serde(skip_serializing_if = "Option::is_none")] pub light_drain_active: Option, + ///Rest ledger high-water-mark: the longest rest stretch ever (time away from the forest between walks) in minutes, as a decimal string. Monotonic — only ever increases. Everything else the rest ledger shows is computed on read from the walk records; this is the one durable figure. + #[serde(skip_serializing_if = "Option::is_none")] + pub longest_rest_minutes: Option, + ///Comma-joined list of goal ids the player selected during onboarding (e.g. 'offline-more,reply-more'). Stored as a string to avoid depending on array support. + #[serde(skip_serializing_if = "Option::is_none")] + pub onboarding_goals: Option, ///Slot capacity overrides: object mapping slotId to integer capacity (for upgrades). Slots not listed use default capacity. #[serde(skip_serializing_if = "Option::is_none")] pub slot_capacity: Option>, @@ -183,6 +207,8 @@ pub mod state_state { pub struct StateBuilder { _state: PhantomData St>, _fields: ( + Option, + Option, Option, Option, Option, @@ -190,10 +216,16 @@ pub struct StateBuilder { Option, Option, Option, + Option>, + Option, Option, Option>, + Option, + Option, Option, Option, + Option, + Option, Option>, Option, Option, @@ -224,7 +256,7 @@ impl StateBuilder { _state: PhantomData, _fields: ( None, None, None, None, None, None, None, None, None, None, None, None, None, None, - None, None, + None, None, None, None, None, None, None, None, None, None, ), _type: PhantomData, } @@ -238,22 +270,48 @@ impl StateBuilder { _state: PhantomData, _fields: ( None, None, None, None, None, None, None, None, None, None, None, None, None, None, - None, None, + None, None, None, None, None, None, None, None, None, None, ), _type: PhantomData, } } } +impl StateBuilder { + /// Set the `acceptedTermsAt` field (optional) + pub fn accepted_terms_at(mut self, value: impl Into>) -> Self { + self._fields.0 = value.into(); + self + } + /// Set the `acceptedTermsAt` field to an Option value (optional) + pub fn maybe_accepted_terms_at(mut self, value: Option) -> Self { + self._fields.0 = value; + self + } +} + +impl StateBuilder { + /// Set the `acceptedTermsVersion` field (optional) + pub fn accepted_terms_version(mut self, value: impl Into>) -> Self { + self._fields.1 = value.into(); + self + } + /// Set the `acceptedTermsVersion` field to an Option value (optional) + pub fn maybe_accepted_terms_version(mut self, value: Option) -> Self { + self._fields.1 = value; + self + } +} + impl StateBuilder { /// Set the `activeBlocksIntentionDaily` field (optional) pub fn active_blocks_intention_daily(mut self, value: impl Into>) -> Self { - self._fields.0 = value.into(); + self._fields.2 = value.into(); self } /// Set the `activeBlocksIntentionDaily` field to an Option value (optional) pub fn maybe_active_blocks_intention_daily(mut self, value: Option) -> Self { - self._fields.0 = value; + self._fields.2 = value; self } } @@ -261,12 +319,12 @@ impl StateBuilder { impl StateBuilder { /// Set the `activityIntentionConsuming7d` field (optional) pub fn activity_intention_consuming7d(mut self, value: impl Into>) -> Self { - self._fields.1 = value.into(); + self._fields.3 = value.into(); self } /// Set the `activityIntentionConsuming7d` field to an Option value (optional) pub fn maybe_activity_intention_consuming7d(mut self, value: Option) -> Self { - self._fields.1 = value; + self._fields.3 = value; self } } @@ -274,12 +332,12 @@ impl StateBuilder { impl StateBuilder { /// Set the `activityIntentionCreating7d` field (optional) pub fn activity_intention_creating7d(mut self, value: impl Into>) -> Self { - self._fields.2 = value.into(); + self._fields.4 = value.into(); self } /// Set the `activityIntentionCreating7d` field to an Option value (optional) pub fn maybe_activity_intention_creating7d(mut self, value: Option) -> Self { - self._fields.2 = value; + self._fields.4 = value; self } } @@ -287,12 +345,12 @@ impl StateBuilder { impl StateBuilder { /// Set the `activityIntentionTotal7d` field (optional) pub fn activity_intention_total7d(mut self, value: impl Into>) -> Self { - self._fields.3 = value.into(); + self._fields.5 = value.into(); self } /// Set the `activityIntentionTotal7d` field to an Option value (optional) pub fn maybe_activity_intention_total7d(mut self, value: Option) -> Self { - self._fields.3 = value; + self._fields.5 = value; self } } @@ -300,12 +358,12 @@ impl StateBuilder { impl StateBuilder { /// Set the `activityIntentionX` field (optional) pub fn activity_intention_x(mut self, value: impl Into>) -> Self { - self._fields.4 = value.into(); + self._fields.6 = value.into(); self } /// Set the `activityIntentionX` field to an Option value (optional) pub fn maybe_activity_intention_x(mut self, value: Option) -> Self { - self._fields.4 = value; + self._fields.6 = value; self } } @@ -313,12 +371,38 @@ impl StateBuilder { impl StateBuilder { /// Set the `activityIntentionY` field (optional) pub fn activity_intention_y(mut self, value: impl Into>) -> Self { - self._fields.5 = value.into(); + self._fields.7 = value.into(); self } /// Set the `activityIntentionY` field to an Option value (optional) pub fn maybe_activity_intention_y(mut self, value: Option) -> Self { - self._fields.5 = value; + self._fields.7 = value; + self + } +} + +impl StateBuilder { + /// Set the `appMode` field (optional) + pub fn app_mode(mut self, value: impl Into>) -> Self { + self._fields.8 = value.into(); + self + } + /// Set the `appMode` field to an Option value (optional) + pub fn maybe_app_mode(mut self, value: Option) -> Self { + self._fields.8 = value; + self + } +} + +impl StateBuilder { + /// Set the `completedChapters` field (optional) + pub fn completed_chapters(mut self, value: impl Into>>) -> Self { + self._fields.9 = value.into(); + self + } + /// Set the `completedChapters` field to an Option value (optional) + pub fn maybe_completed_chapters(mut self, value: Option>) -> Self { + self._fields.9 = value; self } } @@ -326,12 +410,12 @@ impl StateBuilder { impl StateBuilder { /// Set the `currentLight` field (optional) pub fn current_light(mut self, value: impl Into>) -> Self { - self._fields.6 = value.into(); + self._fields.10 = value.into(); self } /// Set the `currentLight` field to an Option value (optional) pub fn maybe_current_light(mut self, value: Option) -> Self { - self._fields.6 = value; + self._fields.10 = value; self } } @@ -339,12 +423,12 @@ impl StateBuilder { impl StateBuilder { /// Set the `currentStamina` field (optional) pub fn current_stamina(mut self, value: impl Into>) -> Self { - self._fields.7 = value.into(); + self._fields.11 = value.into(); self } /// Set the `currentStamina` field to an Option value (optional) pub fn maybe_current_stamina(mut self, value: Option) -> Self { - self._fields.7 = value; + self._fields.11 = value; self } } @@ -352,12 +436,38 @@ impl StateBuilder { impl StateBuilder { /// Set the `equipped` field (optional) pub fn equipped(mut self, value: impl Into>>) -> Self { - self._fields.8 = value.into(); + self._fields.12 = value.into(); self } /// Set the `equipped` field to an Option value (optional) pub fn maybe_equipped(mut self, value: Option>) -> Self { - self._fields.8 = value; + self._fields.12 = value; + self + } +} + +impl StateBuilder { + /// Set the `inventoryMigrationV2` field (optional) + pub fn inventory_migration_v2(mut self, value: impl Into>) -> Self { + self._fields.13 = value.into(); + self + } + /// Set the `inventoryMigrationV2` field to an Option value (optional) + pub fn maybe_inventory_migration_v2(mut self, value: Option) -> Self { + self._fields.13 = value; + self + } +} + +impl StateBuilder { + /// Set the `inventoryMigrationV3` field (optional) + pub fn inventory_migration_v3(mut self, value: impl Into>) -> Self { + self._fields.14 = value.into(); + self + } + /// Set the `inventoryMigrationV3` field to an Option value (optional) + pub fn maybe_inventory_migration_v3(mut self, value: Option) -> Self { + self._fields.14 = value; self } } @@ -365,12 +475,12 @@ impl StateBuilder { impl StateBuilder { /// Set the `lastSessionStart` field (optional) pub fn last_session_start(mut self, value: impl Into>) -> Self { - self._fields.9 = value.into(); + self._fields.15 = value.into(); self } /// Set the `lastSessionStart` field to an Option value (optional) pub fn maybe_last_session_start(mut self, value: Option) -> Self { - self._fields.9 = value; + self._fields.15 = value; self } } @@ -378,12 +488,38 @@ impl StateBuilder { impl StateBuilder { /// Set the `lightDrainActive` field (optional) pub fn light_drain_active(mut self, value: impl Into>) -> Self { - self._fields.10 = value.into(); + self._fields.16 = value.into(); self } /// Set the `lightDrainActive` field to an Option value (optional) pub fn maybe_light_drain_active(mut self, value: Option) -> Self { - self._fields.10 = value; + self._fields.16 = value; + self + } +} + +impl StateBuilder { + /// Set the `longestRestMinutes` field (optional) + pub fn longest_rest_minutes(mut self, value: impl Into>) -> Self { + self._fields.17 = value.into(); + self + } + /// Set the `longestRestMinutes` field to an Option value (optional) + pub fn maybe_longest_rest_minutes(mut self, value: Option) -> Self { + self._fields.17 = value; + self + } +} + +impl StateBuilder { + /// Set the `onboardingGoals` field (optional) + pub fn onboarding_goals(mut self, value: impl Into>) -> Self { + self._fields.18 = value.into(); + self + } + /// Set the `onboardingGoals` field to an Option value (optional) + pub fn maybe_onboarding_goals(mut self, value: Option) -> Self { + self._fields.18 = value; self } } @@ -391,12 +527,12 @@ impl StateBuilder { impl StateBuilder { /// Set the `slotCapacity` field (optional) pub fn slot_capacity(mut self, value: impl Into>>) -> Self { - self._fields.11 = value.into(); + self._fields.19 = value.into(); self } /// Set the `slotCapacity` field to an Option value (optional) pub fn maybe_slot_capacity(mut self, value: Option>) -> Self { - self._fields.11 = value; + self._fields.19 = value; self } } @@ -404,12 +540,12 @@ impl StateBuilder { impl StateBuilder { /// Set the `starterItemsGranted` field (optional) pub fn starter_items_granted(mut self, value: impl Into>) -> Self { - self._fields.12 = value.into(); + self._fields.20 = value.into(); self } /// Set the `starterItemsGranted` field to an Option value (optional) pub fn maybe_starter_items_granted(mut self, value: Option) -> Self { - self._fields.12 = value; + self._fields.20 = value; self } } @@ -417,12 +553,12 @@ impl StateBuilder { impl StateBuilder { /// Set the `triggerSource` field (optional) pub fn trigger_source(mut self, value: impl Into>) -> Self { - self._fields.13 = value.into(); + self._fields.21 = value.into(); self } /// Set the `triggerSource` field to an Option value (optional) pub fn maybe_trigger_source(mut self, value: Option) -> Self { - self._fields.13 = value; + self._fields.21 = value; self } } @@ -430,12 +566,12 @@ impl StateBuilder { impl StateBuilder { /// Set the `tutorialCompletedAt` field (optional) pub fn tutorial_completed_at(mut self, value: impl Into>) -> Self { - self._fields.14 = value.into(); + self._fields.22 = value.into(); self } /// Set the `tutorialCompletedAt` field to an Option value (optional) pub fn maybe_tutorial_completed_at(mut self, value: Option) -> Self { - self._fields.14 = value; + self._fields.22 = value; self } } @@ -450,7 +586,7 @@ where mut self, value: impl Into, ) -> StateBuilder, S> { - self._fields.15 = Option::Some(value.into()); + self._fields.23 = Option::Some(value.into()); StateBuilder { _state: PhantomData, _fields: self._fields, @@ -467,44 +603,60 @@ where /// Build the final struct. pub fn build(self) -> State { State { - active_blocks_intention_daily: self._fields.0, - activity_intention_consuming7d: self._fields.1, - activity_intention_creating7d: self._fields.2, - activity_intention_total7d: self._fields.3, - activity_intention_x: self._fields.4, - activity_intention_y: self._fields.5, - current_light: self._fields.6, - current_stamina: self._fields.7, - equipped: self._fields.8, - last_session_start: self._fields.9, - light_drain_active: self._fields.10, - slot_capacity: self._fields.11, - starter_items_granted: self._fields.12, - trigger_source: self._fields.13, - tutorial_completed_at: self._fields.14, - updated_at: self._fields.15.unwrap(), + accepted_terms_at: self._fields.0, + accepted_terms_version: self._fields.1, + active_blocks_intention_daily: self._fields.2, + activity_intention_consuming7d: self._fields.3, + activity_intention_creating7d: self._fields.4, + activity_intention_total7d: self._fields.5, + activity_intention_x: self._fields.6, + activity_intention_y: self._fields.7, + app_mode: self._fields.8, + completed_chapters: self._fields.9, + current_light: self._fields.10, + current_stamina: self._fields.11, + equipped: self._fields.12, + inventory_migration_v2: self._fields.13, + inventory_migration_v3: self._fields.14, + last_session_start: self._fields.15, + light_drain_active: self._fields.16, + longest_rest_minutes: self._fields.17, + onboarding_goals: self._fields.18, + slot_capacity: self._fields.19, + starter_items_granted: self._fields.20, + trigger_source: self._fields.21, + tutorial_completed_at: self._fields.22, + updated_at: self._fields.23.unwrap(), extra_data: Default::default(), } } /// Build the final struct with custom extra_data. pub fn build_with_data(self, extra_data: BTreeMap>) -> State { State { - active_blocks_intention_daily: self._fields.0, - activity_intention_consuming7d: self._fields.1, - activity_intention_creating7d: self._fields.2, - activity_intention_total7d: self._fields.3, - activity_intention_x: self._fields.4, - activity_intention_y: self._fields.5, - current_light: self._fields.6, - current_stamina: self._fields.7, - equipped: self._fields.8, - last_session_start: self._fields.9, - light_drain_active: self._fields.10, - slot_capacity: self._fields.11, - starter_items_granted: self._fields.12, - trigger_source: self._fields.13, - tutorial_completed_at: self._fields.14, - updated_at: self._fields.15.unwrap(), + accepted_terms_at: self._fields.0, + accepted_terms_version: self._fields.1, + active_blocks_intention_daily: self._fields.2, + activity_intention_consuming7d: self._fields.3, + activity_intention_creating7d: self._fields.4, + activity_intention_total7d: self._fields.5, + activity_intention_x: self._fields.6, + activity_intention_y: self._fields.7, + app_mode: self._fields.8, + completed_chapters: self._fields.9, + current_light: self._fields.10, + current_stamina: self._fields.11, + equipped: self._fields.12, + inventory_migration_v2: self._fields.13, + inventory_migration_v3: self._fields.14, + last_session_start: self._fields.15, + light_drain_active: self._fields.16, + longest_rest_minutes: self._fields.17, + onboarding_goals: self._fields.18, + slot_capacity: self._fields.19, + starter_items_granted: self._fields.20, + trigger_source: self._fields.21, + tutorial_completed_at: self._fields.22, + updated_at: self._fields.23.unwrap(), extra_data: Some(extra_data), } } @@ -534,6 +686,24 @@ fn lexicon_doc_net_anisota_player_state() -> LexiconDoc<'static> { properties: { #[allow(unused_mut)] let mut map = BTreeMap::new(); + map.insert( + SmolStr::new_static("acceptedTermsAt"), + LexObjectProperty::String(LexString { + description: Some( + CowStr::new_static( + "ISO datetime the player most recently accepted the Terms of Service / Privacy Policy.", + ), + ), + format: Some(LexStringFormat::Datetime), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("acceptedTermsVersion"), + LexObjectProperty::Integer(LexInteger { + ..Default::default() + }), + ); map.insert( SmolStr::new_static("activeBlocksIntentionDaily"), LexObjectProperty::String(LexString { @@ -600,6 +770,23 @@ fn lexicon_doc_net_anisota_player_state() -> LexiconDoc<'static> { ..Default::default() }), ); + map.insert( + SmolStr::new_static("appMode"), + LexObjectProperty::String(LexString { + description: Some( + CowStr::new_static( + "Chosen app experience: 'story' (full immersive) or 'open' (simpler). Authoritative cross-device value for the mode picked during onboarding.", + ), + ), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("completedChapters"), + LexObjectProperty::Unknown(LexUnknown { + ..Default::default() + }), + ); map.insert( SmolStr::new_static("currentLight"), LexObjectProperty::String(LexString { @@ -628,6 +815,18 @@ fn lexicon_doc_net_anisota_player_state() -> LexiconDoc<'static> { ..Default::default() }), ); + map.insert( + SmolStr::new_static("inventoryMigrationV2"), + LexObjectProperty::Boolean(LexBoolean { + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("inventoryMigrationV3"), + LexObjectProperty::Boolean(LexBoolean { + ..Default::default() + }), + ); map.insert( SmolStr::new_static("lastSessionStart"), LexObjectProperty::String(LexString { @@ -646,6 +845,28 @@ fn lexicon_doc_net_anisota_player_state() -> LexiconDoc<'static> { ..Default::default() }), ); + map.insert( + SmolStr::new_static("longestRestMinutes"), + LexObjectProperty::String(LexString { + description: Some( + CowStr::new_static( + "Rest ledger high-water-mark: the longest rest stretch ever (time away from the forest between walks) in minutes, as a decimal string. Monotonic — only ever increases. Everything else the rest ledger shows is computed on read from the walk records; this is the one durable figure.", + ), + ), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("onboardingGoals"), + LexObjectProperty::String(LexString { + description: Some( + CowStr::new_static( + "Comma-joined list of goal ids the player selected during onboarding (e.g. 'offline-more,reply-more'). Stored as a string to avoid depending on array support.", + ), + ), + ..Default::default() + }), + ); map.insert( SmolStr::new_static("slotCapacity"), LexObjectProperty::Unknown(LexUnknown { diff --git a/crates/jacquard-api/src/net_anisota/spell.rs b/crates/jacquard-api/src/net_anisota/spell.rs new file mode 100644 index 000000000..f80582877 --- /dev/null +++ b/crates/jacquard-api/src/net_anisota/spell.rs @@ -0,0 +1,8 @@ +// @generated by jacquard-lexicon. DO NOT EDIT. +// +// This file was automatically generated from Lexicon schemas. +// Any manual changes will be overwritten on the next regeneration. + +//! Generated bindings for the `net.anisota.spell` Lexicon namespace/module. +pub mod book; +pub mod custom; diff --git a/crates/jacquard-api/src/net_anisota/spell/book.rs b/crates/jacquard-api/src/net_anisota/spell/book.rs new file mode 100644 index 000000000..54c883f4c --- /dev/null +++ b/crates/jacquard-api/src/net_anisota/spell/book.rs @@ -0,0 +1,468 @@ +// @generated by jacquard-lexicon. DO NOT EDIT. +// +// Lexicon: net.anisota.spell.book +// +// 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; + +use crate::net_anisota::spell::book; +#[allow(unused_imports)] +use jacquard_lexicon::validation::{ConstraintError, ValidationPath}; +use serde::{Deserialize, Serialize}; +/// A reference to one of the user's spells plus its cast state and position. + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic, Default)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct Entry { + ///Whether the spell is currently cast (active). Defaults to false when absent. + #[serde(skip_serializing_if = "Option::is_none")] + pub cast: Option, + ///Zero-based display order within the spell book. + #[serde(skip_serializing_if = "Option::is_none")] + pub order: Option, + ///Record key of the net.anisota.spell.custom record this entry points to, in the same repo. + pub rkey: S, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +/// The user's spell book: a single index record (stored at rkey 'self') that tracks which net.anisota.spell.custom records the user has, whether each is currently cast (active), and in what order they appear. The individual spell definitions live in the net.anisota.spell.custom collection; this record only references them by rkey, so casting/dismissing/reordering a spell touches only this small index rather than rewriting each spell. + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + rename = "net.anisota.spell.book", + tag = "$type", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct Book { + ///Legacy: identifiers of built-in preset spells the user had activated before presets were replaced by real shared spell records. Retained for backward compatibility. + #[serde(skip_serializing_if = "Option::is_none")] + pub active_presets: Option>, + ///The user's spells, in display order, each referencing a net.anisota.spell.custom record in the same repo. + pub entries: Vec>, + ///When the spell book was last modified + pub updated_at: Datetime, + #[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 BookGetRecordOutput { + #[serde(skip_serializing_if = "Option::is_none")] + pub cid: Option>, + pub uri: AtUri, + pub value: Book, +} + +impl Book { + pub fn uri(uri: S) -> Result, UriError> { + RecordUri::try_from_uri(AtUri::new(uri)?) + } +} + +impl LexiconSchema for Entry { + fn nsid() -> &'static str { + "net.anisota.spell.book" + } + fn def_name() -> &'static str { + "entry" + } + fn lexicon_doc() -> LexiconDoc<'static> { + lexicon_doc_net_anisota_spell_book() + } + fn validate(&self) -> Result<(), ConstraintError> { + if let Some(ref value) = self.order { + if *value < 0i64 { + return Err(ConstraintError::Minimum { + path: ValidationPath::from_field("order"), + min: 0i64, + actual: *value, + }); + } + } + { + let value = &self.rkey; + #[allow(unused_comparisons)] + if ::len(value.as_ref()) > 512usize { + return Err(ConstraintError::MaxLength { + path: ValidationPath::from_field("rkey"), + max: 512usize, + actual: ::len(value.as_ref()), + }); + } + } + Ok(()) + } +} + +/// Marker type for deserializing records from this collection. + +#[derive(Debug, Serialize, Deserialize)] +pub struct BookRecord; +impl XrpcResp for BookRecord { + const NSID: &'static str = "net.anisota.spell.book"; + const ENCODING: &'static str = "application/json"; + type Output = BookGetRecordOutput; + type Err = RecordError; +} + +impl From> for Book { + fn from(output: BookGetRecordOutput) -> Self { + output.value + } +} + +impl Collection for Book { + const NSID: &'static str = "net.anisota.spell.book"; + type Record = BookRecord; +} + +impl Collection for BookRecord { + const NSID: &'static str = "net.anisota.spell.book"; + type Record = BookRecord; +} + +impl LexiconSchema for Book { + fn nsid() -> &'static str { + "net.anisota.spell.book" + } + fn def_name() -> &'static str { + "main" + } + fn lexicon_doc() -> LexiconDoc<'static> { + lexicon_doc_net_anisota_spell_book() + } + fn validate(&self) -> Result<(), ConstraintError> { + if let Some(values) = &self.active_presets { + for value in values { + #[allow(unused_comparisons)] + if ::len(value.as_ref()) > 64usize { + return Err(ConstraintError::MaxLength { + path: ValidationPath::from_field("active_presets"), + max: 64usize, + actual: ::len(value.as_ref()), + }); + } + } + } + Ok(()) + } +} + +fn lexicon_doc_net_anisota_spell_book() -> 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("net.anisota.spell.book"), + defs: { + let mut map = BTreeMap::new(); + map.insert( + SmolStr::new_static("entry"), + LexUserType::Object(LexObject { + description: Some( + CowStr::new_static( + "A reference to one of the user's spells plus its cast state and position.", + ), + ), + required: Some(vec![SmolStr::new_static("rkey")]), + properties: { + #[allow(unused_mut)] + let mut map = BTreeMap::new(); + map.insert( + SmolStr::new_static("cast"), + LexObjectProperty::Boolean(LexBoolean { + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("order"), + LexObjectProperty::Integer(LexInteger { + minimum: Some(0i64), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("rkey"), + LexObjectProperty::String(LexString { + description: Some( + CowStr::new_static( + "Record key of the net.anisota.spell.custom record this entry points to, in the same repo.", + ), + ), + max_length: Some(512usize), + ..Default::default() + }), + ); + map + }, + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("main"), + LexUserType::Record(LexRecord { + description: Some( + CowStr::new_static( + "The user's spell book: a single index record (stored at rkey 'self') that tracks which net.anisota.spell.custom records the user has, whether each is currently cast (active), and in what order they appear. The individual spell definitions live in the net.anisota.spell.custom collection; this record only references them by rkey, so casting/dismissing/reordering a spell touches only this small index rather than rewriting each spell.", + ), + ), + key: Some(CowStr::new_static("any")), + record: LexRecordRecord::Object(LexObject { + required: Some( + vec![ + SmolStr::new_static("entries"), + SmolStr::new_static("updatedAt") + ], + ), + properties: { + #[allow(unused_mut)] + let mut map = BTreeMap::new(); + map.insert( + SmolStr::new_static("activePresets"), + LexObjectProperty::Array(LexArray { + description: Some( + CowStr::new_static( + "Legacy: identifiers of built-in preset spells the user had activated before presets were replaced by real shared spell records. Retained for backward compatibility.", + ), + ), + items: LexArrayItem::String(LexString { + max_length: Some(64usize), + ..Default::default() + }), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("entries"), + LexObjectProperty::Array(LexArray { + description: Some( + CowStr::new_static( + "The user's spells, in display order, each referencing a net.anisota.spell.custom record in the same repo.", + ), + ), + items: LexArrayItem::Ref(LexRef { + r#ref: CowStr::new_static("#entry"), + ..Default::default() + }), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("updatedAt"), + LexObjectProperty::String(LexString { + description: Some( + CowStr::new_static("When the spell book was last modified"), + ), + format: Some(LexStringFormat::Datetime), + ..Default::default() + }), + ); + map + }, + ..Default::default() + }), + ..Default::default() + }), + ); + map + }, + ..Default::default() + } +} + +pub mod book_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 Entries; + type UpdatedAt; + } + /// Empty state - all required fields are unset + pub struct Empty(()); + impl sealed::Sealed for Empty {} + impl State for Empty { + type Entries = Unset; + type UpdatedAt = Unset; + } + ///State transition - sets the `entries` field to Set + pub struct SetEntries(PhantomData St>); + impl sealed::Sealed for SetEntries {} + impl State for SetEntries { + type Entries = Set; + type UpdatedAt = St::UpdatedAt; + } + ///State transition - sets the `updated_at` field to Set + pub struct SetUpdatedAt(PhantomData St>); + impl sealed::Sealed for SetUpdatedAt {} + impl State for SetUpdatedAt { + type Entries = St::Entries; + type UpdatedAt = Set; + } + /// Marker types for field names + #[allow(non_camel_case_types)] + pub mod members { + ///Marker type for the `entries` field + pub struct entries(()); + ///Marker type for the `updated_at` field + pub struct updated_at(()); + } +} + +/// Builder for constructing an instance of this type. +pub struct BookBuilder { + _state: PhantomData St>, + _fields: ( + Option>, + Option>>, + Option, + ), + _type: PhantomData S>, +} + +impl Book { + /// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed + pub fn new() -> BookBuilder { + BookBuilder::new() + } +} + +impl Book { + /// Create a new builder for this type + pub fn builder() -> BookBuilder { + BookBuilder::builder() + } +} + +impl BookBuilder { + /// Create a new builder with all fields unset, using the default string type, if needed + pub fn new() -> Self { + BookBuilder { + _state: PhantomData, + _fields: (None, None, None), + _type: PhantomData, + } + } +} + +impl BookBuilder { + /// Create a new builder with all fields unset + pub fn builder() -> Self { + BookBuilder { + _state: PhantomData, + _fields: (None, None, None), + _type: PhantomData, + } + } +} + +impl BookBuilder { + /// Set the `activePresets` field (optional) + pub fn active_presets(mut self, value: impl Into>>) -> Self { + self._fields.0 = value.into(); + self + } + /// Set the `activePresets` field to an Option value (optional) + pub fn maybe_active_presets(mut self, value: Option>) -> Self { + self._fields.0 = value; + self + } +} + +impl BookBuilder +where + St: book_state::State, + St::Entries: book_state::IsUnset, +{ + /// Set the `entries` field (required) + pub fn entries( + mut self, + value: impl Into>>, + ) -> BookBuilder, S> { + self._fields.1 = Option::Some(value.into()); + BookBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl BookBuilder +where + St: book_state::State, + St::UpdatedAt: book_state::IsUnset, +{ + /// Set the `updatedAt` field (required) + pub fn updated_at( + mut self, + value: impl Into, + ) -> BookBuilder, S> { + self._fields.2 = Option::Some(value.into()); + BookBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl BookBuilder +where + St: book_state::State, + St::Entries: book_state::IsSet, + St::UpdatedAt: book_state::IsSet, +{ + /// Build the final struct. + pub fn build(self) -> Book { + Book { + active_presets: self._fields.0, + entries: self._fields.1.unwrap(), + updated_at: 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>) -> Book { + Book { + active_presets: self._fields.0, + entries: self._fields.1.unwrap(), + updated_at: self._fields.2.unwrap(), + extra_data: Some(extra_data), + } + } +} diff --git a/crates/jacquard-api/src/net_anisota/spell/custom.rs b/crates/jacquard-api/src/net_anisota/spell/custom.rs new file mode 100644 index 000000000..31e1fc589 --- /dev/null +++ b/crates/jacquard-api/src/net_anisota/spell/custom.rs @@ -0,0 +1,1970 @@ +// @generated by jacquard-lexicon. DO NOT EDIT. +// +// Lexicon: net.anisota.spell.custom +// +// 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; + +use crate::net_anisota::spell::custom; +#[allow(unused_imports)] +use jacquard_lexicon::validation::{ConstraintError, ValidationPath}; +use serde::{Deserialize, Serialize}; +/// One 'if' clause: a variable compared against a value with an operator. Composite conditions (variable 'activitySum' / 'engagementSum') additionally carry a timeframe and a set of metrics to sum. Words-seen conditions (variable 'wordsSeen') additionally carry the word set to watch for and a counting scope. Each condition also carries an undeclared 'value' property — the thing being compared against. Its shape depends on the variable's type (a number, a 'HH:MM' string, a boolean, a two-element ['HH:MM','HH:MM'] array for time 'between', an integer 0-6 for dayOfWeek, a moon-phase / route / modal / date key string, or a { uri, name } object for a feed), so it is deliberately left out of the schema and validated client-side; lexicon 'unknown' means 'any object', which would reject the scalar cases. + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic, Default)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct Condition { + ///Composite conditions only: which metric keys to sum (e.g. 'postsRead', 'postsCreated', 'repliesSent', 'likesReceived'). See spellService COMPOSITE_METRICS. + #[serde(skip_serializing_if = "Option::is_none")] + pub metrics: Option>, + ///Comparison operator. Numeric/composite use gt/gte/lt/lte/eq/neq; time uses those plus 'between'; booleans use is/isNot; enumerated types (dayOfWeek, moonPhase, route, modal, feed, handle, date) use eq/neq. + pub operator: ConditionOperator, + ///Words-seen ('wordsSeen') conditions only: the window the sighting count covers — 'today' (the calendar day, the default) or 'session' (since the app was opened). + #[serde(skip_serializing_if = "Option::is_none")] + pub scope: Option>, + ///Composite conditions only: the window over which the chosen metrics are summed. + #[serde(skip_serializing_if = "Option::is_none")] + pub timeframe: Option>, + ///The context variable to test, e.g. 'timeOfDay', 'dayOfWeek', 'currentDate', 'stamina', 'level', 'lightRemaining', 'moonPhase', 'unreadNotifications', 'sessionMinutes', 'postsReadToday', 'activitySum', 'wordsSeen', 'currentRoute', 'activeModal', 'currentFeed', 'currentProfileHandle', 'isOnExpedition'. The full catalog is defined client-side in spellService VARIABLE_GROUPS. + pub variable: S, + ///Words-seen ('wordsSeen') conditions only: the words to watch for, stored as trimmed lowercase strings. The condition counts posts containing any of these words as they flow through the viewer's feeds, and compares that count against 'value'. + #[serde(skip_serializing_if = "Option::is_none")] + pub words: Option>, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +/// Comparison operator. Numeric/composite use gt/gte/lt/lte/eq/neq; time uses those plus 'between'; booleans use is/isNot; enumerated types (dayOfWeek, moonPhase, route, modal, feed, handle, date) use eq/neq. + +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub enum ConditionOperator { + Gt, + Gte, + Lt, + Lte, + Eq, + Neq, + Between, + Is, + IsNot, + Other(S), +} + +impl ConditionOperator { + pub fn as_str(&self) -> &str { + match self { + Self::Gt => "gt", + Self::Gte => "gte", + Self::Lt => "lt", + Self::Lte => "lte", + Self::Eq => "eq", + Self::Neq => "neq", + Self::Between => "between", + Self::Is => "is", + Self::IsNot => "isNot", + 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() { + "gt" => Self::Gt, + "gte" => Self::Gte, + "lt" => Self::Lt, + "lte" => Self::Lte, + "eq" => Self::Eq, + "neq" => Self::Neq, + "between" => Self::Between, + "is" => Self::Is, + "isNot" => Self::IsNot, + _ => Self::Other(s), + } + } +} + +impl core::fmt::Display for ConditionOperator { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!(f, "{}", self.as_str()) + } +} + +impl AsRef for ConditionOperator { + fn as_ref(&self) -> &str { + self.as_str() + } +} + +impl Serialize for ConditionOperator { + 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 ConditionOperator { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = S::deserialize(deserializer)?; + Ok(Self::from_value(s)) + } +} + +impl Default for ConditionOperator { + fn default() -> Self { + Self::Other(Default::default()) + } +} + +impl jacquard_common::IntoStatic for ConditionOperator +where + S: BosStr + jacquard_common::IntoStatic, + S::Output: BosStr, +{ + type Output = ConditionOperator; + fn into_static(self) -> Self::Output { + match self { + ConditionOperator::Gt => ConditionOperator::Gt, + ConditionOperator::Gte => ConditionOperator::Gte, + ConditionOperator::Lt => ConditionOperator::Lt, + ConditionOperator::Lte => ConditionOperator::Lte, + ConditionOperator::Eq => ConditionOperator::Eq, + ConditionOperator::Neq => ConditionOperator::Neq, + ConditionOperator::Between => ConditionOperator::Between, + ConditionOperator::Is => ConditionOperator::Is, + ConditionOperator::IsNot => ConditionOperator::IsNot, + ConditionOperator::Other(v) => ConditionOperator::Other(v.into_static()), + } + } +} + +/// Words-seen ('wordsSeen') conditions only: the window the sighting count covers — 'today' (the calendar day, the default) or 'session' (since the app was opened). + +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub enum ConditionScope { + Today, + Session, + Other(S), +} + +impl ConditionScope { + pub fn as_str(&self) -> &str { + match self { + Self::Today => "today", + Self::Session => "session", + 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() { + "today" => Self::Today, + "session" => Self::Session, + _ => Self::Other(s), + } + } +} + +impl core::fmt::Display for ConditionScope { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!(f, "{}", self.as_str()) + } +} + +impl AsRef for ConditionScope { + fn as_ref(&self) -> &str { + self.as_str() + } +} + +impl Serialize for ConditionScope { + 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 ConditionScope { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = S::deserialize(deserializer)?; + Ok(Self::from_value(s)) + } +} + +impl Default for ConditionScope { + fn default() -> Self { + Self::Other(Default::default()) + } +} + +impl jacquard_common::IntoStatic for ConditionScope +where + S: BosStr + jacquard_common::IntoStatic, + S::Output: BosStr, +{ + type Output = ConditionScope; + fn into_static(self) -> Self::Output { + match self { + ConditionScope::Today => ConditionScope::Today, + ConditionScope::Session => ConditionScope::Session, + ConditionScope::Other(v) => ConditionScope::Other(v.into_static()), + } + } +} + +/// Composite conditions only: the window over which the chosen metrics are summed. + +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub enum ConditionTimeframe { + Today, + Week, + Other(S), +} + +impl ConditionTimeframe { + pub fn as_str(&self) -> &str { + match self { + Self::Today => "today", + Self::Week => "week", + 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() { + "today" => Self::Today, + "week" => Self::Week, + _ => Self::Other(s), + } + } +} + +impl core::fmt::Display for ConditionTimeframe { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!(f, "{}", self.as_str()) + } +} + +impl AsRef for ConditionTimeframe { + fn as_ref(&self) -> &str { + self.as_str() + } +} + +impl Serialize for ConditionTimeframe { + 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 ConditionTimeframe { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = S::deserialize(deserializer)?; + Ok(Self::from_value(s)) + } +} + +impl Default for ConditionTimeframe { + fn default() -> Self { + Self::Other(Default::default()) + } +} + +impl jacquard_common::IntoStatic for ConditionTimeframe +where + S: BosStr + jacquard_common::IntoStatic, + S::Output: BosStr, +{ + type Output = ConditionTimeframe; + fn into_static(self) -> Self::Output { + match self { + ConditionTimeframe::Today => ConditionTimeframe::Today, + ConditionTimeframe::Week => ConditionTimeframe::Week, + ConditionTimeframe::Other(v) => ConditionTimeframe::Other(v.into_static()), + } + } +} + +/// One 'then' clause: a typed effect on a UI surface. Continuously-applied effects flow through the live evaluation; the episodic types (showLockout, showAlert, redirect) are edge-triggered by their controllers. Each effect also carries an undeclared 'value' property — the payload, whose shape depends on target+type: an array of element/button/action/menu keys for the multi-select hide effects; a { rkey, name } layout reference or { rkey, name, keys } for hideElements; an array of word-list snapshots [{ rkey, name, words, strength, targetFeeds }] for activateList — the words are carried inline so a learned spell still works on a PDS where the referenced net.anisota.graph.wordlist record doesn't exist; or a config object for showLockout (message/scope/duration/bypass/…), showAlert (title/message/cooldownMinutes/…), redirect ({ route, cooldownMinutes }), sigilBeforePost ({ source, sigilShape }), overrideSetting ({ id, value }), or warnBefore* ({ action|element, message, gate }). toggleMode carries no value. It is left out of the schema and validated client-side because lexicon 'unknown' means 'any object', which would reject the array and string payloads. + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic, Default)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct Effect { + ///The UI surface the effect acts on. + pub target: EffectTarget, + ///The specific effect within the target. Valid types depend on the target (see spellService EFFECT_TARGETS). hideButton/showButton/setButtons are legacy observatory effects kept for backward compatibility. + pub r#type: EffectType, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +/// The UI surface the effect acts on. + +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub enum EffectTarget { + Observatory, + ControlRow, + Layout, + PostCard, + ProfileCard, + FooterControls, + Settings, + WordLists, + Navigation, + Composer, + Interface, + Theme, + Alert, + Other(S), +} + +impl EffectTarget { + pub fn as_str(&self) -> &str { + match self { + Self::Observatory => "observatory", + Self::ControlRow => "controlRow", + Self::Layout => "layout", + Self::PostCard => "postCard", + Self::ProfileCard => "profileCard", + Self::FooterControls => "footerControls", + Self::Settings => "settings", + Self::WordLists => "wordLists", + Self::Navigation => "navigation", + Self::Composer => "composer", + Self::Interface => "interface", + Self::Theme => "theme", + Self::Alert => "alert", + 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() { + "observatory" => Self::Observatory, + "controlRow" => Self::ControlRow, + "layout" => Self::Layout, + "postCard" => Self::PostCard, + "profileCard" => Self::ProfileCard, + "footerControls" => Self::FooterControls, + "settings" => Self::Settings, + "wordLists" => Self::WordLists, + "navigation" => Self::Navigation, + "composer" => Self::Composer, + "interface" => Self::Interface, + "theme" => Self::Theme, + "alert" => Self::Alert, + _ => Self::Other(s), + } + } +} + +impl core::fmt::Display for EffectTarget { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!(f, "{}", self.as_str()) + } +} + +impl AsRef for EffectTarget { + fn as_ref(&self) -> &str { + self.as_str() + } +} + +impl Serialize for EffectTarget { + 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 EffectTarget { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = S::deserialize(deserializer)?; + Ok(Self::from_value(s)) + } +} + +impl Default for EffectTarget { + fn default() -> Self { + Self::Other(Default::default()) + } +} + +impl jacquard_common::IntoStatic for EffectTarget +where + S: BosStr + jacquard_common::IntoStatic, + S::Output: BosStr, +{ + type Output = EffectTarget; + fn into_static(self) -> Self::Output { + match self { + EffectTarget::Observatory => EffectTarget::Observatory, + EffectTarget::ControlRow => EffectTarget::ControlRow, + EffectTarget::Layout => EffectTarget::Layout, + EffectTarget::PostCard => EffectTarget::PostCard, + EffectTarget::ProfileCard => EffectTarget::ProfileCard, + EffectTarget::FooterControls => EffectTarget::FooterControls, + EffectTarget::Settings => EffectTarget::Settings, + EffectTarget::WordLists => EffectTarget::WordLists, + EffectTarget::Navigation => EffectTarget::Navigation, + EffectTarget::Composer => EffectTarget::Composer, + EffectTarget::Interface => EffectTarget::Interface, + EffectTarget::Theme => EffectTarget::Theme, + EffectTarget::Alert => EffectTarget::Alert, + EffectTarget::Other(v) => EffectTarget::Other(v.into_static()), + } + } +} + +/// The specific effect within the target. Valid types depend on the target (see spellService EFFECT_TARGETS). hideButton/showButton/setButtons are legacy observatory effects kept for backward compatibility. + +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub enum EffectType { + HideElements, + SetLayout, + ShowLockout, + HideButton, + ShowButton, + SetButtons, + DisableAction, + WarnBeforeAction, + HideCornerElement, + WarnBeforeCornerElement, + HideElement, + OverrideSetting, + ActivateList, + HideMenuItem, + Redirect, + SigilBeforePost, + Scramble, + ToggleMode, + ShowAlert, + Other(S), +} + +impl EffectType { + pub fn as_str(&self) -> &str { + match self { + Self::HideElements => "hideElements", + Self::SetLayout => "setLayout", + Self::ShowLockout => "showLockout", + Self::HideButton => "hideButton", + Self::ShowButton => "showButton", + Self::SetButtons => "setButtons", + Self::DisableAction => "disableAction", + Self::WarnBeforeAction => "warnBeforeAction", + Self::HideCornerElement => "hideCornerElement", + Self::WarnBeforeCornerElement => "warnBeforeCornerElement", + Self::HideElement => "hideElement", + Self::OverrideSetting => "overrideSetting", + Self::ActivateList => "activateList", + Self::HideMenuItem => "hideMenuItem", + Self::Redirect => "redirect", + Self::SigilBeforePost => "sigilBeforePost", + Self::Scramble => "scramble", + Self::ToggleMode => "toggleMode", + Self::ShowAlert => "showAlert", + 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() { + "hideElements" => Self::HideElements, + "setLayout" => Self::SetLayout, + "showLockout" => Self::ShowLockout, + "hideButton" => Self::HideButton, + "showButton" => Self::ShowButton, + "setButtons" => Self::SetButtons, + "disableAction" => Self::DisableAction, + "warnBeforeAction" => Self::WarnBeforeAction, + "hideCornerElement" => Self::HideCornerElement, + "warnBeforeCornerElement" => Self::WarnBeforeCornerElement, + "hideElement" => Self::HideElement, + "overrideSetting" => Self::OverrideSetting, + "activateList" => Self::ActivateList, + "hideMenuItem" => Self::HideMenuItem, + "redirect" => Self::Redirect, + "sigilBeforePost" => Self::SigilBeforePost, + "scramble" => Self::Scramble, + "toggleMode" => Self::ToggleMode, + "showAlert" => Self::ShowAlert, + _ => Self::Other(s), + } + } +} + +impl core::fmt::Display for EffectType { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!(f, "{}", self.as_str()) + } +} + +impl AsRef for EffectType { + fn as_ref(&self) -> &str { + self.as_str() + } +} + +impl Serialize for EffectType { + 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 EffectType { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = S::deserialize(deserializer)?; + Ok(Self::from_value(s)) + } +} + +impl Default for EffectType { + fn default() -> Self { + Self::Other(Default::default()) + } +} + +impl jacquard_common::IntoStatic for EffectType +where + S: BosStr + jacquard_common::IntoStatic, + S::Output: BosStr, +{ + type Output = EffectType; + fn into_static(self) -> Self::Output { + match self { + EffectType::HideElements => EffectType::HideElements, + EffectType::SetLayout => EffectType::SetLayout, + EffectType::ShowLockout => EffectType::ShowLockout, + EffectType::HideButton => EffectType::HideButton, + EffectType::ShowButton => EffectType::ShowButton, + EffectType::SetButtons => EffectType::SetButtons, + EffectType::DisableAction => EffectType::DisableAction, + EffectType::WarnBeforeAction => EffectType::WarnBeforeAction, + EffectType::HideCornerElement => EffectType::HideCornerElement, + EffectType::WarnBeforeCornerElement => EffectType::WarnBeforeCornerElement, + EffectType::HideElement => EffectType::HideElement, + EffectType::OverrideSetting => EffectType::OverrideSetting, + EffectType::ActivateList => EffectType::ActivateList, + EffectType::HideMenuItem => EffectType::HideMenuItem, + EffectType::Redirect => EffectType::Redirect, + EffectType::SigilBeforePost => EffectType::SigilBeforePost, + EffectType::Scramble => EffectType::Scramble, + EffectType::ToggleMode => EffectType::ToggleMode, + EffectType::ShowAlert => EffectType::ShowAlert, + EffectType::Other(v) => EffectType::Other(v.into_static()), + } + } +} + +/// A user-authored 'spell' — a conditional rule that produces typed effects on the Anisota interface (hiding elements, switching layouts, showing a lockout/alert, redirecting, overriding a setting, and so on). Each spell is a complete, self-contained record so it can be shared by URL and 'learned' (copied) into another user's PDS without depending on the author's other records, mirroring the net.anisota.observatory.layout architecture. A spell is evaluated against a context snapshot (time, activity, player state, location, …); a spell with no conditions is a manual 'mode' that applies whenever it is cast. Whether a spell is currently cast and in what order lives in the separate net.anisota.spell.book index, not here. The effect 'value' is a heterogeneous union whose shape depends on target+type (a string, number, boolean, [start,end] pair, key list, or a config object such as a lockout/alert/sigil/setting-override), so it is left as 'unknown' and validated client-side. + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + rename = "net.anisota.spell.custom", + tag = "$type", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct Custom { + ///How multiple conditions combine: 'all' (AND, the default) or 'any' (OR). Ignored when there are fewer than two conditions. + #[serde(skip_serializing_if = "Option::is_none")] + pub condition_logic: Option>, + ///The 'if' clauses evaluated against the live context. Empty or absent means the spell has no conditions — it applies whenever it is cast (a manual 'mode' spell), or, for an interval-triggered spell, fires on every tick. + #[serde(skip_serializing_if = "Option::is_none")] + pub conditions: Option>>, + ///When this spell was first crafted + pub created_at: Datetime, + ///Optional description of what this spell does + #[serde(skip_serializing_if = "Option::is_none")] + pub description: Option, + ///The 'then' clauses — what the spell does when it applies. At least one is expected. + pub effects: Vec>, + ///Display name for this spell + pub name: S, + #[serde(skip_serializing_if = "Option::is_none")] + pub source: Option>, + ///Optional interval trigger. When present the spell fires on a timer rather than continuously; its conditions (if any) then act as a gate on whether the timed firing is allowed. Absent means the spell is condition-driven (continuous). + #[serde(skip_serializing_if = "Option::is_none")] + pub trigger: Option>, + ///When this spell was last modified + pub updated_at: Datetime, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +/// How multiple conditions combine: 'all' (AND, the default) or 'any' (OR). Ignored when there are fewer than two conditions. + +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub enum CustomConditionLogic { + All, + Any, + Other(S), +} + +impl CustomConditionLogic { + pub fn as_str(&self) -> &str { + match self { + Self::All => "all", + Self::Any => "any", + 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() { + "all" => Self::All, + "any" => Self::Any, + _ => Self::Other(s), + } + } +} + +impl core::fmt::Display for CustomConditionLogic { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!(f, "{}", self.as_str()) + } +} + +impl AsRef for CustomConditionLogic { + fn as_ref(&self) -> &str { + self.as_str() + } +} + +impl Serialize for CustomConditionLogic { + 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 CustomConditionLogic { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = S::deserialize(deserializer)?; + Ok(Self::from_value(s)) + } +} + +impl Default for CustomConditionLogic { + fn default() -> Self { + Self::Other(Default::default()) + } +} + +impl jacquard_common::IntoStatic for CustomConditionLogic +where + S: BosStr + jacquard_common::IntoStatic, + S::Output: BosStr, +{ + type Output = CustomConditionLogic; + fn into_static(self) -> Self::Output { + match self { + CustomConditionLogic::All => CustomConditionLogic::All, + CustomConditionLogic::Any => CustomConditionLogic::Any, + CustomConditionLogic::Other(v) => CustomConditionLogic::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 CustomGetRecordOutput { + #[serde(skip_serializing_if = "Option::is_none")] + pub cid: Option>, + pub uri: AtUri, + pub value: Custom, +} + +/// Provenance. An 'original' spell was crafted here; a 'learned' spell was copied from another user, carrying a backlink to its immediate parent (originalUri/originalDid) and to the top of its lineage (rootUri/rootDid), modelled on Bluesky reply parent/root refs so counts can be aggregated across re-shares. A 'preset' spell was seeded from a built-in template. + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic, Default)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct Source { + ///DID of the user this spell was learned from. + #[serde(skip_serializing_if = "Option::is_none")] + pub original_did: Option>, + ///AT URI of the spell this copy was learned from (its immediate parent). + #[serde(skip_serializing_if = "Option::is_none")] + pub original_uri: Option>, + ///Identifier of the built-in preset a 'preset' spell was seeded from. + #[serde(skip_serializing_if = "Option::is_none")] + pub preset_id: Option, + ///DID of the original crafter at the top of the lineage. + #[serde(skip_serializing_if = "Option::is_none")] + pub root_did: Option>, + ///AT URI of the first crafter's spell — the top of the lineage — propagated to every descendant. + #[serde(skip_serializing_if = "Option::is_none")] + pub root_uri: Option>, + #[serde(skip_serializing_if = "Option::is_none")] + pub r#type: Option>, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub enum SourceType { + Original, + Learned, + Preset, + Other(S), +} + +impl SourceType { + pub fn as_str(&self) -> &str { + match self { + Self::Original => "original", + Self::Learned => "learned", + Self::Preset => "preset", + 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() { + "original" => Self::Original, + "learned" => Self::Learned, + "preset" => Self::Preset, + _ => Self::Other(s), + } + } +} + +impl core::fmt::Display for SourceType { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!(f, "{}", self.as_str()) + } +} + +impl AsRef for SourceType { + fn as_ref(&self) -> &str { + self.as_str() + } +} + +impl Serialize for SourceType { + 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 SourceType { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = S::deserialize(deserializer)?; + Ok(Self::from_value(s)) + } +} + +impl Default for SourceType { + fn default() -> Self { + Self::Other(Default::default()) + } +} + +impl jacquard_common::IntoStatic for SourceType +where + S: BosStr + jacquard_common::IntoStatic, + S::Output: BosStr, +{ + type Output = SourceType; + fn into_static(self) -> Self::Output { + match self { + SourceType::Original => SourceType::Original, + SourceType::Learned => SourceType::Learned, + SourceType::Preset => SourceType::Preset, + SourceType::Other(v) => SourceType::Other(v.into_static()), + } + } +} + +/// An interval (timer) trigger. The spell fires every everyMinutes minutes rather than reacting continuously to its conditions. + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct Trigger { + ///Minutes between firings (1 minute to 24 hours). + pub every_minutes: i64, + pub r#type: TriggerType, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub enum TriggerType { + Interval, + Other(S), +} + +impl TriggerType { + pub fn as_str(&self) -> &str { + match self { + Self::Interval => "interval", + 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() { + "interval" => Self::Interval, + _ => Self::Other(s), + } + } +} + +impl core::fmt::Display for TriggerType { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!(f, "{}", self.as_str()) + } +} + +impl AsRef for TriggerType { + fn as_ref(&self) -> &str { + self.as_str() + } +} + +impl Serialize for TriggerType { + 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 TriggerType { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = S::deserialize(deserializer)?; + Ok(Self::from_value(s)) + } +} + +impl Default for TriggerType { + fn default() -> Self { + Self::Other(Default::default()) + } +} + +impl jacquard_common::IntoStatic for TriggerType +where + S: BosStr + jacquard_common::IntoStatic, + S::Output: BosStr, +{ + type Output = TriggerType; + fn into_static(self) -> Self::Output { + match self { + TriggerType::Interval => TriggerType::Interval, + TriggerType::Other(v) => TriggerType::Other(v.into_static()), + } + } +} + +impl Custom { + pub fn uri(uri: S) -> Result, UriError> { + RecordUri::try_from_uri(AtUri::new(uri)?) + } +} + +impl LexiconSchema for Condition { + fn nsid() -> &'static str { + "net.anisota.spell.custom" + } + fn def_name() -> &'static str { + "condition" + } + fn lexicon_doc() -> LexiconDoc<'static> { + lexicon_doc_net_anisota_spell_custom() + } + fn validate(&self) -> Result<(), ConstraintError> { + if let Some(values) = &self.metrics { + for value in values { + #[allow(unused_comparisons)] + if ::len(value.as_ref()) > 64usize { + return Err(ConstraintError::MaxLength { + path: ValidationPath::from_field("metrics"), + max: 64usize, + actual: ::len(value.as_ref()), + }); + } + } + } + { + let value = &self.variable; + #[allow(unused_comparisons)] + if ::len(value.as_ref()) > 64usize { + return Err(ConstraintError::MaxLength { + path: ValidationPath::from_field("variable"), + max: 64usize, + actual: ::len(value.as_ref()), + }); + } + } + if let Some(values) = &self.words { + for value in values { + #[allow(unused_comparisons)] + if ::len(value.as_ref()) > 100usize { + return Err(ConstraintError::MaxLength { + path: ValidationPath::from_field("words"), + max: 100usize, + actual: ::len(value.as_ref()), + }); + } + } + } + Ok(()) + } +} + +impl LexiconSchema for Effect { + fn nsid() -> &'static str { + "net.anisota.spell.custom" + } + fn def_name() -> &'static str { + "effect" + } + fn lexicon_doc() -> LexiconDoc<'static> { + lexicon_doc_net_anisota_spell_custom() + } + fn validate(&self) -> Result<(), ConstraintError> { + Ok(()) + } +} + +/// Marker type for deserializing records from this collection. + +#[derive(Debug, Serialize, Deserialize)] +pub struct CustomRecord; +impl XrpcResp for CustomRecord { + const NSID: &'static str = "net.anisota.spell.custom"; + const ENCODING: &'static str = "application/json"; + type Output = CustomGetRecordOutput; + type Err = RecordError; +} + +impl From> for Custom { + fn from(output: CustomGetRecordOutput) -> Self { + output.value + } +} + +impl Collection for Custom { + const NSID: &'static str = "net.anisota.spell.custom"; + type Record = CustomRecord; +} + +impl Collection for CustomRecord { + const NSID: &'static str = "net.anisota.spell.custom"; + type Record = CustomRecord; +} + +impl LexiconSchema for Custom { + fn nsid() -> &'static str { + "net.anisota.spell.custom" + } + fn def_name() -> &'static str { + "main" + } + fn lexicon_doc() -> LexiconDoc<'static> { + lexicon_doc_net_anisota_spell_custom() + } + fn validate(&self) -> Result<(), ConstraintError> { + if let Some(ref value) = self.description { + #[allow(unused_comparisons)] + if ::len(value.as_ref()) > 500usize { + return Err(ConstraintError::MaxLength { + path: ValidationPath::from_field("description"), + max: 500usize, + actual: ::len(value.as_ref()), + }); + } + } + { + let value = &self.name; + #[allow(unused_comparisons)] + if ::len(value.as_ref()) > 80usize { + return Err(ConstraintError::MaxLength { + path: ValidationPath::from_field("name"), + max: 80usize, + actual: ::len(value.as_ref()), + }); + } + } + Ok(()) + } +} + +impl LexiconSchema for Source { + fn nsid() -> &'static str { + "net.anisota.spell.custom" + } + fn def_name() -> &'static str { + "source" + } + fn lexicon_doc() -> LexiconDoc<'static> { + lexicon_doc_net_anisota_spell_custom() + } + fn validate(&self) -> Result<(), ConstraintError> { + if let Some(ref value) = self.preset_id { + #[allow(unused_comparisons)] + if ::len(value.as_ref()) > 64usize { + return Err(ConstraintError::MaxLength { + path: ValidationPath::from_field("preset_id"), + max: 64usize, + actual: ::len(value.as_ref()), + }); + } + } + Ok(()) + } +} + +impl LexiconSchema for Trigger { + fn nsid() -> &'static str { + "net.anisota.spell.custom" + } + fn def_name() -> &'static str { + "trigger" + } + fn lexicon_doc() -> LexiconDoc<'static> { + lexicon_doc_net_anisota_spell_custom() + } + fn validate(&self) -> Result<(), ConstraintError> { + { + let value = &self.every_minutes; + if *value > 1440i64 { + return Err(ConstraintError::Maximum { + path: ValidationPath::from_field("every_minutes"), + max: 1440i64, + actual: *value, + }); + } + } + { + let value = &self.every_minutes; + if *value < 1i64 { + return Err(ConstraintError::Minimum { + path: ValidationPath::from_field("every_minutes"), + min: 1i64, + actual: *value, + }); + } + } + Ok(()) + } +} + +fn lexicon_doc_net_anisota_spell_custom() -> 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("net.anisota.spell.custom"), + defs: { + let mut map = BTreeMap::new(); + map.insert( + SmolStr::new_static("condition"), + LexUserType::Object(LexObject { + description: Some( + CowStr::new_static( + "One 'if' clause: a variable compared against a value with an operator. Composite conditions (variable 'activitySum' / 'engagementSum') additionally carry a timeframe and a set of metrics to sum. Words-seen conditions (variable 'wordsSeen') additionally carry the word set to watch for and a counting scope. Each condition also carries an undeclared 'value' property — the thing being compared against. Its shape depends on the variable's type (a number, a 'HH:MM' string, a boolean, a two-element ['HH:MM','HH:MM'] array for time 'between', an integer 0-6 for dayOfWeek, a moon-phase / route / modal / date key string, or a { uri, name } object for a feed), so it is deliberately left out of the schema and validated client-side; lexicon 'unknown' means 'any object', which would reject the scalar cases.", + ), + ), + required: Some( + vec![ + SmolStr::new_static("variable"), + SmolStr::new_static("operator") + ], + ), + properties: { + #[allow(unused_mut)] + let mut map = BTreeMap::new(); + map.insert( + SmolStr::new_static("metrics"), + LexObjectProperty::Array(LexArray { + description: Some( + CowStr::new_static( + "Composite conditions only: which metric keys to sum (e.g. 'postsRead', 'postsCreated', 'repliesSent', 'likesReceived'). See spellService COMPOSITE_METRICS.", + ), + ), + items: LexArrayItem::String(LexString { + max_length: Some(64usize), + ..Default::default() + }), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("operator"), + LexObjectProperty::String(LexString { + description: Some( + CowStr::new_static( + "Comparison operator. Numeric/composite use gt/gte/lt/lte/eq/neq; time uses those plus 'between'; booleans use is/isNot; enumerated types (dayOfWeek, moonPhase, route, modal, feed, handle, date) use eq/neq.", + ), + ), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("scope"), + LexObjectProperty::String(LexString { + description: Some( + CowStr::new_static( + "Words-seen ('wordsSeen') conditions only: the window the sighting count covers — 'today' (the calendar day, the default) or 'session' (since the app was opened).", + ), + ), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("timeframe"), + LexObjectProperty::String(LexString { + description: Some( + CowStr::new_static( + "Composite conditions only: the window over which the chosen metrics are summed.", + ), + ), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("variable"), + LexObjectProperty::String(LexString { + description: Some( + CowStr::new_static( + "The context variable to test, e.g. 'timeOfDay', 'dayOfWeek', 'currentDate', 'stamina', 'level', 'lightRemaining', 'moonPhase', 'unreadNotifications', 'sessionMinutes', 'postsReadToday', 'activitySum', 'wordsSeen', 'currentRoute', 'activeModal', 'currentFeed', 'currentProfileHandle', 'isOnExpedition'. The full catalog is defined client-side in spellService VARIABLE_GROUPS.", + ), + ), + max_length: Some(64usize), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("words"), + LexObjectProperty::Array(LexArray { + description: Some( + CowStr::new_static( + "Words-seen ('wordsSeen') conditions only: the words to watch for, stored as trimmed lowercase strings. The condition counts posts containing any of these words as they flow through the viewer's feeds, and compares that count against 'value'.", + ), + ), + items: LexArrayItem::String(LexString { + max_length: Some(100usize), + ..Default::default() + }), + ..Default::default() + }), + ); + map + }, + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("effect"), + LexUserType::Object(LexObject { + description: Some( + CowStr::new_static( + "One 'then' clause: a typed effect on a UI surface. Continuously-applied effects flow through the live evaluation; the episodic types (showLockout, showAlert, redirect) are edge-triggered by their controllers. Each effect also carries an undeclared 'value' property — the payload, whose shape depends on target+type: an array of element/button/action/menu keys for the multi-select hide effects; a { rkey, name } layout reference or { rkey, name, keys } for hideElements; an array of word-list snapshots [{ rkey, name, words, strength, targetFeeds }] for activateList — the words are carried inline so a learned spell still works on a PDS where the referenced net.anisota.graph.wordlist record doesn't exist; or a config object for showLockout (message/scope/duration/bypass/…), showAlert (title/message/cooldownMinutes/…), redirect ({ route, cooldownMinutes }), sigilBeforePost ({ source, sigilShape }), overrideSetting ({ id, value }), or warnBefore* ({ action|element, message, gate }). toggleMode carries no value. It is left out of the schema and validated client-side because lexicon 'unknown' means 'any object', which would reject the array and string payloads.", + ), + ), + required: Some( + vec![SmolStr::new_static("target"), SmolStr::new_static("type")], + ), + properties: { + #[allow(unused_mut)] + let mut map = BTreeMap::new(); + map.insert( + SmolStr::new_static("target"), + LexObjectProperty::String(LexString { + description: Some( + CowStr::new_static("The UI surface the effect acts on."), + ), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("type"), + LexObjectProperty::String(LexString { + description: Some( + CowStr::new_static( + "The specific effect within the target. Valid types depend on the target (see spellService EFFECT_TARGETS). hideButton/showButton/setButtons are legacy observatory effects kept for backward compatibility.", + ), + ), + ..Default::default() + }), + ); + map + }, + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("main"), + LexUserType::Record(LexRecord { + description: Some( + CowStr::new_static( + "A user-authored 'spell' — a conditional rule that produces typed effects on the Anisota interface (hiding elements, switching layouts, showing a lockout/alert, redirecting, overriding a setting, and so on). Each spell is a complete, self-contained record so it can be shared by URL and 'learned' (copied) into another user's PDS without depending on the author's other records, mirroring the net.anisota.observatory.layout architecture. A spell is evaluated against a context snapshot (time, activity, player state, location, …); a spell with no conditions is a manual 'mode' that applies whenever it is cast. Whether a spell is currently cast and in what order lives in the separate net.anisota.spell.book index, not here. The effect 'value' is a heterogeneous union whose shape depends on target+type (a string, number, boolean, [start,end] pair, key list, or a config object such as a lockout/alert/sigil/setting-override), so it is left as 'unknown' and validated client-side.", + ), + ), + key: Some(CowStr::new_static("any")), + record: LexRecordRecord::Object(LexObject { + required: Some( + vec![ + SmolStr::new_static("name"), SmolStr::new_static("effects"), + SmolStr::new_static("createdAt"), + SmolStr::new_static("updatedAt") + ], + ), + properties: { + #[allow(unused_mut)] + let mut map = BTreeMap::new(); + map.insert( + SmolStr::new_static("conditionLogic"), + LexObjectProperty::String(LexString { + description: Some( + CowStr::new_static( + "How multiple conditions combine: 'all' (AND, the default) or 'any' (OR). Ignored when there are fewer than two conditions.", + ), + ), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("conditions"), + LexObjectProperty::Array(LexArray { + description: Some( + CowStr::new_static( + "The 'if' clauses evaluated against the live context. Empty or absent means the spell has no conditions — it applies whenever it is cast (a manual 'mode' spell), or, for an interval-triggered spell, fires on every tick.", + ), + ), + items: LexArrayItem::Ref(LexRef { + r#ref: CowStr::new_static("#condition"), + ..Default::default() + }), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("createdAt"), + LexObjectProperty::String(LexString { + description: Some( + CowStr::new_static("When this spell was first crafted"), + ), + format: Some(LexStringFormat::Datetime), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("description"), + LexObjectProperty::String(LexString { + description: Some( + CowStr::new_static( + "Optional description of what this spell does", + ), + ), + max_length: Some(500usize), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("effects"), + LexObjectProperty::Array(LexArray { + description: Some( + CowStr::new_static( + "The 'then' clauses — what the spell does when it applies. At least one is expected.", + ), + ), + items: LexArrayItem::Ref(LexRef { + r#ref: CowStr::new_static("#effect"), + ..Default::default() + }), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("name"), + LexObjectProperty::String(LexString { + description: Some( + CowStr::new_static("Display name for this spell"), + ), + max_length: Some(80usize), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("source"), + LexObjectProperty::Ref(LexRef { + r#ref: CowStr::new_static("#source"), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("trigger"), + LexObjectProperty::Ref(LexRef { + r#ref: CowStr::new_static("#trigger"), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("updatedAt"), + LexObjectProperty::String(LexString { + description: Some( + CowStr::new_static("When this spell was last modified"), + ), + format: Some(LexStringFormat::Datetime), + ..Default::default() + }), + ); + map + }, + ..Default::default() + }), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("source"), + LexUserType::Object(LexObject { + description: Some( + CowStr::new_static( + "Provenance. An 'original' spell was crafted here; a 'learned' spell was copied from another user, carrying a backlink to its immediate parent (originalUri/originalDid) and to the top of its lineage (rootUri/rootDid), modelled on Bluesky reply parent/root refs so counts can be aggregated across re-shares. A 'preset' spell was seeded from a built-in template.", + ), + ), + properties: { + #[allow(unused_mut)] + let mut map = BTreeMap::new(); + map.insert( + SmolStr::new_static("originalDid"), + LexObjectProperty::String(LexString { + description: Some( + CowStr::new_static( + "DID of the user this spell was learned from.", + ), + ), + format: Some(LexStringFormat::Did), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("originalUri"), + LexObjectProperty::String(LexString { + description: Some( + CowStr::new_static( + "AT URI of the spell this copy was learned from (its immediate parent).", + ), + ), + format: Some(LexStringFormat::AtUri), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("presetId"), + LexObjectProperty::String(LexString { + description: Some( + CowStr::new_static( + "Identifier of the built-in preset a 'preset' spell was seeded from.", + ), + ), + max_length: Some(64usize), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("rootDid"), + LexObjectProperty::String(LexString { + description: Some( + CowStr::new_static( + "DID of the original crafter at the top of the lineage.", + ), + ), + format: Some(LexStringFormat::Did), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("rootUri"), + LexObjectProperty::String(LexString { + description: Some( + CowStr::new_static( + "AT URI of the first crafter's spell — the top of the lineage — propagated to every descendant.", + ), + ), + format: Some(LexStringFormat::AtUri), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("type"), + LexObjectProperty::String(LexString { ..Default::default() }), + ); + map + }, + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("trigger"), + LexUserType::Object(LexObject { + description: Some( + CowStr::new_static( + "An interval (timer) trigger. The spell fires every everyMinutes minutes rather than reacting continuously to its conditions.", + ), + ), + required: Some( + vec![ + SmolStr::new_static("type"), + SmolStr::new_static("everyMinutes") + ], + ), + properties: { + #[allow(unused_mut)] + let mut map = BTreeMap::new(); + map.insert( + SmolStr::new_static("everyMinutes"), + LexObjectProperty::Integer(LexInteger { + minimum: Some(1i64), + maximum: Some(1440i64), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("type"), + LexObjectProperty::String(LexString { ..Default::default() }), + ); + map + }, + ..Default::default() + }), + ); + map + }, + ..Default::default() + } +} + +pub mod custom_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 Effects; + type Name; + type UpdatedAt; + } + /// Empty state - all required fields are unset + pub struct Empty(()); + impl sealed::Sealed for Empty {} + impl State for Empty { + type CreatedAt = Unset; + type Effects = Unset; + type Name = Unset; + type UpdatedAt = 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 Effects = St::Effects; + type Name = St::Name; + type UpdatedAt = St::UpdatedAt; + } + ///State transition - sets the `effects` field to Set + pub struct SetEffects(PhantomData St>); + impl sealed::Sealed for SetEffects {} + impl State for SetEffects { + type CreatedAt = St::CreatedAt; + type Effects = Set; + type Name = St::Name; + type UpdatedAt = St::UpdatedAt; + } + ///State transition - sets the `name` field to Set + pub struct SetName(PhantomData St>); + impl sealed::Sealed for SetName {} + impl State for SetName { + type CreatedAt = St::CreatedAt; + type Effects = St::Effects; + type Name = Set; + type UpdatedAt = St::UpdatedAt; + } + ///State transition - sets the `updated_at` field to Set + pub struct SetUpdatedAt(PhantomData St>); + impl sealed::Sealed for SetUpdatedAt {} + impl State for SetUpdatedAt { + type CreatedAt = St::CreatedAt; + type Effects = St::Effects; + type Name = St::Name; + type UpdatedAt = 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 `effects` field + pub struct effects(()); + ///Marker type for the `name` field + pub struct name(()); + ///Marker type for the `updated_at` field + pub struct updated_at(()); + } +} + +/// Builder for constructing an instance of this type. +pub struct CustomBuilder { + _state: PhantomData St>, + _fields: ( + Option>, + Option>>, + Option, + Option, + Option>>, + Option, + Option>, + Option>, + Option, + ), + _type: PhantomData S>, +} + +impl Custom { + /// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed + pub fn new() -> CustomBuilder { + CustomBuilder::new() + } +} + +impl Custom { + /// Create a new builder for this type + pub fn builder() -> CustomBuilder { + CustomBuilder::builder() + } +} + +impl CustomBuilder { + /// Create a new builder with all fields unset, using the default string type, if needed + pub fn new() -> Self { + CustomBuilder { + _state: PhantomData, + _fields: (None, None, None, None, None, None, None, None, None), + _type: PhantomData, + } + } +} + +impl CustomBuilder { + /// Create a new builder with all fields unset + pub fn builder() -> Self { + CustomBuilder { + _state: PhantomData, + _fields: (None, None, None, None, None, None, None, None, None), + _type: PhantomData, + } + } +} + +impl CustomBuilder { + /// Set the `conditionLogic` field (optional) + pub fn condition_logic(mut self, value: impl Into>>) -> Self { + self._fields.0 = value.into(); + self + } + /// Set the `conditionLogic` field to an Option value (optional) + pub fn maybe_condition_logic(mut self, value: Option>) -> Self { + self._fields.0 = value; + self + } +} + +impl CustomBuilder { + /// Set the `conditions` field (optional) + pub fn conditions(mut self, value: impl Into>>>) -> Self { + self._fields.1 = value.into(); + self + } + /// Set the `conditions` field to an Option value (optional) + pub fn maybe_conditions(mut self, value: Option>>) -> Self { + self._fields.1 = value; + self + } +} + +impl CustomBuilder +where + St: custom_state::State, + St::CreatedAt: custom_state::IsUnset, +{ + /// Set the `createdAt` field (required) + pub fn created_at( + mut self, + value: impl Into, + ) -> CustomBuilder, S> { + self._fields.2 = Option::Some(value.into()); + CustomBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl CustomBuilder { + /// Set the `description` field (optional) + pub fn description(mut self, value: impl Into>) -> Self { + self._fields.3 = value.into(); + self + } + /// Set the `description` field to an Option value (optional) + pub fn maybe_description(mut self, value: Option) -> Self { + self._fields.3 = value; + self + } +} + +impl CustomBuilder +where + St: custom_state::State, + St::Effects: custom_state::IsUnset, +{ + /// Set the `effects` field (required) + pub fn effects( + mut self, + value: impl Into>>, + ) -> CustomBuilder, S> { + self._fields.4 = Option::Some(value.into()); + CustomBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl CustomBuilder +where + St: custom_state::State, + St::Name: custom_state::IsUnset, +{ + /// Set the `name` field (required) + pub fn name(mut self, value: impl Into) -> CustomBuilder, S> { + self._fields.5 = Option::Some(value.into()); + CustomBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl CustomBuilder { + /// Set the `source` field (optional) + pub fn source(mut self, value: impl Into>>) -> Self { + self._fields.6 = value.into(); + self + } + /// Set the `source` field to an Option value (optional) + pub fn maybe_source(mut self, value: Option>) -> Self { + self._fields.6 = value; + self + } +} + +impl CustomBuilder { + /// Set the `trigger` field (optional) + pub fn trigger(mut self, value: impl Into>>) -> Self { + self._fields.7 = value.into(); + self + } + /// Set the `trigger` field to an Option value (optional) + pub fn maybe_trigger(mut self, value: Option>) -> Self { + self._fields.7 = value; + self + } +} + +impl CustomBuilder +where + St: custom_state::State, + St::UpdatedAt: custom_state::IsUnset, +{ + /// Set the `updatedAt` field (required) + pub fn updated_at( + mut self, + value: impl Into, + ) -> CustomBuilder, S> { + self._fields.8 = Option::Some(value.into()); + CustomBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl CustomBuilder +where + St: custom_state::State, + St::CreatedAt: custom_state::IsSet, + St::Effects: custom_state::IsSet, + St::Name: custom_state::IsSet, + St::UpdatedAt: custom_state::IsSet, +{ + /// Build the final struct. + pub fn build(self) -> Custom { + Custom { + condition_logic: self._fields.0, + conditions: self._fields.1, + created_at: self._fields.2.unwrap(), + description: self._fields.3, + effects: self._fields.4.unwrap(), + name: self._fields.5.unwrap(), + source: self._fields.6, + trigger: self._fields.7, + updated_at: self._fields.8.unwrap(), + extra_data: Default::default(), + } + } + /// Build the final struct with custom extra_data. + pub fn build_with_data(self, extra_data: BTreeMap>) -> Custom { + Custom { + condition_logic: self._fields.0, + conditions: self._fields.1, + created_at: self._fields.2.unwrap(), + description: self._fields.3, + effects: self._fields.4.unwrap(), + name: self._fields.5.unwrap(), + source: self._fields.6, + trigger: self._fields.7, + updated_at: self._fields.8.unwrap(), + extra_data: Some(extra_data), + } + } +} + +pub mod trigger_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 EveryMinutes; + type Type; + } + /// Empty state - all required fields are unset + pub struct Empty(()); + impl sealed::Sealed for Empty {} + impl State for Empty { + type EveryMinutes = Unset; + type Type = Unset; + } + ///State transition - sets the `every_minutes` field to Set + pub struct SetEveryMinutes(PhantomData St>); + impl sealed::Sealed for SetEveryMinutes {} + impl State for SetEveryMinutes { + type EveryMinutes = Set; + type Type = St::Type; + } + ///State transition - sets the `type` field to Set + pub struct SetType(PhantomData St>); + impl sealed::Sealed for SetType {} + impl State for SetType { + type EveryMinutes = St::EveryMinutes; + type Type = Set; + } + /// Marker types for field names + #[allow(non_camel_case_types)] + pub mod members { + ///Marker type for the `every_minutes` field + pub struct every_minutes(()); + ///Marker type for the `type` field + pub struct r#type(()); + } +} + +/// Builder for constructing an instance of this type. +pub struct TriggerBuilder { + _state: PhantomData St>, + _fields: (Option, Option>), + _type: PhantomData S>, +} + +impl Trigger { + /// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed + pub fn new() -> TriggerBuilder { + TriggerBuilder::new() + } +} + +impl Trigger { + /// Create a new builder for this type + pub fn builder() -> TriggerBuilder { + TriggerBuilder::builder() + } +} + +impl TriggerBuilder { + /// Create a new builder with all fields unset, using the default string type, if needed + pub fn new() -> Self { + TriggerBuilder { + _state: PhantomData, + _fields: (None, None), + _type: PhantomData, + } + } +} + +impl TriggerBuilder { + /// Create a new builder with all fields unset + pub fn builder() -> Self { + TriggerBuilder { + _state: PhantomData, + _fields: (None, None), + _type: PhantomData, + } + } +} + +impl TriggerBuilder +where + St: trigger_state::State, + St::EveryMinutes: trigger_state::IsUnset, +{ + /// Set the `everyMinutes` field (required) + pub fn every_minutes( + mut self, + value: impl Into, + ) -> TriggerBuilder, S> { + self._fields.0 = Option::Some(value.into()); + TriggerBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl TriggerBuilder +where + St: trigger_state::State, + St::Type: trigger_state::IsUnset, +{ + /// Set the `type` field (required) + pub fn r#type( + mut self, + value: impl Into>, + ) -> TriggerBuilder, S> { + self._fields.1 = Option::Some(value.into()); + TriggerBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl TriggerBuilder +where + St: trigger_state::State, + St::EveryMinutes: trigger_state::IsSet, + St::Type: trigger_state::IsSet, +{ + /// Build the final struct. + pub fn build(self) -> Trigger { + Trigger { + every_minutes: self._fields.0.unwrap(), + r#type: self._fields.1.unwrap(), + extra_data: Default::default(), + } + } + /// Build the final struct with custom extra_data. + pub fn build_with_data(self, extra_data: BTreeMap>) -> Trigger { + Trigger { + every_minutes: self._fields.0.unwrap(), + r#type: self._fields.1.unwrap(), + extra_data: Some(extra_data), + } + } +} diff --git a/crates/jacquard-api/src/net_shwilliam/hyphae/note.rs b/crates/jacquard-api/src/net_shwilliam/hyphae/note.rs index aeaea1cbe..89ac4e3ec 100644 --- a/crates/jacquard-api/src/net_shwilliam/hyphae/note.rs +++ b/crates/jacquard-api/src/net_shwilliam/hyphae/note.rs @@ -126,6 +126,32 @@ impl LexiconSchema for Note { }); } } + if let Some(values) = &self.tags { + for value in values { + #[allow(unused_comparisons)] + if ::len(value.as_ref()) > 640usize { + return Err(ConstraintError::MaxLength { + path: ValidationPath::from_field("tags"), + max: 640usize, + actual: ::len(value.as_ref()), + }); + } + } + } + if let Some(values) = &self.tags { + for value in values { + { + let count = UnicodeSegmentation::graphemes(value.as_ref(), true).count(); + if count > 64usize { + return Err(ConstraintError::MaxGraphemes { + path: ValidationPath::from_field("tags"), + max: 64usize, + actual: count, + }); + } + } + } + } { let value = &self.text; #[allow(unused_comparisons)] diff --git a/crates/jacquard-api/src/org_hypercerts/helper/work_scope_tag.rs b/crates/jacquard-api/src/org_hypercerts/helper/work_scope_tag.rs index 5fdd024d6..706974ae8 100644 --- a/crates/jacquard-api/src/org_hypercerts/helper/work_scope_tag.rs +++ b/crates/jacquard-api/src/org_hypercerts/helper/work_scope_tag.rs @@ -140,6 +140,18 @@ impl LexiconSchema for WorkScopeTag { }); } } + if let Some(values) = &self.aliases { + for value in values { + #[allow(unused_comparisons)] + if ::len(value.as_ref()) > 200usize { + return Err(ConstraintError::MaxLength { + path: ValidationPath::from_field("aliases"), + max: 200usize, + actual: ::len(value.as_ref()), + }); + } + } + } if let Some(ref value) = self.description { #[allow(unused_comparisons)] if ::len(value.as_ref()) > 10000usize { diff --git a/crates/jacquard-api/src/org_hypercerts/workscope/tag.rs b/crates/jacquard-api/src/org_hypercerts/workscope/tag.rs index 90c41d547..657cc66ba 100644 --- a/crates/jacquard-api/src/org_hypercerts/workscope/tag.rs +++ b/crates/jacquard-api/src/org_hypercerts/workscope/tag.rs @@ -319,6 +319,18 @@ impl LexiconSchema for Tag { }); } } + if let Some(values) = &self.aliases { + for value in values { + #[allow(unused_comparisons)] + if ::len(value.as_ref()) > 200usize { + return Err(ConstraintError::MaxLength { + path: ValidationPath::from_field("aliases"), + max: 200usize, + actual: ::len(value.as_ref()), + }); + } + } + } if let Some(ref value) = self.category { #[allow(unused_comparisons)] if ::len(value.as_ref()) > 50usize { @@ -383,6 +395,18 @@ impl LexiconSchema for Tag { }); } } + if let Some(values) = &self.same_as { + for value in values { + #[allow(unused_comparisons)] + if ::len(value.as_ref()) > 2048usize { + return Err(ConstraintError::MaxLength { + path: ValidationPath::from_field("same_as"), + max: 2048usize, + actual: ::len(value.as_ref()), + }); + } + } + } if let Some(ref value) = self.status { #[allow(unused_comparisons)] if ::len(value.as_ref()) > 20usize { diff --git a/crates/jacquard-api/src/org_impactindexer/review.rs b/crates/jacquard-api/src/org_impactindexer/review.rs index 6b332b47f..610958c52 100644 --- a/crates/jacquard-api/src/org_impactindexer/review.rs +++ b/crates/jacquard-api/src/org_impactindexer/review.rs @@ -149,6 +149,17 @@ impl LexiconSchema for SubjectRef { }); } } + { + let value = &self.r#type; + #[allow(unused_comparisons)] + if ::len(value.as_ref()) > 32usize { + return Err(ConstraintError::MaxLength { + path: ValidationPath::from_field("type"), + max: 32usize, + actual: ::len(value.as_ref()), + }); + } + } { let value = &self.uri; #[allow(unused_comparisons)] diff --git a/crates/jacquard-api/src/org_passingreads/book/registration.rs b/crates/jacquard-api/src/org_passingreads/book/registration.rs index db39b3022..3eea29fdf 100644 --- a/crates/jacquard-api/src/org_passingreads/book/registration.rs +++ b/crates/jacquard-api/src/org_passingreads/book/registration.rs @@ -122,6 +122,26 @@ impl LexiconSchema for Registration { lexicon_doc_org_passingreads_book_registration() } fn validate(&self) -> Result<(), ConstraintError> { + for value in &self.authors { + #[allow(unused_comparisons)] + if ::len(value.as_ref()) > 512usize { + return Err(ConstraintError::MaxLength { + path: ValidationPath::from_field("authors"), + max: 512usize, + actual: ::len(value.as_ref()), + }); + } + } + for value in &self.authors { + #[allow(unused_comparisons)] + if ::len(value.as_ref()) < 1usize { + return Err(ConstraintError::MinLength { + path: ValidationPath::from_field("authors"), + min: 1usize, + actual: ::len(value.as_ref()), + }); + } + } if let Some(ref value) = self.cover { { let size = value.blob().size; diff --git a/crates/jacquard-api/src/org_stormlightlabs/malfestio/deck.rs b/crates/jacquard-api/src/org_stormlightlabs/malfestio/deck.rs index aa103daba..b61f9e11d 100644 --- a/crates/jacquard-api/src/org_stormlightlabs/malfestio/deck.rs +++ b/crates/jacquard-api/src/org_stormlightlabs/malfestio/deck.rs @@ -245,6 +245,18 @@ impl LexiconSchema for Deck { }); } } + if let Some(values) = &self.tags { + for value in values { + #[allow(unused_comparisons)] + if ::len(value.as_ref()) > 100usize { + return Err(ConstraintError::MaxLength { + path: ValidationPath::from_field("tags"), + max: 100usize, + actual: ::len(value.as_ref()), + }); + } + } + } { let value = &self.title; #[allow(unused_comparisons)] diff --git a/crates/jacquard-api/src/org_tangled.rs b/crates/jacquard-api/src/org_tangled.rs new file mode 100644 index 000000000..9561833d3 --- /dev/null +++ b/crates/jacquard-api/src/org_tangled.rs @@ -0,0 +1,7 @@ +// @generated by jacquard-lexicon. DO NOT EDIT. +// +// This file was automatically generated from Lexicon schemas. +// Any manual changes will be overwritten on the next regeneration. + +//! Generated bindings for the `org.tangled` Lexicon namespace/module. +pub mod temp; diff --git a/crates/jacquard-api/src/org_tangled/temp.rs b/crates/jacquard-api/src/org_tangled/temp.rs new file mode 100644 index 000000000..fc8a8190e --- /dev/null +++ b/crates/jacquard-api/src/org_tangled/temp.rs @@ -0,0 +1,12 @@ +// @generated by jacquard-lexicon. DO NOT EDIT. +// +// This file was automatically generated from Lexicon schemas. +// Any manual changes will be overwritten on the next regeneration. + +//! Generated bindings for the `org.tangled.temp` Lexicon namespace/module. +pub mod account; +pub mod focus; +pub mod notification; +pub mod repo; +pub mod search; +pub mod site; diff --git a/crates/jacquard-api/src/org_tangled/temp/account.rs b/crates/jacquard-api/src/org_tangled/temp/account.rs new file mode 100644 index 000000000..190111ce1 --- /dev/null +++ b/crates/jacquard-api/src/org_tangled/temp/account.rs @@ -0,0 +1,13 @@ +// @generated by jacquard-lexicon. DO NOT EDIT. +// +// This file was automatically generated from Lexicon schemas. +// Any manual changes will be overwritten on the next regeneration. + +//! Generated bindings for the `org.tangled.temp.account` Lexicon namespace/module. +pub mod begin_signup; +pub mod complete_signup; +pub mod delete_email; +pub mod dismiss_newsletter; +pub mod list_emails; +pub mod set_primary_email; +pub mod subscribe_newsletter; diff --git a/crates/jacquard-api/src/org_tangled/temp/account/begin_signup.rs b/crates/jacquard-api/src/org_tangled/temp/account/begin_signup.rs new file mode 100644 index 000000000..319bf41e7 --- /dev/null +++ b/crates/jacquard-api/src/org_tangled/temp/account/begin_signup.rs @@ -0,0 +1,128 @@ +// @generated by jacquard-lexicon. DO NOT EDIT. +// +// Lexicon: org.tangled.temp.account.beginSignup +// +// 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::deps::smol_str::SmolStr; +use jacquard_common::types::value::Data; +use jacquard_common::{BosStr, CowStr, DefaultStr, FromStaticStr}; +use jacquard_derive::{IntoStatic, open_union}; +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic, Default)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct BeginSignup { + ///Email address for the new account. + pub email: S, + ///Cloudflare Turnstile challenge response token. + pub turnstile_token: S, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +#[derive( + Serialize, Deserialize, Debug, Clone, PartialEq, Eq, thiserror::Error, miette::Diagnostic, +)] +#[serde(tag = "error", content = "message")] +pub enum BeginSignupError { + /// Signup is not currently enabled on this service. + #[serde(rename = "SignupDisabled")] + SignupDisabled(Option), + /// The Turnstile captcha response could not be verified. + #[serde(rename = "InvalidTurnstileToken")] + InvalidTurnstileToken(Option), + /// The email address is not valid. + #[serde(rename = "InvalidEmail")] + InvalidEmail(Option), + /// An account already exists for this email address. + #[serde(rename = "EmailAlreadyRegistered")] + EmailAlreadyRegistered(Option), + /// Catch-all for unknown error codes. + #[serde(untagged)] + Other { + error: SmolStr, + message: Option, + }, +} + +impl core::fmt::Display for BeginSignupError { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + match self { + Self::SignupDisabled(msg) => { + write!(f, "SignupDisabled")?; + if let Some(msg) = msg { + write!(f, ": {}", msg)?; + } + Ok(()) + } + Self::InvalidTurnstileToken(msg) => { + write!(f, "InvalidTurnstileToken")?; + if let Some(msg) = msg { + write!(f, ": {}", msg)?; + } + Ok(()) + } + Self::InvalidEmail(msg) => { + write!(f, "InvalidEmail")?; + if let Some(msg) = msg { + write!(f, ": {}", msg)?; + } + Ok(()) + } + Self::EmailAlreadyRegistered(msg) => { + write!(f, "EmailAlreadyRegistered")?; + if let Some(msg) = msg { + write!(f, ": {}", msg)?; + } + Ok(()) + } + Self::Other { error, message } => { + write!(f, "{}", error)?; + if let Some(msg) = message { + write!(f, ": {}", msg)?; + } + Ok(()) + } + } + } +} + +/** Response marker for the `org.tangled.temp.account.beginSignup` procedure. + +Implements `jacquard_common::xrpc::XrpcResp`; successful bodies decode as `Self::Output`, which is `()` for this endpoint.*/ +pub struct BeginSignupResponse; +impl jacquard_common::xrpc::XrpcResp for BeginSignupResponse { + const NSID: &'static str = "org.tangled.temp.account.beginSignup"; + const ENCODING: &'static str = "application/json"; + type Output = (); + type Err = BeginSignupError; +} + +impl jacquard_common::xrpc::XrpcRequest for BeginSignup { + const NSID: &'static str = "org.tangled.temp.account.beginSignup"; + const METHOD: jacquard_common::xrpc::XrpcMethod = + jacquard_common::xrpc::XrpcMethod::Procedure("application/json"); + type Response = BeginSignupResponse; +} + +/** Endpoint marker for the `org.tangled.temp.account.beginSignup` procedure. + +Path: `/xrpc/org.tangled.temp.account.beginSignup`. The request payload type is `BeginSignup`; send that request with `jacquard::Client` or use this marker through lower-level `XrpcEndpoint` APIs.*/ +pub struct BeginSignupRequest; +impl jacquard_common::xrpc::XrpcEndpoint for BeginSignupRequest { + const PATH: &'static str = "/xrpc/org.tangled.temp.account.beginSignup"; + const METHOD: jacquard_common::xrpc::XrpcMethod = + jacquard_common::xrpc::XrpcMethod::Procedure("application/json"); + type Request = BeginSignup; + type Response = BeginSignupResponse; +} diff --git a/crates/jacquard-api/src/org_tangled/temp/account/complete_signup.rs b/crates/jacquard-api/src/org_tangled/temp/account/complete_signup.rs new file mode 100644 index 000000000..7f8da8634 --- /dev/null +++ b/crates/jacquard-api/src/org_tangled/temp/account/complete_signup.rs @@ -0,0 +1,145 @@ +// @generated by jacquard-lexicon. DO NOT EDIT. +// +// Lexicon: org.tangled.temp.account.completeSignup +// +// 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::deps::smol_str::SmolStr; +use jacquard_common::types::string::Did; +use jacquard_common::types::value::Data; +use jacquard_common::{BosStr, CowStr, DefaultStr, FromStaticStr}; +use jacquard_derive::{IntoStatic, open_union}; +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic, Default)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct CompleteSignup { + ///Verification code from the signup email. + pub code: S, + ///Password for the new account. + pub password: S, + ///Desired username; the assigned handle is .. + pub username: S, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct CompleteSignupOutput { + ///DID of the newly provisioned account. + pub did: Did, + ///The assigned handle, .. + pub handle: S, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +#[derive( + Serialize, Deserialize, Debug, Clone, PartialEq, Eq, thiserror::Error, miette::Diagnostic, +)] +#[serde(tag = "error", content = "message")] +pub enum CompleteSignupError { + /// Signup is not currently enabled on this service. + #[serde(rename = "SignupDisabled")] + SignupDisabled(Option), + /// Username must be 4-63 characters, lowercase letters, digits, or hyphens, and cannot start or end with a hyphen. + #[serde(rename = "InvalidUsername")] + InvalidUsername(Option), + /// This username is reserved or already taken. + #[serde(rename = "UsernameUnavailable")] + UsernameUnavailable(Option), + /// The verification code is invalid or has expired. + #[serde(rename = "InvalidCode")] + InvalidCode(Option), + /// Catch-all for unknown error codes. + #[serde(untagged)] + Other { + error: SmolStr, + message: Option, + }, +} + +impl core::fmt::Display for CompleteSignupError { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + match self { + Self::SignupDisabled(msg) => { + write!(f, "SignupDisabled")?; + if let Some(msg) = msg { + write!(f, ": {}", msg)?; + } + Ok(()) + } + Self::InvalidUsername(msg) => { + write!(f, "InvalidUsername")?; + if let Some(msg) = msg { + write!(f, ": {}", msg)?; + } + Ok(()) + } + Self::UsernameUnavailable(msg) => { + write!(f, "UsernameUnavailable")?; + if let Some(msg) = msg { + write!(f, ": {}", msg)?; + } + Ok(()) + } + Self::InvalidCode(msg) => { + write!(f, "InvalidCode")?; + if let Some(msg) = msg { + write!(f, ": {}", msg)?; + } + Ok(()) + } + Self::Other { error, message } => { + write!(f, "{}", error)?; + if let Some(msg) = message { + write!(f, ": {}", msg)?; + } + Ok(()) + } + } + } +} + +/** Response marker for the `org.tangled.temp.account.completeSignup` procedure. + +Implements `jacquard_common::xrpc::XrpcResp`; successful bodies decode as `Self::Output`, which is `CompleteSignupOutput` for this endpoint.*/ +pub struct CompleteSignupResponse; +impl jacquard_common::xrpc::XrpcResp for CompleteSignupResponse { + const NSID: &'static str = "org.tangled.temp.account.completeSignup"; + const ENCODING: &'static str = "application/json"; + type Output = CompleteSignupOutput; + type Err = CompleteSignupError; +} + +impl jacquard_common::xrpc::XrpcRequest for CompleteSignup { + const NSID: &'static str = "org.tangled.temp.account.completeSignup"; + const METHOD: jacquard_common::xrpc::XrpcMethod = + jacquard_common::xrpc::XrpcMethod::Procedure("application/json"); + type Response = CompleteSignupResponse; +} + +/** Endpoint marker for the `org.tangled.temp.account.completeSignup` procedure. + +Path: `/xrpc/org.tangled.temp.account.completeSignup`. The request payload type is `CompleteSignup`; send that request with `jacquard::Client` or use this marker through lower-level `XrpcEndpoint` APIs.*/ +pub struct CompleteSignupRequest; +impl jacquard_common::xrpc::XrpcEndpoint for CompleteSignupRequest { + const PATH: &'static str = "/xrpc/org.tangled.temp.account.completeSignup"; + const METHOD: jacquard_common::xrpc::XrpcMethod = + jacquard_common::xrpc::XrpcMethod::Procedure("application/json"); + type Request = CompleteSignup; + type Response = CompleteSignupResponse; +} diff --git a/crates/jacquard-api/src/org_tangled/temp/account/delete_email.rs b/crates/jacquard-api/src/org_tangled/temp/account/delete_email.rs new file mode 100644 index 000000000..d363f6032 --- /dev/null +++ b/crates/jacquard-api/src/org_tangled/temp/account/delete_email.rs @@ -0,0 +1,96 @@ +// @generated by jacquard-lexicon. DO NOT EDIT. +// +// Lexicon: org.tangled.temp.account.deleteEmail +// +// 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::deps::smol_str::SmolStr; +use jacquard_common::types::value::Data; +use jacquard_common::{BosStr, CowStr, DefaultStr, FromStaticStr}; +use jacquard_derive::{IntoStatic, open_union}; +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic, Default)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct DeleteEmail { + ///Email address to remove. + pub email: S, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +#[derive( + Serialize, Deserialize, Debug, Clone, PartialEq, Eq, thiserror::Error, miette::Diagnostic, +)] +#[serde(tag = "error", content = "message")] +pub enum DeleteEmailError { + /// The primary email address cannot be deleted. Set another address as primary first. + #[serde(rename = "CannotDeletePrimary")] + CannotDeletePrimary(Option), + /// Catch-all for unknown error codes. + #[serde(untagged)] + Other { + error: SmolStr, + message: Option, + }, +} + +impl core::fmt::Display for DeleteEmailError { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + match self { + Self::CannotDeletePrimary(msg) => { + write!(f, "CannotDeletePrimary")?; + if let Some(msg) = msg { + write!(f, ": {}", msg)?; + } + Ok(()) + } + Self::Other { error, message } => { + write!(f, "{}", error)?; + if let Some(msg) = message { + write!(f, ": {}", msg)?; + } + Ok(()) + } + } + } +} + +/** Response marker for the `org.tangled.temp.account.deleteEmail` procedure. + +Implements `jacquard_common::xrpc::XrpcResp`; successful bodies decode as `Self::Output`, which is `()` for this endpoint.*/ +pub struct DeleteEmailResponse; +impl jacquard_common::xrpc::XrpcResp for DeleteEmailResponse { + const NSID: &'static str = "org.tangled.temp.account.deleteEmail"; + const ENCODING: &'static str = "application/json"; + type Output = (); + type Err = DeleteEmailError; +} + +impl jacquard_common::xrpc::XrpcRequest for DeleteEmail { + const NSID: &'static str = "org.tangled.temp.account.deleteEmail"; + const METHOD: jacquard_common::xrpc::XrpcMethod = + jacquard_common::xrpc::XrpcMethod::Procedure("application/json"); + type Response = DeleteEmailResponse; +} + +/** Endpoint marker for the `org.tangled.temp.account.deleteEmail` procedure. + +Path: `/xrpc/org.tangled.temp.account.deleteEmail`. The request payload type is `DeleteEmail`; send that request with `jacquard::Client` or use this marker through lower-level `XrpcEndpoint` APIs.*/ +pub struct DeleteEmailRequest; +impl jacquard_common::xrpc::XrpcEndpoint for DeleteEmailRequest { + const PATH: &'static str = "/xrpc/org.tangled.temp.account.deleteEmail"; + const METHOD: jacquard_common::xrpc::XrpcMethod = + jacquard_common::xrpc::XrpcMethod::Procedure("application/json"); + type Request = DeleteEmail; + type Response = DeleteEmailResponse; +} diff --git a/crates/jacquard-api/src/org_tangled/temp/account/dismiss_newsletter.rs b/crates/jacquard-api/src/org_tangled/temp/account/dismiss_newsletter.rs new file mode 100644 index 000000000..4c575abed --- /dev/null +++ b/crates/jacquard-api/src/org_tangled/temp/account/dismiss_newsletter.rs @@ -0,0 +1,52 @@ +// @generated by jacquard-lexicon. DO NOT EDIT. +// +// Lexicon: org.tangled.temp.account.dismissNewsletter +// +// 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::deps::smol_str::SmolStr; +use jacquard_common::types::value::Data; +use jacquard_common::{BosStr, DefaultStr, FromStaticStr}; +use jacquard_derive::IntoStatic; +use serde::{Deserialize, Serialize}; +/** Request marker for the `org.tangled.temp.account.dismissNewsletter` procedure. + +This endpoint has no request parameters or input body; send this marker with `jacquard::Client`.*/ + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic, Copy)] +pub struct DismissNewsletter; +/** Response marker for the `org.tangled.temp.account.dismissNewsletter` procedure. + +Implements `jacquard_common::xrpc::XrpcResp`; successful bodies decode as `Self::Output`, which is `()` for this endpoint.*/ +pub struct DismissNewsletterResponse; +impl jacquard_common::xrpc::XrpcResp for DismissNewsletterResponse { + const NSID: &'static str = "org.tangled.temp.account.dismissNewsletter"; + const ENCODING: &'static str = "application/json"; + type Output = (); + type Err = jacquard_common::xrpc::GenericError; +} + +impl jacquard_common::xrpc::XrpcRequest for DismissNewsletter { + const NSID: &'static str = "org.tangled.temp.account.dismissNewsletter"; + const METHOD: jacquard_common::xrpc::XrpcMethod = + jacquard_common::xrpc::XrpcMethod::Procedure("application/json"); + type Response = DismissNewsletterResponse; +} + +/** Endpoint marker for the `org.tangled.temp.account.dismissNewsletter` procedure. + +Path: `/xrpc/org.tangled.temp.account.dismissNewsletter`. The request payload type is `DismissNewsletter`; use this marker with lower-level `XrpcEndpoint` APIs when you need endpoint metadata.*/ +pub struct DismissNewsletterRequest; +impl jacquard_common::xrpc::XrpcEndpoint for DismissNewsletterRequest { + const PATH: &'static str = "/xrpc/org.tangled.temp.account.dismissNewsletter"; + const METHOD: jacquard_common::xrpc::XrpcMethod = + jacquard_common::xrpc::XrpcMethod::Procedure("application/json"); + type Request = DismissNewsletter; + type Response = DismissNewsletterResponse; +} diff --git a/crates/jacquard-api/src/org_tangled/temp/account/list_emails.rs b/crates/jacquard-api/src/org_tangled/temp/account/list_emails.rs new file mode 100644 index 000000000..5fb644c99 --- /dev/null +++ b/crates/jacquard-api/src/org_tangled/temp/account/list_emails.rs @@ -0,0 +1,390 @@ +// @generated by jacquard-lexicon. DO NOT EDIT. +// +// Lexicon: org.tangled.temp.account.listEmails +// +// 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::string::Datetime; +use jacquard_common::types::value::Data; +use jacquard_derive::IntoStatic; +use jacquard_lexicon::lexicon::LexiconDoc; +use jacquard_lexicon::schema::LexiconSchema; + +use crate::org_tangled::temp::account::list_emails; +#[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", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct Email { + ///Email address. + pub address: S, + pub created_at: Datetime, + ///Whether this is the primary email address. + pub primary: bool, + ///Whether the address has been verified. + pub verified: bool, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct ListEmailsOutput { + pub emails: Vec>, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +impl LexiconSchema for Email { + fn nsid() -> &'static str { + "org.tangled.temp.account.listEmails" + } + fn def_name() -> &'static str { + "email" + } + fn lexicon_doc() -> LexiconDoc<'static> { + lexicon_doc_org_tangled_temp_account_listEmails() + } + fn validate(&self) -> Result<(), ConstraintError> { + Ok(()) + } +} + +/** Request marker for the `org.tangled.temp.account.listEmails` query. + +This endpoint has no request parameters or input body; send this marker with `jacquard::Client`.*/ + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic, Copy)] +pub struct ListEmails; +/** Response marker for the `org.tangled.temp.account.listEmails` query. + +Implements `jacquard_common::xrpc::XrpcResp`; successful bodies decode as `Self::Output`, which is `ListEmailsOutput` for this endpoint.*/ +pub struct ListEmailsResponse; +impl jacquard_common::xrpc::XrpcResp for ListEmailsResponse { + const NSID: &'static str = "org.tangled.temp.account.listEmails"; + const ENCODING: &'static str = "application/json"; + type Output = ListEmailsOutput; + type Err = jacquard_common::xrpc::GenericError; +} + +impl jacquard_common::xrpc::XrpcRequest for ListEmails { + const NSID: &'static str = "org.tangled.temp.account.listEmails"; + const METHOD: jacquard_common::xrpc::XrpcMethod = jacquard_common::xrpc::XrpcMethod::Query; + type Response = ListEmailsResponse; +} + +/** Endpoint marker for the `org.tangled.temp.account.listEmails` query. + +Path: `/xrpc/org.tangled.temp.account.listEmails`. The request payload type is `ListEmails`; use this marker with lower-level `XrpcEndpoint` APIs when you need endpoint metadata.*/ +pub struct ListEmailsRequest; +impl jacquard_common::xrpc::XrpcEndpoint for ListEmailsRequest { + const PATH: &'static str = "/xrpc/org.tangled.temp.account.listEmails"; + const METHOD: jacquard_common::xrpc::XrpcMethod = jacquard_common::xrpc::XrpcMethod::Query; + type Request = ListEmails; + type Response = ListEmailsResponse; +} + +pub mod email_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 Address; + type CreatedAt; + type Primary; + type Verified; + } + /// Empty state - all required fields are unset + pub struct Empty(()); + impl sealed::Sealed for Empty {} + impl State for Empty { + type Address = Unset; + type CreatedAt = Unset; + type Primary = Unset; + type Verified = Unset; + } + ///State transition - sets the `address` field to Set + pub struct SetAddress(PhantomData St>); + impl sealed::Sealed for SetAddress {} + impl State for SetAddress { + type Address = Set; + type CreatedAt = St::CreatedAt; + type Primary = St::Primary; + type Verified = St::Verified; + } + ///State transition - sets the `created_at` field to Set + pub struct SetCreatedAt(PhantomData St>); + impl sealed::Sealed for SetCreatedAt {} + impl State for SetCreatedAt { + type Address = St::Address; + type CreatedAt = Set; + type Primary = St::Primary; + type Verified = St::Verified; + } + ///State transition - sets the `primary` field to Set + pub struct SetPrimary(PhantomData St>); + impl sealed::Sealed for SetPrimary {} + impl State for SetPrimary { + type Address = St::Address; + type CreatedAt = St::CreatedAt; + type Primary = Set; + type Verified = St::Verified; + } + ///State transition - sets the `verified` field to Set + pub struct SetVerified(PhantomData St>); + impl sealed::Sealed for SetVerified {} + impl State for SetVerified { + type Address = St::Address; + type CreatedAt = St::CreatedAt; + type Primary = St::Primary; + type Verified = Set; + } + /// Marker types for field names + #[allow(non_camel_case_types)] + pub mod members { + ///Marker type for the `address` field + pub struct address(()); + ///Marker type for the `created_at` field + pub struct created_at(()); + ///Marker type for the `primary` field + pub struct primary(()); + ///Marker type for the `verified` field + pub struct verified(()); + } +} + +/// Builder for constructing an instance of this type. +pub struct EmailBuilder { + _state: PhantomData St>, + _fields: (Option, Option, Option, Option), + _type: PhantomData S>, +} + +impl Email { + /// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed + pub fn new() -> EmailBuilder { + EmailBuilder::new() + } +} + +impl Email { + /// Create a new builder for this type + pub fn builder() -> EmailBuilder { + EmailBuilder::builder() + } +} + +impl EmailBuilder { + /// Create a new builder with all fields unset, using the default string type, if needed + pub fn new() -> Self { + EmailBuilder { + _state: PhantomData, + _fields: (None, None, None, None), + _type: PhantomData, + } + } +} + +impl EmailBuilder { + /// Create a new builder with all fields unset + pub fn builder() -> Self { + EmailBuilder { + _state: PhantomData, + _fields: (None, None, None, None), + _type: PhantomData, + } + } +} + +impl EmailBuilder +where + St: email_state::State, + St::Address: email_state::IsUnset, +{ + /// Set the `address` field (required) + pub fn address(mut self, value: impl Into) -> EmailBuilder, S> { + self._fields.0 = Option::Some(value.into()); + EmailBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl EmailBuilder +where + St: email_state::State, + St::CreatedAt: email_state::IsUnset, +{ + /// Set the `createdAt` field (required) + pub fn created_at( + mut self, + value: impl Into, + ) -> EmailBuilder, S> { + self._fields.1 = Option::Some(value.into()); + EmailBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl EmailBuilder +where + St: email_state::State, + St::Primary: email_state::IsUnset, +{ + /// Set the `primary` field (required) + pub fn primary( + mut self, + value: impl Into, + ) -> EmailBuilder, S> { + self._fields.2 = Option::Some(value.into()); + EmailBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl EmailBuilder +where + St: email_state::State, + St::Verified: email_state::IsUnset, +{ + /// Set the `verified` field (required) + pub fn verified( + mut self, + value: impl Into, + ) -> EmailBuilder, S> { + self._fields.3 = Option::Some(value.into()); + EmailBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl EmailBuilder +where + St: email_state::State, + St::Address: email_state::IsSet, + St::CreatedAt: email_state::IsSet, + St::Primary: email_state::IsSet, + St::Verified: email_state::IsSet, +{ + /// Build the final struct. + pub fn build(self) -> Email { + Email { + address: self._fields.0.unwrap(), + created_at: self._fields.1.unwrap(), + primary: self._fields.2.unwrap(), + verified: self._fields.3.unwrap(), + extra_data: Default::default(), + } + } + /// Build the final struct with custom extra_data. + pub fn build_with_data(self, extra_data: BTreeMap>) -> Email { + Email { + address: self._fields.0.unwrap(), + created_at: self._fields.1.unwrap(), + primary: self._fields.2.unwrap(), + verified: self._fields.3.unwrap(), + extra_data: Some(extra_data), + } + } +} + +fn lexicon_doc_org_tangled_temp_account_listEmails() -> 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("org.tangled.temp.account.listEmails"), + defs: { + let mut map = BTreeMap::new(); + map.insert( + SmolStr::new_static("email"), + LexUserType::Object(LexObject { + required: Some(vec![ + SmolStr::new_static("address"), + SmolStr::new_static("verified"), + SmolStr::new_static("primary"), + SmolStr::new_static("createdAt"), + ]), + properties: { + #[allow(unused_mut)] + let mut map = BTreeMap::new(); + map.insert( + SmolStr::new_static("address"), + LexObjectProperty::String(LexString { + description: Some(CowStr::new_static("Email address.")), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("createdAt"), + LexObjectProperty::String(LexString { + format: Some(LexStringFormat::Datetime), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("primary"), + LexObjectProperty::Boolean(LexBoolean { + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("verified"), + LexObjectProperty::Boolean(LexBoolean { + ..Default::default() + }), + ); + map + }, + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("main"), + LexUserType::XrpcQuery(LexXrpcQuery { + parameters: None, + ..Default::default() + }), + ); + map + }, + ..Default::default() + } +} diff --git a/crates/jacquard-api/src/org_tangled/temp/account/set_primary_email.rs b/crates/jacquard-api/src/org_tangled/temp/account/set_primary_email.rs new file mode 100644 index 000000000..87772ebb5 --- /dev/null +++ b/crates/jacquard-api/src/org_tangled/temp/account/set_primary_email.rs @@ -0,0 +1,106 @@ +// @generated by jacquard-lexicon. DO NOT EDIT. +// +// Lexicon: org.tangled.temp.account.setPrimaryEmail +// +// 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::deps::smol_str::SmolStr; +use jacquard_common::types::value::Data; +use jacquard_common::{BosStr, CowStr, DefaultStr, FromStaticStr}; +use jacquard_derive::{IntoStatic, open_union}; +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic, Default)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct SetPrimaryEmail { + ///Email address to promote to primary. + pub email: S, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +#[derive( + Serialize, Deserialize, Debug, Clone, PartialEq, Eq, thiserror::Error, miette::Diagnostic, +)] +#[serde(tag = "error", content = "message")] +pub enum SetPrimaryEmailError { + /// The email address must be verified before it can be made primary. + #[serde(rename = "EmailNotVerified")] + EmailNotVerified(Option), + /// The email address is not associated with this account. + #[serde(rename = "EmailNotFound")] + EmailNotFound(Option), + /// Catch-all for unknown error codes. + #[serde(untagged)] + Other { + error: SmolStr, + message: Option, + }, +} + +impl core::fmt::Display for SetPrimaryEmailError { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + match self { + Self::EmailNotVerified(msg) => { + write!(f, "EmailNotVerified")?; + if let Some(msg) = msg { + write!(f, ": {}", msg)?; + } + Ok(()) + } + Self::EmailNotFound(msg) => { + write!(f, "EmailNotFound")?; + if let Some(msg) = msg { + write!(f, ": {}", msg)?; + } + Ok(()) + } + Self::Other { error, message } => { + write!(f, "{}", error)?; + if let Some(msg) = message { + write!(f, ": {}", msg)?; + } + Ok(()) + } + } + } +} + +/** Response marker for the `org.tangled.temp.account.setPrimaryEmail` procedure. + +Implements `jacquard_common::xrpc::XrpcResp`; successful bodies decode as `Self::Output`, which is `()` for this endpoint.*/ +pub struct SetPrimaryEmailResponse; +impl jacquard_common::xrpc::XrpcResp for SetPrimaryEmailResponse { + const NSID: &'static str = "org.tangled.temp.account.setPrimaryEmail"; + const ENCODING: &'static str = "application/json"; + type Output = (); + type Err = SetPrimaryEmailError; +} + +impl jacquard_common::xrpc::XrpcRequest for SetPrimaryEmail { + const NSID: &'static str = "org.tangled.temp.account.setPrimaryEmail"; + const METHOD: jacquard_common::xrpc::XrpcMethod = + jacquard_common::xrpc::XrpcMethod::Procedure("application/json"); + type Response = SetPrimaryEmailResponse; +} + +/** Endpoint marker for the `org.tangled.temp.account.setPrimaryEmail` procedure. + +Path: `/xrpc/org.tangled.temp.account.setPrimaryEmail`. The request payload type is `SetPrimaryEmail`; send that request with `jacquard::Client` or use this marker through lower-level `XrpcEndpoint` APIs.*/ +pub struct SetPrimaryEmailRequest; +impl jacquard_common::xrpc::XrpcEndpoint for SetPrimaryEmailRequest { + const PATH: &'static str = "/xrpc/org.tangled.temp.account.setPrimaryEmail"; + const METHOD: jacquard_common::xrpc::XrpcMethod = + jacquard_common::xrpc::XrpcMethod::Procedure("application/json"); + type Request = SetPrimaryEmail; + type Response = SetPrimaryEmailResponse; +} diff --git a/crates/jacquard-api/src/org_tangled/temp/account/subscribe_newsletter.rs b/crates/jacquard-api/src/org_tangled/temp/account/subscribe_newsletter.rs new file mode 100644 index 000000000..c8eaf064c --- /dev/null +++ b/crates/jacquard-api/src/org_tangled/temp/account/subscribe_newsletter.rs @@ -0,0 +1,52 @@ +// @generated by jacquard-lexicon. DO NOT EDIT. +// +// Lexicon: org.tangled.temp.account.subscribeNewsletter +// +// 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::deps::smol_str::SmolStr; +use jacquard_common::types::value::Data; +use jacquard_common::{BosStr, DefaultStr, FromStaticStr}; +use jacquard_derive::IntoStatic; +use serde::{Deserialize, Serialize}; +/** Request marker for the `org.tangled.temp.account.subscribeNewsletter` procedure. + +This endpoint has no request parameters or input body; send this marker with `jacquard::Client`.*/ + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic, Copy)] +pub struct SubscribeNewsletter; +/** Response marker for the `org.tangled.temp.account.subscribeNewsletter` procedure. + +Implements `jacquard_common::xrpc::XrpcResp`; successful bodies decode as `Self::Output`, which is `()` for this endpoint.*/ +pub struct SubscribeNewsletterResponse; +impl jacquard_common::xrpc::XrpcResp for SubscribeNewsletterResponse { + const NSID: &'static str = "org.tangled.temp.account.subscribeNewsletter"; + const ENCODING: &'static str = "application/json"; + type Output = (); + type Err = jacquard_common::xrpc::GenericError; +} + +impl jacquard_common::xrpc::XrpcRequest for SubscribeNewsletter { + const NSID: &'static str = "org.tangled.temp.account.subscribeNewsletter"; + const METHOD: jacquard_common::xrpc::XrpcMethod = + jacquard_common::xrpc::XrpcMethod::Procedure("application/json"); + type Response = SubscribeNewsletterResponse; +} + +/** Endpoint marker for the `org.tangled.temp.account.subscribeNewsletter` procedure. + +Path: `/xrpc/org.tangled.temp.account.subscribeNewsletter`. The request payload type is `SubscribeNewsletter`; use this marker with lower-level `XrpcEndpoint` APIs when you need endpoint metadata.*/ +pub struct SubscribeNewsletterRequest; +impl jacquard_common::xrpc::XrpcEndpoint for SubscribeNewsletterRequest { + const PATH: &'static str = "/xrpc/org.tangled.temp.account.subscribeNewsletter"; + const METHOD: jacquard_common::xrpc::XrpcMethod = + jacquard_common::xrpc::XrpcMethod::Procedure("application/json"); + type Request = SubscribeNewsletter; + type Response = SubscribeNewsletterResponse; +} diff --git a/crates/jacquard-api/src/org_tangled/temp/focus.rs b/crates/jacquard-api/src/org_tangled/temp/focus.rs new file mode 100644 index 000000000..cde0e50b5 --- /dev/null +++ b/crates/jacquard-api/src/org_tangled/temp/focus.rs @@ -0,0 +1,9 @@ +// @generated by jacquard-lexicon. DO NOT EDIT. +// +// This file was automatically generated from Lexicon schemas. +// Any manual changes will be overwritten on the next regeneration. + +//! Generated bindings for the `org.tangled.temp.focus` Lexicon namespace/module. +pub mod begin_session; +pub mod end_session; +pub mod next_item; diff --git a/crates/jacquard-api/src/org_tangled/temp/focus/begin_session.rs b/crates/jacquard-api/src/org_tangled/temp/focus/begin_session.rs new file mode 100644 index 000000000..3f4777ce1 --- /dev/null +++ b/crates/jacquard-api/src/org_tangled/temp/focus/begin_session.rs @@ -0,0 +1,113 @@ +// @generated by jacquard-lexicon. DO NOT EDIT. +// +// Lexicon: org.tangled.temp.focus.beginSession +// +// 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::deps::smol_str::SmolStr; +use jacquard_common::types::string::{AtUri, Did}; +use jacquard_common::types::value::Data; +use jacquard_common::{BosStr, CowStr, DefaultStr, FromStaticStr}; +use jacquard_derive::{IntoStatic, open_union}; +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic, Default)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct BeginSessionOutput { + ///AT-URI of the issue to navigate to, if the item is an issue. + #[serde(skip_serializing_if = "Option::is_none")] + pub issue_at: Option>, + ///ID of the first notification to address. Absent if the queue is empty. + #[serde(skip_serializing_if = "Option::is_none")] + pub notification_id: Option, + ///AT-URI of the pull to navigate to, if the item is a pull. + #[serde(skip_serializing_if = "Option::is_none")] + pub pull_at: Option>, + ///DID of the repository the item belongs to. Absent if the queue is empty. + #[serde(skip_serializing_if = "Option::is_none")] + pub repo_did: Option>, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +#[derive( + Serialize, Deserialize, Debug, Clone, PartialEq, Eq, thiserror::Error, miette::Diagnostic, +)] +#[serde(tag = "error", content = "message")] +pub enum BeginSessionError { + /// There are no unread work notifications to focus on. + #[serde(rename = "NoFocusItems")] + NoFocusItems(Option), + /// Catch-all for unknown error codes. + #[serde(untagged)] + Other { + error: SmolStr, + message: Option, + }, +} + +impl core::fmt::Display for BeginSessionError { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + match self { + Self::NoFocusItems(msg) => { + write!(f, "NoFocusItems")?; + if let Some(msg) = msg { + write!(f, ": {}", msg)?; + } + Ok(()) + } + Self::Other { error, message } => { + write!(f, "{}", error)?; + if let Some(msg) = message { + write!(f, ": {}", msg)?; + } + Ok(()) + } + } + } +} + +/** Request marker for the `org.tangled.temp.focus.beginSession` procedure. + +This endpoint has no request parameters or input body; send this marker with `jacquard::Client`.*/ + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic, Copy)] +pub struct BeginSession; +/** Response marker for the `org.tangled.temp.focus.beginSession` procedure. + +Implements `jacquard_common::xrpc::XrpcResp`; successful bodies decode as `Self::Output`, which is `BeginSessionOutput` for this endpoint.*/ +pub struct BeginSessionResponse; +impl jacquard_common::xrpc::XrpcResp for BeginSessionResponse { + const NSID: &'static str = "org.tangled.temp.focus.beginSession"; + const ENCODING: &'static str = "application/json"; + type Output = BeginSessionOutput; + type Err = BeginSessionError; +} + +impl jacquard_common::xrpc::XrpcRequest for BeginSession { + const NSID: &'static str = "org.tangled.temp.focus.beginSession"; + const METHOD: jacquard_common::xrpc::XrpcMethod = + jacquard_common::xrpc::XrpcMethod::Procedure("application/json"); + type Response = BeginSessionResponse; +} + +/** Endpoint marker for the `org.tangled.temp.focus.beginSession` procedure. + +Path: `/xrpc/org.tangled.temp.focus.beginSession`. The request payload type is `BeginSession`; use this marker with lower-level `XrpcEndpoint` APIs when you need endpoint metadata.*/ +pub struct BeginSessionRequest; +impl jacquard_common::xrpc::XrpcEndpoint for BeginSessionRequest { + const PATH: &'static str = "/xrpc/org.tangled.temp.focus.beginSession"; + const METHOD: jacquard_common::xrpc::XrpcMethod = + jacquard_common::xrpc::XrpcMethod::Procedure("application/json"); + type Request = BeginSession; + type Response = BeginSessionResponse; +} diff --git a/crates/jacquard-api/src/org_tangled/temp/focus/end_session.rs b/crates/jacquard-api/src/org_tangled/temp/focus/end_session.rs new file mode 100644 index 000000000..bac7238ee --- /dev/null +++ b/crates/jacquard-api/src/org_tangled/temp/focus/end_session.rs @@ -0,0 +1,52 @@ +// @generated by jacquard-lexicon. DO NOT EDIT. +// +// Lexicon: org.tangled.temp.focus.endSession +// +// 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::deps::smol_str::SmolStr; +use jacquard_common::types::value::Data; +use jacquard_common::{BosStr, DefaultStr, FromStaticStr}; +use jacquard_derive::IntoStatic; +use serde::{Deserialize, Serialize}; +/** Request marker for the `org.tangled.temp.focus.endSession` procedure. + +This endpoint has no request parameters or input body; send this marker with `jacquard::Client`.*/ + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic, Copy)] +pub struct EndSession; +/** Response marker for the `org.tangled.temp.focus.endSession` procedure. + +Implements `jacquard_common::xrpc::XrpcResp`; successful bodies decode as `Self::Output`, which is `()` for this endpoint.*/ +pub struct EndSessionResponse; +impl jacquard_common::xrpc::XrpcResp for EndSessionResponse { + const NSID: &'static str = "org.tangled.temp.focus.endSession"; + const ENCODING: &'static str = "application/json"; + type Output = (); + type Err = jacquard_common::xrpc::GenericError; +} + +impl jacquard_common::xrpc::XrpcRequest for EndSession { + const NSID: &'static str = "org.tangled.temp.focus.endSession"; + const METHOD: jacquard_common::xrpc::XrpcMethod = + jacquard_common::xrpc::XrpcMethod::Procedure("application/json"); + type Response = EndSessionResponse; +} + +/** Endpoint marker for the `org.tangled.temp.focus.endSession` procedure. + +Path: `/xrpc/org.tangled.temp.focus.endSession`. The request payload type is `EndSession`; use this marker with lower-level `XrpcEndpoint` APIs when you need endpoint metadata.*/ +pub struct EndSessionRequest; +impl jacquard_common::xrpc::XrpcEndpoint for EndSessionRequest { + const PATH: &'static str = "/xrpc/org.tangled.temp.focus.endSession"; + const METHOD: jacquard_common::xrpc::XrpcMethod = + jacquard_common::xrpc::XrpcMethod::Procedure("application/json"); + type Request = EndSession; + type Response = EndSessionResponse; +} diff --git a/crates/jacquard-api/src/org_tangled/temp/focus/next_item.rs b/crates/jacquard-api/src/org_tangled/temp/focus/next_item.rs new file mode 100644 index 000000000..f64602087 --- /dev/null +++ b/crates/jacquard-api/src/org_tangled/temp/focus/next_item.rs @@ -0,0 +1,197 @@ +// @generated by jacquard-lexicon. DO NOT EDIT. +// +// Lexicon: org.tangled.temp.focus.nextItem +// +// 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::deps::smol_str::SmolStr; +use jacquard_common::types::string::{AtUri, Did}; +use jacquard_common::types::value::Data; +use jacquard_common::{BosStr, DefaultStr, FromStaticStr}; +use jacquard_derive::IntoStatic; +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct NextItem { + ///ID of the notification just addressed, to be marked read. + pub current_id: i64, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic, Default)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct NextItemOutput { + ///AT-URI of the issue to navigate to, if the item is an issue. + #[serde(skip_serializing_if = "Option::is_none")] + pub issue_at: Option>, + ///ID of the next notification to address. Absent when focus mode has ended. + #[serde(skip_serializing_if = "Option::is_none")] + pub notification_id: Option, + ///AT-URI of the pull to navigate to, if the item is a pull. + #[serde(skip_serializing_if = "Option::is_none")] + pub pull_at: Option>, + ///DID of the repository the next item belongs to. Absent when focus mode has ended. + #[serde(skip_serializing_if = "Option::is_none")] + pub repo_did: Option>, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +/** Response marker for the `org.tangled.temp.focus.nextItem` procedure. + +Implements `jacquard_common::xrpc::XrpcResp`; successful bodies decode as `Self::Output`, which is `NextItemOutput` for this endpoint.*/ +pub struct NextItemResponse; +impl jacquard_common::xrpc::XrpcResp for NextItemResponse { + const NSID: &'static str = "org.tangled.temp.focus.nextItem"; + const ENCODING: &'static str = "application/json"; + type Output = NextItemOutput; + type Err = jacquard_common::xrpc::GenericError; +} + +impl jacquard_common::xrpc::XrpcRequest for NextItem { + const NSID: &'static str = "org.tangled.temp.focus.nextItem"; + const METHOD: jacquard_common::xrpc::XrpcMethod = + jacquard_common::xrpc::XrpcMethod::Procedure("application/json"); + type Response = NextItemResponse; +} + +/** Endpoint marker for the `org.tangled.temp.focus.nextItem` procedure. + +Path: `/xrpc/org.tangled.temp.focus.nextItem`. The request payload type is `NextItem`; send that request with `jacquard::Client` or use this marker through lower-level `XrpcEndpoint` APIs.*/ +pub struct NextItemRequest; +impl jacquard_common::xrpc::XrpcEndpoint for NextItemRequest { + const PATH: &'static str = "/xrpc/org.tangled.temp.focus.nextItem"; + const METHOD: jacquard_common::xrpc::XrpcMethod = + jacquard_common::xrpc::XrpcMethod::Procedure("application/json"); + type Request = NextItem; + type Response = NextItemResponse; +} + +pub mod next_item_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 CurrentId; + } + /// Empty state - all required fields are unset + pub struct Empty(()); + impl sealed::Sealed for Empty {} + impl State for Empty { + type CurrentId = Unset; + } + ///State transition - sets the `current_id` field to Set + pub struct SetCurrentId(PhantomData St>); + impl sealed::Sealed for SetCurrentId {} + impl State for SetCurrentId { + type CurrentId = Set; + } + /// Marker types for field names + #[allow(non_camel_case_types)] + pub mod members { + ///Marker type for the `current_id` field + pub struct current_id(()); + } +} + +/// Builder for constructing an instance of this type. +pub struct NextItemBuilder { + _state: PhantomData St>, + _fields: (Option,), + _type: PhantomData S>, +} + +impl NextItem { + /// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed + pub fn new() -> NextItemBuilder { + NextItemBuilder::new() + } +} + +impl NextItem { + /// Create a new builder for this type + pub fn builder() -> NextItemBuilder { + NextItemBuilder::builder() + } +} + +impl NextItemBuilder { + /// Create a new builder with all fields unset, using the default string type, if needed + pub fn new() -> Self { + NextItemBuilder { + _state: PhantomData, + _fields: (None,), + _type: PhantomData, + } + } +} + +impl NextItemBuilder { + /// Create a new builder with all fields unset + pub fn builder() -> Self { + NextItemBuilder { + _state: PhantomData, + _fields: (None,), + _type: PhantomData, + } + } +} + +impl NextItemBuilder +where + St: next_item_state::State, + St::CurrentId: next_item_state::IsUnset, +{ + /// Set the `currentId` field (required) + pub fn current_id( + mut self, + value: impl Into, + ) -> NextItemBuilder, S> { + self._fields.0 = Option::Some(value.into()); + NextItemBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl NextItemBuilder +where + St: next_item_state::State, + St::CurrentId: next_item_state::IsSet, +{ + /// Build the final struct. + pub fn build(self) -> NextItem { + NextItem { + current_id: self._fields.0.unwrap(), + extra_data: Default::default(), + } + } + /// Build the final struct with custom extra_data. + pub fn build_with_data(self, extra_data: BTreeMap>) -> NextItem { + NextItem { + current_id: self._fields.0.unwrap(), + extra_data: Some(extra_data), + } + } +} diff --git a/crates/jacquard-api/src/org_tangled/temp/notification.rs b/crates/jacquard-api/src/org_tangled/temp/notification.rs new file mode 100644 index 000000000..ff108aae9 --- /dev/null +++ b/crates/jacquard-api/src/org_tangled/temp/notification.rs @@ -0,0 +1,13 @@ +// @generated by jacquard-lexicon. DO NOT EDIT. +// +// This file was automatically generated from Lexicon schemas. +// Any manual changes will be overwritten on the next regeneration. + +//! Generated bindings for the `org.tangled.temp.notification` Lexicon namespace/module. +pub mod delete_notification; +pub mod get_preferences; +pub mod get_unread_count; +pub mod list_notifications; +pub mod mark_all_read; +pub mod update_preferences; +pub mod update_seen; diff --git a/crates/jacquard-api/src/org_tangled/temp/notification/delete_notification.rs b/crates/jacquard-api/src/org_tangled/temp/notification/delete_notification.rs new file mode 100644 index 000000000..fc532c02f --- /dev/null +++ b/crates/jacquard-api/src/org_tangled/temp/notification/delete_notification.rs @@ -0,0 +1,174 @@ +// @generated by jacquard-lexicon. DO NOT EDIT. +// +// Lexicon: org.tangled.temp.notification.deleteNotification +// +// 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::deps::smol_str::SmolStr; +use jacquard_common::types::value::Data; +use jacquard_common::{BosStr, DefaultStr, FromStaticStr}; +use jacquard_derive::IntoStatic; +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct DeleteNotification { + ///ID of the notification to delete. + pub id: i64, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +/** Response marker for the `org.tangled.temp.notification.deleteNotification` procedure. + +Implements `jacquard_common::xrpc::XrpcResp`; successful bodies decode as `Self::Output`, which is `()` for this endpoint.*/ +pub struct DeleteNotificationResponse; +impl jacquard_common::xrpc::XrpcResp for DeleteNotificationResponse { + const NSID: &'static str = "org.tangled.temp.notification.deleteNotification"; + const ENCODING: &'static str = "application/json"; + type Output = (); + type Err = jacquard_common::xrpc::GenericError; +} + +impl jacquard_common::xrpc::XrpcRequest for DeleteNotification { + const NSID: &'static str = "org.tangled.temp.notification.deleteNotification"; + const METHOD: jacquard_common::xrpc::XrpcMethod = + jacquard_common::xrpc::XrpcMethod::Procedure("application/json"); + type Response = DeleteNotificationResponse; +} + +/** Endpoint marker for the `org.tangled.temp.notification.deleteNotification` procedure. + +Path: `/xrpc/org.tangled.temp.notification.deleteNotification`. The request payload type is `DeleteNotification`; send that request with `jacquard::Client` or use this marker through lower-level `XrpcEndpoint` APIs.*/ +pub struct DeleteNotificationRequest; +impl jacquard_common::xrpc::XrpcEndpoint for DeleteNotificationRequest { + const PATH: &'static str = "/xrpc/org.tangled.temp.notification.deleteNotification"; + const METHOD: jacquard_common::xrpc::XrpcMethod = + jacquard_common::xrpc::XrpcMethod::Procedure("application/json"); + type Request = DeleteNotification; + type Response = DeleteNotificationResponse; +} + +pub mod delete_notification_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 Id; + } + /// Empty state - all required fields are unset + pub struct Empty(()); + impl sealed::Sealed for Empty {} + impl State for Empty { + type Id = Unset; + } + ///State transition - sets the `id` field to Set + pub struct SetId(PhantomData St>); + impl sealed::Sealed for SetId {} + impl State for SetId { + type Id = Set; + } + /// Marker types for field names + #[allow(non_camel_case_types)] + pub mod members { + ///Marker type for the `id` field + pub struct id(()); + } +} + +/// Builder for constructing an instance of this type. +pub struct DeleteNotificationBuilder { + _state: PhantomData St>, + _fields: (Option,), + _type: PhantomData S>, +} + +impl DeleteNotification { + /// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed + pub fn new() -> DeleteNotificationBuilder { + DeleteNotificationBuilder::new() + } +} + +impl DeleteNotification { + /// Create a new builder for this type + pub fn builder() -> DeleteNotificationBuilder { + DeleteNotificationBuilder::builder() + } +} + +impl DeleteNotificationBuilder { + /// Create a new builder with all fields unset, using the default string type, if needed + pub fn new() -> Self { + DeleteNotificationBuilder { + _state: PhantomData, + _fields: (None,), + _type: PhantomData, + } + } +} + +impl DeleteNotificationBuilder { + /// Create a new builder with all fields unset + pub fn builder() -> Self { + DeleteNotificationBuilder { + _state: PhantomData, + _fields: (None,), + _type: PhantomData, + } + } +} + +impl DeleteNotificationBuilder +where + St: delete_notification_state::State, + St::Id: delete_notification_state::IsUnset, +{ + /// Set the `id` field (required) + pub fn id( + mut self, + value: impl Into, + ) -> DeleteNotificationBuilder, S> { + self._fields.0 = Option::Some(value.into()); + DeleteNotificationBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl DeleteNotificationBuilder +where + St: delete_notification_state::State, + St::Id: delete_notification_state::IsSet, +{ + /// Build the final struct. + pub fn build(self) -> DeleteNotification { + DeleteNotification { + id: self._fields.0.unwrap(), + extra_data: Default::default(), + } + } + /// Build the final struct with custom extra_data. + pub fn build_with_data(self, extra_data: BTreeMap>) -> DeleteNotification { + DeleteNotification { + id: self._fields.0.unwrap(), + extra_data: Some(extra_data), + } + } +} diff --git a/crates/jacquard-api/src/org_tangled/temp/notification/get_preferences.rs b/crates/jacquard-api/src/org_tangled/temp/notification/get_preferences.rs new file mode 100644 index 000000000..43ab1b695 --- /dev/null +++ b/crates/jacquard-api/src/org_tangled/temp/notification/get_preferences.rs @@ -0,0 +1,717 @@ +// @generated by jacquard-lexicon. DO NOT EDIT. +// +// Lexicon: org.tangled.temp.notification.getPreferences +// +// 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, DefaultStr, FromStaticStr}; + +#[allow(unused_imports)] +use jacquard_common::deps::codegen::unicode_segmentation::UnicodeSegmentation; +use jacquard_common::deps::smol_str::SmolStr; +use jacquard_common::types::value::Data; +use jacquard_derive::IntoStatic; +use jacquard_lexicon::lexicon::LexiconDoc; +use jacquard_lexicon::schema::LexiconSchema; + +use crate::org_tangled::temp::notification::get_preferences; +#[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", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct GetPreferencesOutput { + #[serde(flatten)] + pub value: Data, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct Preferences { + pub email_notifications: bool, + pub followed: bool, + pub issue_closed: bool, + pub issue_commented: bool, + pub issue_created: bool, + pub pull_commented: bool, + pub pull_created: bool, + pub pull_merged: bool, + pub repo_starred: bool, + pub user_mentioned: bool, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +/** Request marker for the `org.tangled.temp.notification.getPreferences` query. + +This endpoint has no request parameters or input body; send this marker with `jacquard::Client`.*/ + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic, Copy)] +pub struct GetPreferences; +/** Response marker for the `org.tangled.temp.notification.getPreferences` query. + +Implements `jacquard_common::xrpc::XrpcResp`; successful bodies decode as `Self::Output`, which is `GetPreferencesOutput` for this endpoint.*/ +pub struct GetPreferencesResponse; +impl jacquard_common::xrpc::XrpcResp for GetPreferencesResponse { + const NSID: &'static str = "org.tangled.temp.notification.getPreferences"; + const ENCODING: &'static str = "application/json"; + type Output = GetPreferencesOutput; + type Err = jacquard_common::xrpc::GenericError; +} + +impl jacquard_common::xrpc::XrpcRequest for GetPreferences { + const NSID: &'static str = "org.tangled.temp.notification.getPreferences"; + const METHOD: jacquard_common::xrpc::XrpcMethod = jacquard_common::xrpc::XrpcMethod::Query; + type Response = GetPreferencesResponse; +} + +/** Endpoint marker for the `org.tangled.temp.notification.getPreferences` query. + +Path: `/xrpc/org.tangled.temp.notification.getPreferences`. The request payload type is `GetPreferences`; use this marker with lower-level `XrpcEndpoint` APIs when you need endpoint metadata.*/ +pub struct GetPreferencesRequest; +impl jacquard_common::xrpc::XrpcEndpoint for GetPreferencesRequest { + const PATH: &'static str = "/xrpc/org.tangled.temp.notification.getPreferences"; + const METHOD: jacquard_common::xrpc::XrpcMethod = jacquard_common::xrpc::XrpcMethod::Query; + type Request = GetPreferences; + type Response = GetPreferencesResponse; +} + +impl LexiconSchema for Preferences { + fn nsid() -> &'static str { + "org.tangled.temp.notification.getPreferences" + } + fn def_name() -> &'static str { + "preferences" + } + fn lexicon_doc() -> LexiconDoc<'static> { + lexicon_doc_org_tangled_temp_notification_getPreferences() + } + fn validate(&self) -> Result<(), ConstraintError> { + Ok(()) + } +} + +pub mod preferences_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 EmailNotifications; + type Followed; + type IssueClosed; + type IssueCommented; + type IssueCreated; + type PullCommented; + type PullCreated; + type PullMerged; + type RepoStarred; + type UserMentioned; + } + /// Empty state - all required fields are unset + pub struct Empty(()); + impl sealed::Sealed for Empty {} + impl State for Empty { + type EmailNotifications = Unset; + type Followed = Unset; + type IssueClosed = Unset; + type IssueCommented = Unset; + type IssueCreated = Unset; + type PullCommented = Unset; + type PullCreated = Unset; + type PullMerged = Unset; + type RepoStarred = Unset; + type UserMentioned = Unset; + } + ///State transition - sets the `email_notifications` field to Set + pub struct SetEmailNotifications(PhantomData St>); + impl sealed::Sealed for SetEmailNotifications {} + impl State for SetEmailNotifications { + type EmailNotifications = Set; + type Followed = St::Followed; + type IssueClosed = St::IssueClosed; + type IssueCommented = St::IssueCommented; + type IssueCreated = St::IssueCreated; + type PullCommented = St::PullCommented; + type PullCreated = St::PullCreated; + type PullMerged = St::PullMerged; + type RepoStarred = St::RepoStarred; + type UserMentioned = St::UserMentioned; + } + ///State transition - sets the `followed` field to Set + pub struct SetFollowed(PhantomData St>); + impl sealed::Sealed for SetFollowed {} + impl State for SetFollowed { + type EmailNotifications = St::EmailNotifications; + type Followed = Set; + type IssueClosed = St::IssueClosed; + type IssueCommented = St::IssueCommented; + type IssueCreated = St::IssueCreated; + type PullCommented = St::PullCommented; + type PullCreated = St::PullCreated; + type PullMerged = St::PullMerged; + type RepoStarred = St::RepoStarred; + type UserMentioned = St::UserMentioned; + } + ///State transition - sets the `issue_closed` field to Set + pub struct SetIssueClosed(PhantomData St>); + impl sealed::Sealed for SetIssueClosed {} + impl State for SetIssueClosed { + type EmailNotifications = St::EmailNotifications; + type Followed = St::Followed; + type IssueClosed = Set; + type IssueCommented = St::IssueCommented; + type IssueCreated = St::IssueCreated; + type PullCommented = St::PullCommented; + type PullCreated = St::PullCreated; + type PullMerged = St::PullMerged; + type RepoStarred = St::RepoStarred; + type UserMentioned = St::UserMentioned; + } + ///State transition - sets the `issue_commented` field to Set + pub struct SetIssueCommented(PhantomData St>); + impl sealed::Sealed for SetIssueCommented {} + impl State for SetIssueCommented { + type EmailNotifications = St::EmailNotifications; + type Followed = St::Followed; + type IssueClosed = St::IssueClosed; + type IssueCommented = Set; + type IssueCreated = St::IssueCreated; + type PullCommented = St::PullCommented; + type PullCreated = St::PullCreated; + type PullMerged = St::PullMerged; + type RepoStarred = St::RepoStarred; + type UserMentioned = St::UserMentioned; + } + ///State transition - sets the `issue_created` field to Set + pub struct SetIssueCreated(PhantomData St>); + impl sealed::Sealed for SetIssueCreated {} + impl State for SetIssueCreated { + type EmailNotifications = St::EmailNotifications; + type Followed = St::Followed; + type IssueClosed = St::IssueClosed; + type IssueCommented = St::IssueCommented; + type IssueCreated = Set; + type PullCommented = St::PullCommented; + type PullCreated = St::PullCreated; + type PullMerged = St::PullMerged; + type RepoStarred = St::RepoStarred; + type UserMentioned = St::UserMentioned; + } + ///State transition - sets the `pull_commented` field to Set + pub struct SetPullCommented(PhantomData St>); + impl sealed::Sealed for SetPullCommented {} + impl State for SetPullCommented { + type EmailNotifications = St::EmailNotifications; + type Followed = St::Followed; + type IssueClosed = St::IssueClosed; + type IssueCommented = St::IssueCommented; + type IssueCreated = St::IssueCreated; + type PullCommented = Set; + type PullCreated = St::PullCreated; + type PullMerged = St::PullMerged; + type RepoStarred = St::RepoStarred; + type UserMentioned = St::UserMentioned; + } + ///State transition - sets the `pull_created` field to Set + pub struct SetPullCreated(PhantomData St>); + impl sealed::Sealed for SetPullCreated {} + impl State for SetPullCreated { + type EmailNotifications = St::EmailNotifications; + type Followed = St::Followed; + type IssueClosed = St::IssueClosed; + type IssueCommented = St::IssueCommented; + type IssueCreated = St::IssueCreated; + type PullCommented = St::PullCommented; + type PullCreated = Set; + type PullMerged = St::PullMerged; + type RepoStarred = St::RepoStarred; + type UserMentioned = St::UserMentioned; + } + ///State transition - sets the `pull_merged` field to Set + pub struct SetPullMerged(PhantomData St>); + impl sealed::Sealed for SetPullMerged {} + impl State for SetPullMerged { + type EmailNotifications = St::EmailNotifications; + type Followed = St::Followed; + type IssueClosed = St::IssueClosed; + type IssueCommented = St::IssueCommented; + type IssueCreated = St::IssueCreated; + type PullCommented = St::PullCommented; + type PullCreated = St::PullCreated; + type PullMerged = Set; + type RepoStarred = St::RepoStarred; + type UserMentioned = St::UserMentioned; + } + ///State transition - sets the `repo_starred` field to Set + pub struct SetRepoStarred(PhantomData St>); + impl sealed::Sealed for SetRepoStarred {} + impl State for SetRepoStarred { + type EmailNotifications = St::EmailNotifications; + type Followed = St::Followed; + type IssueClosed = St::IssueClosed; + type IssueCommented = St::IssueCommented; + type IssueCreated = St::IssueCreated; + type PullCommented = St::PullCommented; + type PullCreated = St::PullCreated; + type PullMerged = St::PullMerged; + type RepoStarred = Set; + type UserMentioned = St::UserMentioned; + } + ///State transition - sets the `user_mentioned` field to Set + pub struct SetUserMentioned(PhantomData St>); + impl sealed::Sealed for SetUserMentioned {} + impl State for SetUserMentioned { + type EmailNotifications = St::EmailNotifications; + type Followed = St::Followed; + type IssueClosed = St::IssueClosed; + type IssueCommented = St::IssueCommented; + type IssueCreated = St::IssueCreated; + type PullCommented = St::PullCommented; + type PullCreated = St::PullCreated; + type PullMerged = St::PullMerged; + type RepoStarred = St::RepoStarred; + type UserMentioned = Set; + } + /// Marker types for field names + #[allow(non_camel_case_types)] + pub mod members { + ///Marker type for the `email_notifications` field + pub struct email_notifications(()); + ///Marker type for the `followed` field + pub struct followed(()); + ///Marker type for the `issue_closed` field + pub struct issue_closed(()); + ///Marker type for the `issue_commented` field + pub struct issue_commented(()); + ///Marker type for the `issue_created` field + pub struct issue_created(()); + ///Marker type for the `pull_commented` field + pub struct pull_commented(()); + ///Marker type for the `pull_created` field + pub struct pull_created(()); + ///Marker type for the `pull_merged` field + pub struct pull_merged(()); + ///Marker type for the `repo_starred` field + pub struct repo_starred(()); + ///Marker type for the `user_mentioned` field + pub struct user_mentioned(()); + } +} + +/// Builder for constructing an instance of this type. +pub struct PreferencesBuilder { + _state: PhantomData St>, + _fields: ( + Option, + Option, + Option, + Option, + Option, + Option, + Option, + Option, + Option, + Option, + ), + _type: PhantomData S>, +} + +impl Preferences { + /// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed + pub fn new() -> PreferencesBuilder { + PreferencesBuilder::new() + } +} + +impl Preferences { + /// Create a new builder for this type + pub fn builder() -> PreferencesBuilder { + PreferencesBuilder::builder() + } +} + +impl PreferencesBuilder { + /// Create a new builder with all fields unset, using the default string type, if needed + pub fn new() -> Self { + PreferencesBuilder { + _state: PhantomData, + _fields: (None, None, None, None, None, None, None, None, None, None), + _type: PhantomData, + } + } +} + +impl PreferencesBuilder { + /// Create a new builder with all fields unset + pub fn builder() -> Self { + PreferencesBuilder { + _state: PhantomData, + _fields: (None, None, None, None, None, None, None, None, None, None), + _type: PhantomData, + } + } +} + +impl PreferencesBuilder +where + St: preferences_state::State, + St::EmailNotifications: preferences_state::IsUnset, +{ + /// Set the `emailNotifications` field (required) + pub fn email_notifications( + mut self, + value: impl Into, + ) -> PreferencesBuilder, S> { + self._fields.0 = Option::Some(value.into()); + PreferencesBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl PreferencesBuilder +where + St: preferences_state::State, + St::Followed: preferences_state::IsUnset, +{ + /// Set the `followed` field (required) + pub fn followed( + mut self, + value: impl Into, + ) -> PreferencesBuilder, S> { + self._fields.1 = Option::Some(value.into()); + PreferencesBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl PreferencesBuilder +where + St: preferences_state::State, + St::IssueClosed: preferences_state::IsUnset, +{ + /// Set the `issueClosed` field (required) + pub fn issue_closed( + mut self, + value: impl Into, + ) -> PreferencesBuilder, S> { + self._fields.2 = Option::Some(value.into()); + PreferencesBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl PreferencesBuilder +where + St: preferences_state::State, + St::IssueCommented: preferences_state::IsUnset, +{ + /// Set the `issueCommented` field (required) + pub fn issue_commented( + mut self, + value: impl Into, + ) -> PreferencesBuilder, S> { + self._fields.3 = Option::Some(value.into()); + PreferencesBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl PreferencesBuilder +where + St: preferences_state::State, + St::IssueCreated: preferences_state::IsUnset, +{ + /// Set the `issueCreated` field (required) + pub fn issue_created( + mut self, + value: impl Into, + ) -> PreferencesBuilder, S> { + self._fields.4 = Option::Some(value.into()); + PreferencesBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl PreferencesBuilder +where + St: preferences_state::State, + St::PullCommented: preferences_state::IsUnset, +{ + /// Set the `pullCommented` field (required) + pub fn pull_commented( + mut self, + value: impl Into, + ) -> PreferencesBuilder, S> { + self._fields.5 = Option::Some(value.into()); + PreferencesBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl PreferencesBuilder +where + St: preferences_state::State, + St::PullCreated: preferences_state::IsUnset, +{ + /// Set the `pullCreated` field (required) + pub fn pull_created( + mut self, + value: impl Into, + ) -> PreferencesBuilder, S> { + self._fields.6 = Option::Some(value.into()); + PreferencesBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl PreferencesBuilder +where + St: preferences_state::State, + St::PullMerged: preferences_state::IsUnset, +{ + /// Set the `pullMerged` field (required) + pub fn pull_merged( + mut self, + value: impl Into, + ) -> PreferencesBuilder, S> { + self._fields.7 = Option::Some(value.into()); + PreferencesBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl PreferencesBuilder +where + St: preferences_state::State, + St::RepoStarred: preferences_state::IsUnset, +{ + /// Set the `repoStarred` field (required) + pub fn repo_starred( + mut self, + value: impl Into, + ) -> PreferencesBuilder, S> { + self._fields.8 = Option::Some(value.into()); + PreferencesBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl PreferencesBuilder +where + St: preferences_state::State, + St::UserMentioned: preferences_state::IsUnset, +{ + /// Set the `userMentioned` field (required) + pub fn user_mentioned( + mut self, + value: impl Into, + ) -> PreferencesBuilder, S> { + self._fields.9 = Option::Some(value.into()); + PreferencesBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl PreferencesBuilder +where + St: preferences_state::State, + St::EmailNotifications: preferences_state::IsSet, + St::Followed: preferences_state::IsSet, + St::IssueClosed: preferences_state::IsSet, + St::IssueCommented: preferences_state::IsSet, + St::IssueCreated: preferences_state::IsSet, + St::PullCommented: preferences_state::IsSet, + St::PullCreated: preferences_state::IsSet, + St::PullMerged: preferences_state::IsSet, + St::RepoStarred: preferences_state::IsSet, + St::UserMentioned: preferences_state::IsSet, +{ + /// Build the final struct. + pub fn build(self) -> Preferences { + Preferences { + email_notifications: self._fields.0.unwrap(), + followed: self._fields.1.unwrap(), + issue_closed: self._fields.2.unwrap(), + issue_commented: self._fields.3.unwrap(), + issue_created: self._fields.4.unwrap(), + pull_commented: self._fields.5.unwrap(), + pull_created: self._fields.6.unwrap(), + pull_merged: self._fields.7.unwrap(), + repo_starred: self._fields.8.unwrap(), + user_mentioned: self._fields.9.unwrap(), + extra_data: Default::default(), + } + } + /// Build the final struct with custom extra_data. + pub fn build_with_data(self, extra_data: BTreeMap>) -> Preferences { + Preferences { + email_notifications: self._fields.0.unwrap(), + followed: self._fields.1.unwrap(), + issue_closed: self._fields.2.unwrap(), + issue_commented: self._fields.3.unwrap(), + issue_created: self._fields.4.unwrap(), + pull_commented: self._fields.5.unwrap(), + pull_created: self._fields.6.unwrap(), + pull_merged: self._fields.7.unwrap(), + repo_starred: self._fields.8.unwrap(), + user_mentioned: self._fields.9.unwrap(), + extra_data: Some(extra_data), + } + } +} + +fn lexicon_doc_org_tangled_temp_notification_getPreferences() -> 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("org.tangled.temp.notification.getPreferences"), + defs: { + let mut map = BTreeMap::new(); + map.insert( + SmolStr::new_static("main"), + LexUserType::XrpcQuery(LexXrpcQuery { + parameters: None, + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("preferences"), + LexUserType::Object(LexObject { + required: Some(vec![ + SmolStr::new_static("repoStarred"), + SmolStr::new_static("issueCreated"), + SmolStr::new_static("issueCommented"), + SmolStr::new_static("issueClosed"), + SmolStr::new_static("pullCreated"), + SmolStr::new_static("pullCommented"), + SmolStr::new_static("pullMerged"), + SmolStr::new_static("followed"), + SmolStr::new_static("userMentioned"), + SmolStr::new_static("emailNotifications"), + ]), + properties: { + #[allow(unused_mut)] + let mut map = BTreeMap::new(); + map.insert( + SmolStr::new_static("emailNotifications"), + LexObjectProperty::Boolean(LexBoolean { + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("followed"), + LexObjectProperty::Boolean(LexBoolean { + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("issueClosed"), + LexObjectProperty::Boolean(LexBoolean { + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("issueCommented"), + LexObjectProperty::Boolean(LexBoolean { + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("issueCreated"), + LexObjectProperty::Boolean(LexBoolean { + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("pullCommented"), + LexObjectProperty::Boolean(LexBoolean { + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("pullCreated"), + LexObjectProperty::Boolean(LexBoolean { + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("pullMerged"), + LexObjectProperty::Boolean(LexBoolean { + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("repoStarred"), + LexObjectProperty::Boolean(LexBoolean { + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("userMentioned"), + LexObjectProperty::Boolean(LexBoolean { + ..Default::default() + }), + ); + map + }, + ..Default::default() + }), + ); + map + }, + ..Default::default() + } +} diff --git a/crates/jacquard-api/src/org_tangled/temp/notification/get_unread_count.rs b/crates/jacquard-api/src/org_tangled/temp/notification/get_unread_count.rs new file mode 100644 index 000000000..daab91cc2 --- /dev/null +++ b/crates/jacquard-api/src/org_tangled/temp/notification/get_unread_count.rs @@ -0,0 +1,62 @@ +// @generated by jacquard-lexicon. DO NOT EDIT. +// +// Lexicon: org.tangled.temp.notification.getUnreadCount +// +// 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::deps::smol_str::SmolStr; +use jacquard_common::types::value::Data; +use jacquard_common::{BosStr, DefaultStr, FromStaticStr}; +use jacquard_derive::IntoStatic; +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct GetUnreadCountOutput { + pub count: i64, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +/** Request marker for the `org.tangled.temp.notification.getUnreadCount` query. + +This endpoint has no request parameters or input body; send this marker with `jacquard::Client`.*/ + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic, Copy)] +pub struct GetUnreadCount; +/** Response marker for the `org.tangled.temp.notification.getUnreadCount` query. + +Implements `jacquard_common::xrpc::XrpcResp`; successful bodies decode as `Self::Output`, which is `GetUnreadCountOutput` for this endpoint.*/ +pub struct GetUnreadCountResponse; +impl jacquard_common::xrpc::XrpcResp for GetUnreadCountResponse { + const NSID: &'static str = "org.tangled.temp.notification.getUnreadCount"; + const ENCODING: &'static str = "application/json"; + type Output = GetUnreadCountOutput; + type Err = jacquard_common::xrpc::GenericError; +} + +impl jacquard_common::xrpc::XrpcRequest for GetUnreadCount { + const NSID: &'static str = "org.tangled.temp.notification.getUnreadCount"; + const METHOD: jacquard_common::xrpc::XrpcMethod = jacquard_common::xrpc::XrpcMethod::Query; + type Response = GetUnreadCountResponse; +} + +/** Endpoint marker for the `org.tangled.temp.notification.getUnreadCount` query. + +Path: `/xrpc/org.tangled.temp.notification.getUnreadCount`. The request payload type is `GetUnreadCount`; use this marker with lower-level `XrpcEndpoint` APIs when you need endpoint metadata.*/ +pub struct GetUnreadCountRequest; +impl jacquard_common::xrpc::XrpcEndpoint for GetUnreadCountRequest { + const PATH: &'static str = "/xrpc/org.tangled.temp.notification.getUnreadCount"; + const METHOD: jacquard_common::xrpc::XrpcMethod = jacquard_common::xrpc::XrpcMethod::Query; + type Request = GetUnreadCount; + type Response = GetUnreadCountResponse; +} diff --git a/crates/jacquard-api/src/org_tangled/temp/notification/list_notifications.rs b/crates/jacquard-api/src/org_tangled/temp/notification/list_notifications.rs new file mode 100644 index 000000000..d77dfa81b --- /dev/null +++ b/crates/jacquard-api/src/org_tangled/temp/notification/list_notifications.rs @@ -0,0 +1,786 @@ +// @generated by jacquard-lexicon. DO NOT EDIT. +// +// Lexicon: org.tangled.temp.notification.listNotifications +// +// 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::string::{AtUri, Datetime, Did}; +use jacquard_common::types::value::Data; +use jacquard_derive::IntoStatic; +use jacquard_lexicon::lexicon::LexiconDoc; +use jacquard_lexicon::schema::LexiconSchema; + +use crate::org_tangled::temp::notification::list_notifications; +#[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", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct ListNotifications { + #[serde(skip_serializing_if = "Option::is_none")] + pub category: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub cursor: Option, + /// (min: 1, max: 100) + #[serde(skip_serializing_if = "Option::is_none")] + pub limit: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub read: Option, +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct ListNotificationsOutput { + #[serde(skip_serializing_if = "Option::is_none")] + pub cursor: Option, + pub notifications: Vec>, + pub social_unread_count: i64, + pub work_unread_count: i64, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct Notification { + ///DID of the user who triggered this notification. + pub actor_did: Did, + ///Broad category: 'social' or 'work'. + pub category: S, + pub created_at: Datetime, + ///Stable numeric ID for this notification. + pub id: i64, + ///AT-URI of the related org.tangled.issue.issue record, if applicable. + #[serde(skip_serializing_if = "Option::is_none")] + pub issue_at: Option>, + ///AT-URI of the related org.tangled.pulls.pull record, if applicable. + #[serde(skip_serializing_if = "Option::is_none")] + pub pull_at: Option>, + pub read: bool, + ///DID of the related repository, if applicable. + #[serde(skip_serializing_if = "Option::is_none")] + pub repo_did: Option>, + ///Notification type: repo_starred, issue_created, issue_commented, issue_closed, issue_reopen, issue_assigned, issue_unassigned, pull_created, pull_commented, pull_merged, pull_closed, pull_reopen, pull_assigned, pull_unassigned, followed, user_mentioned. + pub r#type: S, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +/** Response marker for the `org.tangled.temp.notification.listNotifications` query. + +Implements `jacquard_common::xrpc::XrpcResp`; successful bodies decode as `Self::Output`, which is `ListNotificationsOutput` for this endpoint.*/ +pub struct ListNotificationsResponse; +impl jacquard_common::xrpc::XrpcResp for ListNotificationsResponse { + const NSID: &'static str = "org.tangled.temp.notification.listNotifications"; + const ENCODING: &'static str = "application/json"; + type Output = ListNotificationsOutput; + type Err = jacquard_common::xrpc::GenericError; +} + +impl jacquard_common::xrpc::XrpcRequest for ListNotifications { + const NSID: &'static str = "org.tangled.temp.notification.listNotifications"; + const METHOD: jacquard_common::xrpc::XrpcMethod = jacquard_common::xrpc::XrpcMethod::Query; + type Response = ListNotificationsResponse; +} + +/** Endpoint marker for the `org.tangled.temp.notification.listNotifications` query. + +Path: `/xrpc/org.tangled.temp.notification.listNotifications`. The request payload type is `ListNotifications`; send that request with `jacquard::Client` or use this marker through lower-level `XrpcEndpoint` APIs.*/ +pub struct ListNotificationsRequest; +impl jacquard_common::xrpc::XrpcEndpoint for ListNotificationsRequest { + const PATH: &'static str = "/xrpc/org.tangled.temp.notification.listNotifications"; + const METHOD: jacquard_common::xrpc::XrpcMethod = jacquard_common::xrpc::XrpcMethod::Query; + type Request = ListNotifications; + type Response = ListNotificationsResponse; +} + +impl LexiconSchema for Notification { + fn nsid() -> &'static str { + "org.tangled.temp.notification.listNotifications" + } + fn def_name() -> &'static str { + "notification" + } + fn lexicon_doc() -> LexiconDoc<'static> { + lexicon_doc_org_tangled_temp_notification_listNotifications() + } + fn validate(&self) -> Result<(), ConstraintError> { + Ok(()) + } +} + +pub mod list_notifications_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 {} + /// Empty state - all required fields are unset + pub struct Empty(()); + impl sealed::Sealed for Empty {} + impl State for Empty {} + /// Marker types for field names + #[allow(non_camel_case_types)] + pub mod members {} +} + +/// Builder for constructing an instance of this type. +pub struct ListNotificationsBuilder { + _state: PhantomData St>, + _fields: (Option, Option, Option, Option), + _type: PhantomData S>, +} + +impl ListNotifications { + /// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed + pub fn new() -> ListNotificationsBuilder { + ListNotificationsBuilder::new() + } +} + +impl ListNotifications { + /// Create a new builder for this type + pub fn builder() -> ListNotificationsBuilder { + ListNotificationsBuilder::builder() + } +} + +impl ListNotificationsBuilder { + /// Create a new builder with all fields unset, using the default string type, if needed + pub fn new() -> Self { + ListNotificationsBuilder { + _state: PhantomData, + _fields: (None, None, None, None), + _type: PhantomData, + } + } +} + +impl ListNotificationsBuilder { + /// Create a new builder with all fields unset + pub fn builder() -> Self { + ListNotificationsBuilder { + _state: PhantomData, + _fields: (None, None, None, None), + _type: PhantomData, + } + } +} + +impl ListNotificationsBuilder { + /// Set the `category` field (optional) + pub fn category(mut self, value: impl Into>) -> Self { + self._fields.0 = value.into(); + self + } + /// Set the `category` field to an Option value (optional) + pub fn maybe_category(mut self, value: Option) -> Self { + self._fields.0 = value; + self + } +} + +impl ListNotificationsBuilder { + /// Set the `cursor` field (optional) + pub fn cursor(mut self, value: impl Into>) -> Self { + self._fields.1 = value.into(); + self + } + /// Set the `cursor` field to an Option value (optional) + pub fn maybe_cursor(mut self, value: Option) -> Self { + self._fields.1 = value; + self + } +} + +impl ListNotificationsBuilder { + /// Set the `limit` field (optional) + pub fn limit(mut self, value: impl Into>) -> Self { + self._fields.2 = value.into(); + self + } + /// Set the `limit` field to an Option value (optional) + pub fn maybe_limit(mut self, value: Option) -> Self { + self._fields.2 = value; + self + } +} + +impl ListNotificationsBuilder { + /// Set the `read` field (optional) + pub fn read(mut self, value: impl Into>) -> Self { + self._fields.3 = value.into(); + self + } + /// Set the `read` field to an Option value (optional) + pub fn maybe_read(mut self, value: Option) -> Self { + self._fields.3 = value; + self + } +} + +impl ListNotificationsBuilder +where + St: list_notifications_state::State, +{ + /// Build the final struct. + pub fn build(self) -> ListNotifications { + ListNotifications { + category: self._fields.0, + cursor: self._fields.1, + limit: self._fields.2, + read: self._fields.3, + } + } +} + +pub mod notification_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 ActorDid; + type Category; + type CreatedAt; + type Id; + type Read; + type Type; + } + /// Empty state - all required fields are unset + pub struct Empty(()); + impl sealed::Sealed for Empty {} + impl State for Empty { + type ActorDid = Unset; + type Category = Unset; + type CreatedAt = Unset; + type Id = Unset; + type Read = Unset; + type Type = Unset; + } + ///State transition - sets the `actor_did` field to Set + pub struct SetActorDid(PhantomData St>); + impl sealed::Sealed for SetActorDid {} + impl State for SetActorDid { + type ActorDid = Set; + type Category = St::Category; + type CreatedAt = St::CreatedAt; + type Id = St::Id; + type Read = St::Read; + type Type = St::Type; + } + ///State transition - sets the `category` field to Set + pub struct SetCategory(PhantomData St>); + impl sealed::Sealed for SetCategory {} + impl State for SetCategory { + type ActorDid = St::ActorDid; + type Category = Set; + type CreatedAt = St::CreatedAt; + type Id = St::Id; + type Read = St::Read; + type Type = St::Type; + } + ///State transition - sets the `created_at` field to Set + pub struct SetCreatedAt(PhantomData St>); + impl sealed::Sealed for SetCreatedAt {} + impl State for SetCreatedAt { + type ActorDid = St::ActorDid; + type Category = St::Category; + type CreatedAt = Set; + type Id = St::Id; + type Read = St::Read; + type Type = St::Type; + } + ///State transition - sets the `id` field to Set + pub struct SetId(PhantomData St>); + impl sealed::Sealed for SetId {} + impl State for SetId { + type ActorDid = St::ActorDid; + type Category = St::Category; + type CreatedAt = St::CreatedAt; + type Id = Set; + type Read = St::Read; + type Type = St::Type; + } + ///State transition - sets the `read` field to Set + pub struct SetRead(PhantomData St>); + impl sealed::Sealed for SetRead {} + impl State for SetRead { + type ActorDid = St::ActorDid; + type Category = St::Category; + type CreatedAt = St::CreatedAt; + type Id = St::Id; + type Read = Set; + type Type = St::Type; + } + ///State transition - sets the `type` field to Set + pub struct SetType(PhantomData St>); + impl sealed::Sealed for SetType {} + impl State for SetType { + type ActorDid = St::ActorDid; + type Category = St::Category; + type CreatedAt = St::CreatedAt; + type Id = St::Id; + type Read = St::Read; + type Type = Set; + } + /// Marker types for field names + #[allow(non_camel_case_types)] + pub mod members { + ///Marker type for the `actor_did` field + pub struct actor_did(()); + ///Marker type for the `category` field + pub struct category(()); + ///Marker type for the `created_at` field + pub struct created_at(()); + ///Marker type for the `id` field + pub struct id(()); + ///Marker type for the `read` field + pub struct read(()); + ///Marker type for the `type` field + pub struct r#type(()); + } +} + +/// Builder for constructing an instance of this type. +pub struct NotificationBuilder { + _state: PhantomData St>, + _fields: ( + Option>, + Option, + Option, + Option, + Option>, + Option>, + Option, + Option>, + Option, + ), + _type: PhantomData S>, +} + +impl Notification { + /// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed + pub fn new() -> NotificationBuilder { + NotificationBuilder::new() + } +} + +impl Notification { + /// Create a new builder for this type + pub fn builder() -> NotificationBuilder { + NotificationBuilder::builder() + } +} + +impl NotificationBuilder { + /// Create a new builder with all fields unset, using the default string type, if needed + pub fn new() -> Self { + NotificationBuilder { + _state: PhantomData, + _fields: (None, None, None, None, None, None, None, None, None), + _type: PhantomData, + } + } +} + +impl NotificationBuilder { + /// Create a new builder with all fields unset + pub fn builder() -> Self { + NotificationBuilder { + _state: PhantomData, + _fields: (None, None, None, None, None, None, None, None, None), + _type: PhantomData, + } + } +} + +impl NotificationBuilder +where + St: notification_state::State, + St::ActorDid: notification_state::IsUnset, +{ + /// Set the `actorDid` field (required) + pub fn actor_did( + mut self, + value: impl Into>, + ) -> NotificationBuilder, S> { + self._fields.0 = Option::Some(value.into()); + NotificationBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl NotificationBuilder +where + St: notification_state::State, + St::Category: notification_state::IsUnset, +{ + /// Set the `category` field (required) + pub fn category( + mut self, + value: impl Into, + ) -> NotificationBuilder, S> { + self._fields.1 = Option::Some(value.into()); + NotificationBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl NotificationBuilder +where + St: notification_state::State, + St::CreatedAt: notification_state::IsUnset, +{ + /// Set the `createdAt` field (required) + pub fn created_at( + mut self, + value: impl Into, + ) -> NotificationBuilder, S> { + self._fields.2 = Option::Some(value.into()); + NotificationBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl NotificationBuilder +where + St: notification_state::State, + St::Id: notification_state::IsUnset, +{ + /// Set the `id` field (required) + pub fn id( + mut self, + value: impl Into, + ) -> NotificationBuilder, S> { + self._fields.3 = Option::Some(value.into()); + NotificationBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl NotificationBuilder { + /// Set the `issueAt` field (optional) + pub fn issue_at(mut self, value: impl Into>>) -> Self { + self._fields.4 = value.into(); + self + } + /// Set the `issueAt` field to an Option value (optional) + pub fn maybe_issue_at(mut self, value: Option>) -> Self { + self._fields.4 = value; + self + } +} + +impl NotificationBuilder { + /// Set the `pullAt` field (optional) + pub fn pull_at(mut self, value: impl Into>>) -> Self { + self._fields.5 = value.into(); + self + } + /// Set the `pullAt` field to an Option value (optional) + pub fn maybe_pull_at(mut self, value: Option>) -> Self { + self._fields.5 = value; + self + } +} + +impl NotificationBuilder +where + St: notification_state::State, + St::Read: notification_state::IsUnset, +{ + /// Set the `read` field (required) + pub fn read( + mut self, + value: impl Into, + ) -> NotificationBuilder, S> { + self._fields.6 = Option::Some(value.into()); + NotificationBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl NotificationBuilder { + /// Set the `repoDid` field (optional) + pub fn repo_did(mut self, value: impl Into>>) -> Self { + self._fields.7 = value.into(); + self + } + /// Set the `repoDid` field to an Option value (optional) + pub fn maybe_repo_did(mut self, value: Option>) -> Self { + self._fields.7 = value; + self + } +} + +impl NotificationBuilder +where + St: notification_state::State, + St::Type: notification_state::IsUnset, +{ + /// Set the `type` field (required) + pub fn r#type( + mut self, + value: impl Into, + ) -> NotificationBuilder, S> { + self._fields.8 = Option::Some(value.into()); + NotificationBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl NotificationBuilder +where + St: notification_state::State, + St::ActorDid: notification_state::IsSet, + St::Category: notification_state::IsSet, + St::CreatedAt: notification_state::IsSet, + St::Id: notification_state::IsSet, + St::Read: notification_state::IsSet, + St::Type: notification_state::IsSet, +{ + /// Build the final struct. + pub fn build(self) -> Notification { + Notification { + actor_did: self._fields.0.unwrap(), + category: self._fields.1.unwrap(), + created_at: self._fields.2.unwrap(), + id: self._fields.3.unwrap(), + issue_at: self._fields.4, + pull_at: self._fields.5, + read: self._fields.6.unwrap(), + repo_did: self._fields.7, + r#type: self._fields.8.unwrap(), + extra_data: Default::default(), + } + } + /// Build the final struct with custom extra_data. + pub fn build_with_data(self, extra_data: BTreeMap>) -> Notification { + Notification { + actor_did: self._fields.0.unwrap(), + category: self._fields.1.unwrap(), + created_at: self._fields.2.unwrap(), + id: self._fields.3.unwrap(), + issue_at: self._fields.4, + pull_at: self._fields.5, + read: self._fields.6.unwrap(), + repo_did: self._fields.7, + r#type: self._fields.8.unwrap(), + extra_data: Some(extra_data), + } + } +} + +fn lexicon_doc_org_tangled_temp_notification_listNotifications() -> 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("org.tangled.temp.notification.listNotifications"), + defs: { + let mut map = BTreeMap::new(); + map.insert( + SmolStr::new_static("main"), + LexUserType::XrpcQuery(LexXrpcQuery { + parameters: Some(LexXrpcQueryParameter::Params(LexXrpcParameters { + properties: { + #[allow(unused_mut)] + let mut map = BTreeMap::new(); + map.insert( + SmolStr::new_static("category"), + LexXrpcParametersProperty::String(LexString { + description: Some(CowStr::new_static( + "Filter by category: 'all', 'social', or 'work'.", + )), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("cursor"), + LexXrpcParametersProperty::String(LexString { + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("limit"), + LexXrpcParametersProperty::Integer(LexInteger { + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("read"), + LexXrpcParametersProperty::String(LexString { + description: Some(CowStr::new_static( + "Filter by read state: 'all' or 'unread'.", + )), + ..Default::default() + }), + ); + map + }, + ..Default::default() + })), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("notification"), + LexUserType::Object(LexObject { + required: Some( + vec![ + SmolStr::new_static("id"), SmolStr::new_static("type"), + SmolStr::new_static("category"), + SmolStr::new_static("actorDid"), SmolStr::new_static("read"), + SmolStr::new_static("createdAt") + ], + ), + properties: { + #[allow(unused_mut)] + let mut map = BTreeMap::new(); + map.insert( + SmolStr::new_static("actorDid"), + LexObjectProperty::String(LexString { + description: Some( + CowStr::new_static( + "DID of the user who triggered this notification.", + ), + ), + format: Some(LexStringFormat::Did), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("category"), + LexObjectProperty::String(LexString { + description: Some( + CowStr::new_static("Broad category: 'social' or 'work'."), + ), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("createdAt"), + LexObjectProperty::String(LexString { + format: Some(LexStringFormat::Datetime), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("id"), + LexObjectProperty::Integer(LexInteger { + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("issueAt"), + LexObjectProperty::String(LexString { + description: Some( + CowStr::new_static( + "AT-URI of the related org.tangled.issue.issue record, if applicable.", + ), + ), + format: Some(LexStringFormat::AtUri), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("pullAt"), + LexObjectProperty::String(LexString { + description: Some( + CowStr::new_static( + "AT-URI of the related org.tangled.pulls.pull record, if applicable.", + ), + ), + format: Some(LexStringFormat::AtUri), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("read"), + LexObjectProperty::Boolean(LexBoolean { + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("repoDid"), + LexObjectProperty::String(LexString { + description: Some( + CowStr::new_static( + "DID of the related repository, if applicable.", + ), + ), + format: Some(LexStringFormat::Did), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("type"), + LexObjectProperty::String(LexString { + description: Some( + CowStr::new_static( + "Notification type: repo_starred, issue_created, issue_commented, issue_closed, issue_reopen, issue_assigned, issue_unassigned, pull_created, pull_commented, pull_merged, pull_closed, pull_reopen, pull_assigned, pull_unassigned, followed, user_mentioned.", + ), + ), + ..Default::default() + }), + ); + map + }, + ..Default::default() + }), + ); + map + }, + ..Default::default() + } +} diff --git a/crates/jacquard-api/src/org_tangled/temp/notification/mark_all_read.rs b/crates/jacquard-api/src/org_tangled/temp/notification/mark_all_read.rs new file mode 100644 index 000000000..07202a179 --- /dev/null +++ b/crates/jacquard-api/src/org_tangled/temp/notification/mark_all_read.rs @@ -0,0 +1,52 @@ +// @generated by jacquard-lexicon. DO NOT EDIT. +// +// Lexicon: org.tangled.temp.notification.markAllRead +// +// 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::deps::smol_str::SmolStr; +use jacquard_common::types::value::Data; +use jacquard_common::{BosStr, DefaultStr, FromStaticStr}; +use jacquard_derive::IntoStatic; +use serde::{Deserialize, Serialize}; +/** Request marker for the `org.tangled.temp.notification.markAllRead` procedure. + +This endpoint has no request parameters or input body; send this marker with `jacquard::Client`.*/ + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic, Copy)] +pub struct MarkAllRead; +/** Response marker for the `org.tangled.temp.notification.markAllRead` procedure. + +Implements `jacquard_common::xrpc::XrpcResp`; successful bodies decode as `Self::Output`, which is `()` for this endpoint.*/ +pub struct MarkAllReadResponse; +impl jacquard_common::xrpc::XrpcResp for MarkAllReadResponse { + const NSID: &'static str = "org.tangled.temp.notification.markAllRead"; + const ENCODING: &'static str = "application/json"; + type Output = (); + type Err = jacquard_common::xrpc::GenericError; +} + +impl jacquard_common::xrpc::XrpcRequest for MarkAllRead { + const NSID: &'static str = "org.tangled.temp.notification.markAllRead"; + const METHOD: jacquard_common::xrpc::XrpcMethod = + jacquard_common::xrpc::XrpcMethod::Procedure("application/json"); + type Response = MarkAllReadResponse; +} + +/** Endpoint marker for the `org.tangled.temp.notification.markAllRead` procedure. + +Path: `/xrpc/org.tangled.temp.notification.markAllRead`. The request payload type is `MarkAllRead`; use this marker with lower-level `XrpcEndpoint` APIs when you need endpoint metadata.*/ +pub struct MarkAllReadRequest; +impl jacquard_common::xrpc::XrpcEndpoint for MarkAllReadRequest { + const PATH: &'static str = "/xrpc/org.tangled.temp.notification.markAllRead"; + const METHOD: jacquard_common::xrpc::XrpcMethod = + jacquard_common::xrpc::XrpcMethod::Procedure("application/json"); + type Request = MarkAllRead; + type Response = MarkAllReadResponse; +} diff --git a/crates/jacquard-api/src/org_tangled/temp/notification/update_preferences.rs b/crates/jacquard-api/src/org_tangled/temp/notification/update_preferences.rs new file mode 100644 index 000000000..00c9506d6 --- /dev/null +++ b/crates/jacquard-api/src/org_tangled/temp/notification/update_preferences.rs @@ -0,0 +1,77 @@ +// @generated by jacquard-lexicon. DO NOT EDIT. +// +// Lexicon: org.tangled.temp.notification.updatePreferences +// +// 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::deps::smol_str::SmolStr; +use jacquard_common::types::value::Data; +use jacquard_common::{BosStr, DefaultStr, FromStaticStr}; +use jacquard_derive::IntoStatic; +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic, Default)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct UpdatePreferences { + #[serde(skip_serializing_if = "Option::is_none")] + pub email_notifications: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub followed: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub issue_closed: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub issue_commented: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub issue_created: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub pull_commented: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub pull_created: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub pull_merged: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub repo_starred: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub user_mentioned: Option, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +/** Response marker for the `org.tangled.temp.notification.updatePreferences` procedure. + +Implements `jacquard_common::xrpc::XrpcResp`; successful bodies decode as `Self::Output`, which is `()` for this endpoint.*/ +pub struct UpdatePreferencesResponse; +impl jacquard_common::xrpc::XrpcResp for UpdatePreferencesResponse { + const NSID: &'static str = "org.tangled.temp.notification.updatePreferences"; + const ENCODING: &'static str = "application/json"; + type Output = (); + type Err = jacquard_common::xrpc::GenericError; +} + +impl jacquard_common::xrpc::XrpcRequest for UpdatePreferences { + const NSID: &'static str = "org.tangled.temp.notification.updatePreferences"; + const METHOD: jacquard_common::xrpc::XrpcMethod = + jacquard_common::xrpc::XrpcMethod::Procedure("application/json"); + type Response = UpdatePreferencesResponse; +} + +/** Endpoint marker for the `org.tangled.temp.notification.updatePreferences` procedure. + +Path: `/xrpc/org.tangled.temp.notification.updatePreferences`. The request payload type is `UpdatePreferences`; send that request with `jacquard::Client` or use this marker through lower-level `XrpcEndpoint` APIs.*/ +pub struct UpdatePreferencesRequest; +impl jacquard_common::xrpc::XrpcEndpoint for UpdatePreferencesRequest { + const PATH: &'static str = "/xrpc/org.tangled.temp.notification.updatePreferences"; + const METHOD: jacquard_common::xrpc::XrpcMethod = + jacquard_common::xrpc::XrpcMethod::Procedure("application/json"); + type Request = UpdatePreferences; + type Response = UpdatePreferencesResponse; +} diff --git a/crates/jacquard-api/src/org_tangled/temp/notification/update_seen.rs b/crates/jacquard-api/src/org_tangled/temp/notification/update_seen.rs new file mode 100644 index 000000000..7c6208987 --- /dev/null +++ b/crates/jacquard-api/src/org_tangled/temp/notification/update_seen.rs @@ -0,0 +1,209 @@ +// @generated by jacquard-lexicon. DO NOT EDIT. +// +// Lexicon: org.tangled.temp.notification.updateSeen +// +// 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::deps::smol_str::SmolStr; +use jacquard_common::types::value::Data; +use jacquard_common::{BosStr, DefaultStr, FromStaticStr}; +use jacquard_derive::IntoStatic; +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct UpdateSeen { + ///ID of the notification to update. + pub id: i64, + pub read: bool, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +/** Response marker for the `org.tangled.temp.notification.updateSeen` procedure. + +Implements `jacquard_common::xrpc::XrpcResp`; successful bodies decode as `Self::Output`, which is `()` for this endpoint.*/ +pub struct UpdateSeenResponse; +impl jacquard_common::xrpc::XrpcResp for UpdateSeenResponse { + const NSID: &'static str = "org.tangled.temp.notification.updateSeen"; + const ENCODING: &'static str = "application/json"; + type Output = (); + type Err = jacquard_common::xrpc::GenericError; +} + +impl jacquard_common::xrpc::XrpcRequest for UpdateSeen { + const NSID: &'static str = "org.tangled.temp.notification.updateSeen"; + const METHOD: jacquard_common::xrpc::XrpcMethod = + jacquard_common::xrpc::XrpcMethod::Procedure("application/json"); + type Response = UpdateSeenResponse; +} + +/** Endpoint marker for the `org.tangled.temp.notification.updateSeen` procedure. + +Path: `/xrpc/org.tangled.temp.notification.updateSeen`. The request payload type is `UpdateSeen`; send that request with `jacquard::Client` or use this marker through lower-level `XrpcEndpoint` APIs.*/ +pub struct UpdateSeenRequest; +impl jacquard_common::xrpc::XrpcEndpoint for UpdateSeenRequest { + const PATH: &'static str = "/xrpc/org.tangled.temp.notification.updateSeen"; + const METHOD: jacquard_common::xrpc::XrpcMethod = + jacquard_common::xrpc::XrpcMethod::Procedure("application/json"); + type Request = UpdateSeen; + type Response = UpdateSeenResponse; +} + +pub mod update_seen_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 Id; + type Read; + } + /// Empty state - all required fields are unset + pub struct Empty(()); + impl sealed::Sealed for Empty {} + impl State for Empty { + type Id = Unset; + type Read = Unset; + } + ///State transition - sets the `id` field to Set + pub struct SetId(PhantomData St>); + impl sealed::Sealed for SetId {} + impl State for SetId { + type Id = Set; + type Read = St::Read; + } + ///State transition - sets the `read` field to Set + pub struct SetRead(PhantomData St>); + impl sealed::Sealed for SetRead {} + impl State for SetRead { + type Id = St::Id; + type Read = Set; + } + /// Marker types for field names + #[allow(non_camel_case_types)] + pub mod members { + ///Marker type for the `id` field + pub struct id(()); + ///Marker type for the `read` field + pub struct read(()); + } +} + +/// Builder for constructing an instance of this type. +pub struct UpdateSeenBuilder { + _state: PhantomData St>, + _fields: (Option, Option), + _type: PhantomData S>, +} + +impl UpdateSeen { + /// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed + pub fn new() -> UpdateSeenBuilder { + UpdateSeenBuilder::new() + } +} + +impl UpdateSeen { + /// Create a new builder for this type + pub fn builder() -> UpdateSeenBuilder { + UpdateSeenBuilder::builder() + } +} + +impl UpdateSeenBuilder { + /// Create a new builder with all fields unset, using the default string type, if needed + pub fn new() -> Self { + UpdateSeenBuilder { + _state: PhantomData, + _fields: (None, None), + _type: PhantomData, + } + } +} + +impl UpdateSeenBuilder { + /// Create a new builder with all fields unset + pub fn builder() -> Self { + UpdateSeenBuilder { + _state: PhantomData, + _fields: (None, None), + _type: PhantomData, + } + } +} + +impl UpdateSeenBuilder +where + St: update_seen_state::State, + St::Id: update_seen_state::IsUnset, +{ + /// Set the `id` field (required) + pub fn id( + mut self, + value: impl Into, + ) -> UpdateSeenBuilder, S> { + self._fields.0 = Option::Some(value.into()); + UpdateSeenBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl UpdateSeenBuilder +where + St: update_seen_state::State, + St::Read: update_seen_state::IsUnset, +{ + /// Set the `read` field (required) + pub fn read( + mut self, + value: impl Into, + ) -> UpdateSeenBuilder, S> { + self._fields.1 = Option::Some(value.into()); + UpdateSeenBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl UpdateSeenBuilder +where + St: update_seen_state::State, + St::Id: update_seen_state::IsSet, + St::Read: update_seen_state::IsSet, +{ + /// Build the final struct. + pub fn build(self) -> UpdateSeen { + UpdateSeen { + id: self._fields.0.unwrap(), + read: self._fields.1.unwrap(), + extra_data: Default::default(), + } + } + /// Build the final struct with custom extra_data. + pub fn build_with_data(self, extra_data: BTreeMap>) -> UpdateSeen { + UpdateSeen { + id: self._fields.0.unwrap(), + read: self._fields.1.unwrap(), + extra_data: Some(extra_data), + } + } +} diff --git a/crates/jacquard-api/src/org_tangled/temp/repo.rs b/crates/jacquard-api/src/org_tangled/temp/repo.rs new file mode 100644 index 000000000..df8354549 --- /dev/null +++ b/crates/jacquard-api/src/org_tangled/temp/repo.rs @@ -0,0 +1,16 @@ +// @generated by jacquard-lexicon. DO NOT EDIT. +// +// This file was automatically generated from Lexicon schemas. +// Any manual changes will be overwritten on the next regeneration. + +//! Generated bindings for the `org.tangled.temp.repo` Lexicon namespace/module. +pub mod create_webhook; +pub mod delete_webhook; +pub mod disable_site; +pub mod get_site_config; +pub mod list_webhook_deliveries; +pub mod list_webhooks; +pub mod retry_webhook_delivery; +pub mod toggle_webhook; +pub mod update_site_config; +pub mod update_webhook; diff --git a/crates/jacquard-api/src/org_tangled/temp/repo/create_webhook.rs b/crates/jacquard-api/src/org_tangled/temp/repo/create_webhook.rs new file mode 100644 index 000000000..bbf22e702 --- /dev/null +++ b/crates/jacquard-api/src/org_tangled/temp/repo/create_webhook.rs @@ -0,0 +1,340 @@ +// @generated by jacquard-lexicon. DO NOT EDIT. +// +// Lexicon: org.tangled.temp.repo.createWebhook +// +// 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::deps::smol_str::SmolStr; +use jacquard_common::types::string::{Did, UriValue}; +use jacquard_common::types::value::Data; +use jacquard_common::{BosStr, CowStr, DefaultStr, FromStaticStr}; +use jacquard_derive::{IntoStatic, open_union}; +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct CreateWebhook { + ///Whether the webhook should be active immediately. Defaults to true. + #[serde(skip_serializing_if = "Option::is_none")] + pub active: Option, + ///Event types to subscribe to (e.g. 'push', 'repository:renamed'). + pub events: Vec, + ///DID of the repository as minted by the knot. + pub repo_did: Did, + ///Optional HMAC secret used to sign payloads. If omitted, payloads are not signed. + #[serde(skip_serializing_if = "Option::is_none")] + pub secret: Option, + ///Endpoint URL that will receive webhook payloads. + pub url: UriValue, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct CreateWebhookOutput { + ///ID of the newly created webhook. + pub id: i64, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +#[derive( + Serialize, Deserialize, Debug, Clone, PartialEq, Eq, thiserror::Error, miette::Diagnostic, +)] +#[serde(tag = "error", content = "message")] +pub enum CreateWebhookError { + /// At least one event type must be specified. + #[serde(rename = "NoEventsSelected")] + NoEventsSelected(Option), + /// Catch-all for unknown error codes. + #[serde(untagged)] + Other { + error: SmolStr, + message: Option, + }, +} + +impl core::fmt::Display for CreateWebhookError { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + match self { + Self::NoEventsSelected(msg) => { + write!(f, "NoEventsSelected")?; + if let Some(msg) = msg { + write!(f, ": {}", msg)?; + } + Ok(()) + } + Self::Other { error, message } => { + write!(f, "{}", error)?; + if let Some(msg) = message { + write!(f, ": {}", msg)?; + } + Ok(()) + } + } + } +} + +/** Response marker for the `org.tangled.temp.repo.createWebhook` procedure. + +Implements `jacquard_common::xrpc::XrpcResp`; successful bodies decode as `Self::Output`, which is `CreateWebhookOutput` for this endpoint.*/ +pub struct CreateWebhookResponse; +impl jacquard_common::xrpc::XrpcResp for CreateWebhookResponse { + const NSID: &'static str = "org.tangled.temp.repo.createWebhook"; + const ENCODING: &'static str = "application/json"; + type Output = CreateWebhookOutput; + type Err = CreateWebhookError; +} + +impl jacquard_common::xrpc::XrpcRequest for CreateWebhook { + const NSID: &'static str = "org.tangled.temp.repo.createWebhook"; + const METHOD: jacquard_common::xrpc::XrpcMethod = + jacquard_common::xrpc::XrpcMethod::Procedure("application/json"); + type Response = CreateWebhookResponse; +} + +/** Endpoint marker for the `org.tangled.temp.repo.createWebhook` procedure. + +Path: `/xrpc/org.tangled.temp.repo.createWebhook`. The request payload type is `CreateWebhook`; send that request with `jacquard::Client` or use this marker through lower-level `XrpcEndpoint` APIs.*/ +pub struct CreateWebhookRequest; +impl jacquard_common::xrpc::XrpcEndpoint for CreateWebhookRequest { + const PATH: &'static str = "/xrpc/org.tangled.temp.repo.createWebhook"; + const METHOD: jacquard_common::xrpc::XrpcMethod = + jacquard_common::xrpc::XrpcMethod::Procedure("application/json"); + type Request = CreateWebhook; + type Response = CreateWebhookResponse; +} + +pub mod create_webhook_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 Events; + type RepoDid; + type Url; + } + /// Empty state - all required fields are unset + pub struct Empty(()); + impl sealed::Sealed for Empty {} + impl State for Empty { + type Events = Unset; + type RepoDid = Unset; + type Url = Unset; + } + ///State transition - sets the `events` field to Set + pub struct SetEvents(PhantomData St>); + impl sealed::Sealed for SetEvents {} + impl State for SetEvents { + type Events = Set; + type RepoDid = St::RepoDid; + type Url = St::Url; + } + ///State transition - sets the `repo_did` field to Set + pub struct SetRepoDid(PhantomData St>); + impl sealed::Sealed for SetRepoDid {} + impl State for SetRepoDid { + type Events = St::Events; + type RepoDid = Set; + type Url = St::Url; + } + ///State transition - sets the `url` field to Set + pub struct SetUrl(PhantomData St>); + impl sealed::Sealed for SetUrl {} + impl State for SetUrl { + type Events = St::Events; + type RepoDid = St::RepoDid; + type Url = Set; + } + /// Marker types for field names + #[allow(non_camel_case_types)] + pub mod members { + ///Marker type for the `events` field + pub struct events(()); + ///Marker type for the `repo_did` field + pub struct repo_did(()); + ///Marker type for the `url` field + pub struct url(()); + } +} + +/// Builder for constructing an instance of this type. +pub struct CreateWebhookBuilder { + _state: PhantomData St>, + _fields: ( + Option, + Option>, + Option>, + Option, + Option>, + ), + _type: PhantomData S>, +} + +impl CreateWebhook { + /// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed + pub fn new() -> CreateWebhookBuilder { + CreateWebhookBuilder::new() + } +} + +impl CreateWebhook { + /// Create a new builder for this type + pub fn builder() -> CreateWebhookBuilder { + CreateWebhookBuilder::builder() + } +} + +impl CreateWebhookBuilder { + /// Create a new builder with all fields unset, using the default string type, if needed + pub fn new() -> Self { + CreateWebhookBuilder { + _state: PhantomData, + _fields: (None, None, None, None, None), + _type: PhantomData, + } + } +} + +impl CreateWebhookBuilder { + /// Create a new builder with all fields unset + pub fn builder() -> Self { + CreateWebhookBuilder { + _state: PhantomData, + _fields: (None, None, None, None, None), + _type: PhantomData, + } + } +} + +impl CreateWebhookBuilder { + /// Set the `active` field (optional) + pub fn active(mut self, value: impl Into>) -> Self { + self._fields.0 = value.into(); + self + } + /// Set the `active` field to an Option value (optional) + pub fn maybe_active(mut self, value: Option) -> Self { + self._fields.0 = value; + self + } +} + +impl CreateWebhookBuilder +where + St: create_webhook_state::State, + St::Events: create_webhook_state::IsUnset, +{ + /// Set the `events` field (required) + pub fn events( + mut self, + value: impl Into>, + ) -> CreateWebhookBuilder, S> { + self._fields.1 = Option::Some(value.into()); + CreateWebhookBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl CreateWebhookBuilder +where + St: create_webhook_state::State, + St::RepoDid: create_webhook_state::IsUnset, +{ + /// Set the `repoDid` field (required) + pub fn repo_did( + mut self, + value: impl Into>, + ) -> CreateWebhookBuilder, S> { + self._fields.2 = Option::Some(value.into()); + CreateWebhookBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl CreateWebhookBuilder { + /// Set the `secret` field (optional) + pub fn secret(mut self, value: impl Into>) -> Self { + self._fields.3 = value.into(); + self + } + /// Set the `secret` field to an Option value (optional) + pub fn maybe_secret(mut self, value: Option) -> Self { + self._fields.3 = value; + self + } +} + +impl CreateWebhookBuilder +where + St: create_webhook_state::State, + St::Url: create_webhook_state::IsUnset, +{ + /// Set the `url` field (required) + pub fn url( + mut self, + value: impl Into>, + ) -> CreateWebhookBuilder, S> { + self._fields.4 = Option::Some(value.into()); + CreateWebhookBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl CreateWebhookBuilder +where + St: create_webhook_state::State, + St::Events: create_webhook_state::IsSet, + St::RepoDid: create_webhook_state::IsSet, + St::Url: create_webhook_state::IsSet, +{ + /// Build the final struct. + pub fn build(self) -> CreateWebhook { + CreateWebhook { + active: self._fields.0, + events: self._fields.1.unwrap(), + repo_did: self._fields.2.unwrap(), + secret: self._fields.3, + url: self._fields.4.unwrap(), + extra_data: Default::default(), + } + } + /// Build the final struct with custom extra_data. + pub fn build_with_data(self, extra_data: BTreeMap>) -> CreateWebhook { + CreateWebhook { + active: self._fields.0, + events: self._fields.1.unwrap(), + repo_did: self._fields.2.unwrap(), + secret: self._fields.3, + url: self._fields.4.unwrap(), + extra_data: Some(extra_data), + } + } +} diff --git a/crates/jacquard-api/src/org_tangled/temp/repo/delete_webhook.rs b/crates/jacquard-api/src/org_tangled/temp/repo/delete_webhook.rs new file mode 100644 index 000000000..12c16b89c --- /dev/null +++ b/crates/jacquard-api/src/org_tangled/temp/repo/delete_webhook.rs @@ -0,0 +1,247 @@ +// @generated by jacquard-lexicon. DO NOT EDIT. +// +// Lexicon: org.tangled.temp.repo.deleteWebhook +// +// 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::deps::smol_str::SmolStr; +use jacquard_common::types::string::Did; +use jacquard_common::types::value::Data; +use jacquard_common::{BosStr, CowStr, DefaultStr, FromStaticStr}; +use jacquard_derive::{IntoStatic, open_union}; +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct DeleteWebhook { + ///Webhook ID to delete. + pub id: i64, + ///DID of the repository as minted by the knot. + pub repo_did: Did, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +#[derive( + Serialize, Deserialize, Debug, Clone, PartialEq, Eq, thiserror::Error, miette::Diagnostic, +)] +#[serde(tag = "error", content = "message")] +pub enum DeleteWebhookError { + #[serde(rename = "WebhookNotFound")] + WebhookNotFound(Option), + /// Catch-all for unknown error codes. + #[serde(untagged)] + Other { + error: SmolStr, + message: Option, + }, +} + +impl core::fmt::Display for DeleteWebhookError { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + match self { + Self::WebhookNotFound(msg) => { + write!(f, "WebhookNotFound")?; + if let Some(msg) = msg { + write!(f, ": {}", msg)?; + } + Ok(()) + } + Self::Other { error, message } => { + write!(f, "{}", error)?; + if let Some(msg) = message { + write!(f, ": {}", msg)?; + } + Ok(()) + } + } + } +} + +/** Response marker for the `org.tangled.temp.repo.deleteWebhook` procedure. + +Implements `jacquard_common::xrpc::XrpcResp`; successful bodies decode as `Self::Output`, which is `()` for this endpoint.*/ +pub struct DeleteWebhookResponse; +impl jacquard_common::xrpc::XrpcResp for DeleteWebhookResponse { + const NSID: &'static str = "org.tangled.temp.repo.deleteWebhook"; + const ENCODING: &'static str = "application/json"; + type Output = (); + type Err = DeleteWebhookError; +} + +impl jacquard_common::xrpc::XrpcRequest for DeleteWebhook { + const NSID: &'static str = "org.tangled.temp.repo.deleteWebhook"; + const METHOD: jacquard_common::xrpc::XrpcMethod = + jacquard_common::xrpc::XrpcMethod::Procedure("application/json"); + type Response = DeleteWebhookResponse; +} + +/** Endpoint marker for the `org.tangled.temp.repo.deleteWebhook` procedure. + +Path: `/xrpc/org.tangled.temp.repo.deleteWebhook`. The request payload type is `DeleteWebhook`; send that request with `jacquard::Client` or use this marker through lower-level `XrpcEndpoint` APIs.*/ +pub struct DeleteWebhookRequest; +impl jacquard_common::xrpc::XrpcEndpoint for DeleteWebhookRequest { + const PATH: &'static str = "/xrpc/org.tangled.temp.repo.deleteWebhook"; + const METHOD: jacquard_common::xrpc::XrpcMethod = + jacquard_common::xrpc::XrpcMethod::Procedure("application/json"); + type Request = DeleteWebhook; + type Response = DeleteWebhookResponse; +} + +pub mod delete_webhook_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 Id; + type RepoDid; + } + /// Empty state - all required fields are unset + pub struct Empty(()); + impl sealed::Sealed for Empty {} + impl State for Empty { + type Id = Unset; + type RepoDid = Unset; + } + ///State transition - sets the `id` field to Set + pub struct SetId(PhantomData St>); + impl sealed::Sealed for SetId {} + impl State for SetId { + type Id = Set; + type RepoDid = St::RepoDid; + } + ///State transition - sets the `repo_did` field to Set + pub struct SetRepoDid(PhantomData St>); + impl sealed::Sealed for SetRepoDid {} + impl State for SetRepoDid { + type Id = St::Id; + type RepoDid = Set; + } + /// Marker types for field names + #[allow(non_camel_case_types)] + pub mod members { + ///Marker type for the `id` field + pub struct id(()); + ///Marker type for the `repo_did` field + pub struct repo_did(()); + } +} + +/// Builder for constructing an instance of this type. +pub struct DeleteWebhookBuilder { + _state: PhantomData St>, + _fields: (Option, Option>), + _type: PhantomData S>, +} + +impl DeleteWebhook { + /// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed + pub fn new() -> DeleteWebhookBuilder { + DeleteWebhookBuilder::new() + } +} + +impl DeleteWebhook { + /// Create a new builder for this type + pub fn builder() -> DeleteWebhookBuilder { + DeleteWebhookBuilder::builder() + } +} + +impl DeleteWebhookBuilder { + /// Create a new builder with all fields unset, using the default string type, if needed + pub fn new() -> Self { + DeleteWebhookBuilder { + _state: PhantomData, + _fields: (None, None), + _type: PhantomData, + } + } +} + +impl DeleteWebhookBuilder { + /// Create a new builder with all fields unset + pub fn builder() -> Self { + DeleteWebhookBuilder { + _state: PhantomData, + _fields: (None, None), + _type: PhantomData, + } + } +} + +impl DeleteWebhookBuilder +where + St: delete_webhook_state::State, + St::Id: delete_webhook_state::IsUnset, +{ + /// Set the `id` field (required) + pub fn id( + mut self, + value: impl Into, + ) -> DeleteWebhookBuilder, S> { + self._fields.0 = Option::Some(value.into()); + DeleteWebhookBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl DeleteWebhookBuilder +where + St: delete_webhook_state::State, + St::RepoDid: delete_webhook_state::IsUnset, +{ + /// Set the `repoDid` field (required) + pub fn repo_did( + mut self, + value: impl Into>, + ) -> DeleteWebhookBuilder, S> { + self._fields.1 = Option::Some(value.into()); + DeleteWebhookBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl DeleteWebhookBuilder +where + St: delete_webhook_state::State, + St::Id: delete_webhook_state::IsSet, + St::RepoDid: delete_webhook_state::IsSet, +{ + /// Build the final struct. + pub fn build(self) -> DeleteWebhook { + DeleteWebhook { + id: self._fields.0.unwrap(), + repo_did: self._fields.1.unwrap(), + extra_data: Default::default(), + } + } + /// Build the final struct with custom extra_data. + pub fn build_with_data(self, extra_data: BTreeMap>) -> DeleteWebhook { + DeleteWebhook { + id: self._fields.0.unwrap(), + repo_did: self._fields.1.unwrap(), + extra_data: Some(extra_data), + } + } +} diff --git a/crates/jacquard-api/src/org_tangled/temp/repo/disable_site.rs b/crates/jacquard-api/src/org_tangled/temp/repo/disable_site.rs new file mode 100644 index 000000000..14f828354 --- /dev/null +++ b/crates/jacquard-api/src/org_tangled/temp/repo/disable_site.rs @@ -0,0 +1,212 @@ +// @generated by jacquard-lexicon. DO NOT EDIT. +// +// Lexicon: org.tangled.temp.repo.disableSite +// +// 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::deps::smol_str::SmolStr; +use jacquard_common::types::string::Did; +use jacquard_common::types::value::Data; +use jacquard_common::{BosStr, CowStr, DefaultStr, FromStaticStr}; +use jacquard_derive::{IntoStatic, open_union}; +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct DisableSite { + ///DID of the repository as minted by the knot. + pub repo_did: Did, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +#[derive( + Serialize, Deserialize, Debug, Clone, PartialEq, Eq, thiserror::Error, miette::Diagnostic, +)] +#[serde(tag = "error", content = "message")] +pub enum DisableSiteError { + /// No site configuration exists for this repository. + #[serde(rename = "SiteNotFound")] + SiteNotFound(Option), + /// Catch-all for unknown error codes. + #[serde(untagged)] + Other { + error: SmolStr, + message: Option, + }, +} + +impl core::fmt::Display for DisableSiteError { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + match self { + Self::SiteNotFound(msg) => { + write!(f, "SiteNotFound")?; + if let Some(msg) = msg { + write!(f, ": {}", msg)?; + } + Ok(()) + } + Self::Other { error, message } => { + write!(f, "{}", error)?; + if let Some(msg) = message { + write!(f, ": {}", msg)?; + } + Ok(()) + } + } + } +} + +/** Response marker for the `org.tangled.temp.repo.disableSite` procedure. + +Implements `jacquard_common::xrpc::XrpcResp`; successful bodies decode as `Self::Output`, which is `()` for this endpoint.*/ +pub struct DisableSiteResponse; +impl jacquard_common::xrpc::XrpcResp for DisableSiteResponse { + const NSID: &'static str = "org.tangled.temp.repo.disableSite"; + const ENCODING: &'static str = "application/json"; + type Output = (); + type Err = DisableSiteError; +} + +impl jacquard_common::xrpc::XrpcRequest for DisableSite { + const NSID: &'static str = "org.tangled.temp.repo.disableSite"; + const METHOD: jacquard_common::xrpc::XrpcMethod = + jacquard_common::xrpc::XrpcMethod::Procedure("application/json"); + type Response = DisableSiteResponse; +} + +/** Endpoint marker for the `org.tangled.temp.repo.disableSite` procedure. + +Path: `/xrpc/org.tangled.temp.repo.disableSite`. The request payload type is `DisableSite`; send that request with `jacquard::Client` or use this marker through lower-level `XrpcEndpoint` APIs.*/ +pub struct DisableSiteRequest; +impl jacquard_common::xrpc::XrpcEndpoint for DisableSiteRequest { + const PATH: &'static str = "/xrpc/org.tangled.temp.repo.disableSite"; + const METHOD: jacquard_common::xrpc::XrpcMethod = + jacquard_common::xrpc::XrpcMethod::Procedure("application/json"); + type Request = DisableSite; + type Response = DisableSiteResponse; +} + +pub mod disable_site_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 RepoDid; + } + /// Empty state - all required fields are unset + pub struct Empty(()); + impl sealed::Sealed for Empty {} + impl State for Empty { + type RepoDid = Unset; + } + ///State transition - sets the `repo_did` field to Set + pub struct SetRepoDid(PhantomData St>); + impl sealed::Sealed for SetRepoDid {} + impl State for SetRepoDid { + type RepoDid = Set; + } + /// Marker types for field names + #[allow(non_camel_case_types)] + pub mod members { + ///Marker type for the `repo_did` field + pub struct repo_did(()); + } +} + +/// Builder for constructing an instance of this type. +pub struct DisableSiteBuilder { + _state: PhantomData St>, + _fields: (Option>,), + _type: PhantomData S>, +} + +impl DisableSite { + /// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed + pub fn new() -> DisableSiteBuilder { + DisableSiteBuilder::new() + } +} + +impl DisableSite { + /// Create a new builder for this type + pub fn builder() -> DisableSiteBuilder { + DisableSiteBuilder::builder() + } +} + +impl DisableSiteBuilder { + /// Create a new builder with all fields unset, using the default string type, if needed + pub fn new() -> Self { + DisableSiteBuilder { + _state: PhantomData, + _fields: (None,), + _type: PhantomData, + } + } +} + +impl DisableSiteBuilder { + /// Create a new builder with all fields unset + pub fn builder() -> Self { + DisableSiteBuilder { + _state: PhantomData, + _fields: (None,), + _type: PhantomData, + } + } +} + +impl DisableSiteBuilder +where + St: disable_site_state::State, + St::RepoDid: disable_site_state::IsUnset, +{ + /// Set the `repoDid` field (required) + pub fn repo_did( + mut self, + value: impl Into>, + ) -> DisableSiteBuilder, S> { + self._fields.0 = Option::Some(value.into()); + DisableSiteBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl DisableSiteBuilder +where + St: disable_site_state::State, + St::RepoDid: disable_site_state::IsSet, +{ + /// Build the final struct. + pub fn build(self) -> DisableSite { + DisableSite { + repo_did: self._fields.0.unwrap(), + extra_data: Default::default(), + } + } + /// Build the final struct with custom extra_data. + pub fn build_with_data(self, extra_data: BTreeMap>) -> DisableSite { + DisableSite { + repo_did: self._fields.0.unwrap(), + extra_data: Some(extra_data), + } + } +} diff --git a/crates/jacquard-api/src/org_tangled/temp/repo/get_site_config.rs b/crates/jacquard-api/src/org_tangled/temp/repo/get_site_config.rs new file mode 100644 index 000000000..ea0b45ead --- /dev/null +++ b/crates/jacquard-api/src/org_tangled/temp/repo/get_site_config.rs @@ -0,0 +1,484 @@ +// @generated by jacquard-lexicon. DO NOT EDIT. +// +// Lexicon: org.tangled.temp.repo.getSiteConfig +// +// 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::string::Did; +use jacquard_common::types::value::Data; +use jacquard_derive::IntoStatic; +use jacquard_lexicon::lexicon::LexiconDoc; +use jacquard_lexicon::schema::LexiconSchema; + +use crate::org_tangled::temp::repo::get_site_config; +#[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", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct GetSiteConfig { + pub repo_did: Did, +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic, Default)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct GetSiteConfigOutput { + ///Site config for the repository. Absent if no site is configured. + #[serde(skip_serializing_if = "Option::is_none")] + pub config: Option>, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct SiteConfig { + ///Branch to deploy from. + pub branch: S, + ///Directory within the repository to deploy (e.g. '/' or '/docs'). + pub dir: S, + ///Whether this repo serves as the index (root) for the domain. + pub is_index: bool, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +/** Response marker for the `org.tangled.temp.repo.getSiteConfig` query. + +Implements `jacquard_common::xrpc::XrpcResp`; successful bodies decode as `Self::Output`, which is `GetSiteConfigOutput` for this endpoint.*/ +pub struct GetSiteConfigResponse; +impl jacquard_common::xrpc::XrpcResp for GetSiteConfigResponse { + const NSID: &'static str = "org.tangled.temp.repo.getSiteConfig"; + const ENCODING: &'static str = "application/json"; + type Output = GetSiteConfigOutput; + type Err = jacquard_common::xrpc::GenericError; +} + +impl jacquard_common::xrpc::XrpcRequest for GetSiteConfig { + const NSID: &'static str = "org.tangled.temp.repo.getSiteConfig"; + const METHOD: jacquard_common::xrpc::XrpcMethod = jacquard_common::xrpc::XrpcMethod::Query; + type Response = GetSiteConfigResponse; +} + +/** Endpoint marker for the `org.tangled.temp.repo.getSiteConfig` query. + +Path: `/xrpc/org.tangled.temp.repo.getSiteConfig`. The request payload type is `GetSiteConfig`; send that request with `jacquard::Client` or use this marker through lower-level `XrpcEndpoint` APIs.*/ +pub struct GetSiteConfigRequest; +impl jacquard_common::xrpc::XrpcEndpoint for GetSiteConfigRequest { + const PATH: &'static str = "/xrpc/org.tangled.temp.repo.getSiteConfig"; + const METHOD: jacquard_common::xrpc::XrpcMethod = jacquard_common::xrpc::XrpcMethod::Query; + type Request = GetSiteConfig; + type Response = GetSiteConfigResponse; +} + +impl LexiconSchema for SiteConfig { + fn nsid() -> &'static str { + "org.tangled.temp.repo.getSiteConfig" + } + fn def_name() -> &'static str { + "siteConfig" + } + fn lexicon_doc() -> LexiconDoc<'static> { + lexicon_doc_org_tangled_temp_repo_getSiteConfig() + } + fn validate(&self) -> Result<(), ConstraintError> { + Ok(()) + } +} + +pub mod get_site_config_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 RepoDid; + } + /// Empty state - all required fields are unset + pub struct Empty(()); + impl sealed::Sealed for Empty {} + impl State for Empty { + type RepoDid = Unset; + } + ///State transition - sets the `repo_did` field to Set + pub struct SetRepoDid(PhantomData St>); + impl sealed::Sealed for SetRepoDid {} + impl State for SetRepoDid { + type RepoDid = Set; + } + /// Marker types for field names + #[allow(non_camel_case_types)] + pub mod members { + ///Marker type for the `repo_did` field + pub struct repo_did(()); + } +} + +/// Builder for constructing an instance of this type. +pub struct GetSiteConfigBuilder { + _state: PhantomData St>, + _fields: (Option>,), + _type: PhantomData S>, +} + +impl GetSiteConfig { + /// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed + pub fn new() -> GetSiteConfigBuilder { + GetSiteConfigBuilder::new() + } +} + +impl GetSiteConfig { + /// Create a new builder for this type + pub fn builder() -> GetSiteConfigBuilder { + GetSiteConfigBuilder::builder() + } +} + +impl GetSiteConfigBuilder { + /// Create a new builder with all fields unset, using the default string type, if needed + pub fn new() -> Self { + GetSiteConfigBuilder { + _state: PhantomData, + _fields: (None,), + _type: PhantomData, + } + } +} + +impl GetSiteConfigBuilder { + /// Create a new builder with all fields unset + pub fn builder() -> Self { + GetSiteConfigBuilder { + _state: PhantomData, + _fields: (None,), + _type: PhantomData, + } + } +} + +impl GetSiteConfigBuilder +where + St: get_site_config_state::State, + St::RepoDid: get_site_config_state::IsUnset, +{ + /// Set the `repoDid` field (required) + pub fn repo_did( + mut self, + value: impl Into>, + ) -> GetSiteConfigBuilder, S> { + self._fields.0 = Option::Some(value.into()); + GetSiteConfigBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl GetSiteConfigBuilder +where + St: get_site_config_state::State, + St::RepoDid: get_site_config_state::IsSet, +{ + /// Build the final struct. + pub fn build(self) -> GetSiteConfig { + GetSiteConfig { + repo_did: self._fields.0.unwrap(), + } + } +} + +pub mod site_config_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 Branch; + type Dir; + type IsIndex; + } + /// Empty state - all required fields are unset + pub struct Empty(()); + impl sealed::Sealed for Empty {} + impl State for Empty { + type Branch = Unset; + type Dir = Unset; + type IsIndex = Unset; + } + ///State transition - sets the `branch` field to Set + pub struct SetBranch(PhantomData St>); + impl sealed::Sealed for SetBranch {} + impl State for SetBranch { + type Branch = Set; + type Dir = St::Dir; + type IsIndex = St::IsIndex; + } + ///State transition - sets the `dir` field to Set + pub struct SetDir(PhantomData St>); + impl sealed::Sealed for SetDir {} + impl State for SetDir { + type Branch = St::Branch; + type Dir = Set; + type IsIndex = St::IsIndex; + } + ///State transition - sets the `is_index` field to Set + pub struct SetIsIndex(PhantomData St>); + impl sealed::Sealed for SetIsIndex {} + impl State for SetIsIndex { + type Branch = St::Branch; + type Dir = St::Dir; + type IsIndex = Set; + } + /// Marker types for field names + #[allow(non_camel_case_types)] + pub mod members { + ///Marker type for the `branch` field + pub struct branch(()); + ///Marker type for the `dir` field + pub struct dir(()); + ///Marker type for the `is_index` field + pub struct is_index(()); + } +} + +/// Builder for constructing an instance of this type. +pub struct SiteConfigBuilder { + _state: PhantomData St>, + _fields: (Option, Option, Option), + _type: PhantomData S>, +} + +impl SiteConfig { + /// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed + pub fn new() -> SiteConfigBuilder { + SiteConfigBuilder::new() + } +} + +impl SiteConfig { + /// Create a new builder for this type + pub fn builder() -> SiteConfigBuilder { + SiteConfigBuilder::builder() + } +} + +impl SiteConfigBuilder { + /// Create a new builder with all fields unset, using the default string type, if needed + pub fn new() -> Self { + SiteConfigBuilder { + _state: PhantomData, + _fields: (None, None, None), + _type: PhantomData, + } + } +} + +impl SiteConfigBuilder { + /// Create a new builder with all fields unset + pub fn builder() -> Self { + SiteConfigBuilder { + _state: PhantomData, + _fields: (None, None, None), + _type: PhantomData, + } + } +} + +impl SiteConfigBuilder +where + St: site_config_state::State, + St::Branch: site_config_state::IsUnset, +{ + /// Set the `branch` field (required) + pub fn branch( + mut self, + value: impl Into, + ) -> SiteConfigBuilder, S> { + self._fields.0 = Option::Some(value.into()); + SiteConfigBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl SiteConfigBuilder +where + St: site_config_state::State, + St::Dir: site_config_state::IsUnset, +{ + /// Set the `dir` field (required) + pub fn dir( + mut self, + value: impl Into, + ) -> SiteConfigBuilder, S> { + self._fields.1 = Option::Some(value.into()); + SiteConfigBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl SiteConfigBuilder +where + St: site_config_state::State, + St::IsIndex: site_config_state::IsUnset, +{ + /// Set the `isIndex` field (required) + pub fn is_index( + mut self, + value: impl Into, + ) -> SiteConfigBuilder, S> { + self._fields.2 = Option::Some(value.into()); + SiteConfigBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl SiteConfigBuilder +where + St: site_config_state::State, + St::Branch: site_config_state::IsSet, + St::Dir: site_config_state::IsSet, + St::IsIndex: site_config_state::IsSet, +{ + /// Build the final struct. + pub fn build(self) -> SiteConfig { + SiteConfig { + branch: self._fields.0.unwrap(), + dir: self._fields.1.unwrap(), + is_index: 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>) -> SiteConfig { + SiteConfig { + branch: self._fields.0.unwrap(), + dir: self._fields.1.unwrap(), + is_index: self._fields.2.unwrap(), + extra_data: Some(extra_data), + } + } +} + +fn lexicon_doc_org_tangled_temp_repo_getSiteConfig() -> 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("org.tangled.temp.repo.getSiteConfig"), + defs: { + let mut map = BTreeMap::new(); + map.insert( + SmolStr::new_static("main"), + LexUserType::XrpcQuery(LexXrpcQuery { + parameters: Some(LexXrpcQueryParameter::Params(LexXrpcParameters { + required: Some(vec![SmolStr::new_static("repoDid")]), + properties: { + #[allow(unused_mut)] + let mut map = BTreeMap::new(); + map.insert( + SmolStr::new_static("repoDid"), + LexXrpcParametersProperty::String(LexString { + description: Some(CowStr::new_static( + "DID of the repository as minted by the knot.", + )), + format: Some(LexStringFormat::Did), + ..Default::default() + }), + ); + map + }, + ..Default::default() + })), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("siteConfig"), + LexUserType::Object(LexObject { + required: Some( + vec![ + SmolStr::new_static("branch"), SmolStr::new_static("dir"), + SmolStr::new_static("isIndex") + ], + ), + properties: { + #[allow(unused_mut)] + let mut map = BTreeMap::new(); + map.insert( + SmolStr::new_static("branch"), + LexObjectProperty::String(LexString { + description: Some( + CowStr::new_static("Branch to deploy from."), + ), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("dir"), + LexObjectProperty::String(LexString { + description: Some( + CowStr::new_static( + "Directory within the repository to deploy (e.g. '/' or '/docs').", + ), + ), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("isIndex"), + LexObjectProperty::Boolean(LexBoolean { + ..Default::default() + }), + ); + map + }, + ..Default::default() + }), + ); + map + }, + ..Default::default() + } +} diff --git a/crates/jacquard-api/src/org_tangled/temp/repo/list_webhook_deliveries.rs b/crates/jacquard-api/src/org_tangled/temp/repo/list_webhook_deliveries.rs new file mode 100644 index 000000000..9b45f2b96 --- /dev/null +++ b/crates/jacquard-api/src/org_tangled/temp/repo/list_webhook_deliveries.rs @@ -0,0 +1,769 @@ +// @generated by jacquard-lexicon. DO NOT EDIT. +// +// Lexicon: org.tangled.temp.repo.listWebhookDeliveries +// +// 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::string::{Datetime, Did, UriValue}; +use jacquard_common::types::value::Data; +use jacquard_derive::IntoStatic; +use jacquard_lexicon::lexicon::LexiconDoc; +use jacquard_lexicon::schema::LexiconSchema; + +use crate::org_tangled::temp::repo::list_webhook_deliveries; +#[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", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct Delivery { + pub created_at: Datetime, + ///UUID for tracking this delivery attempt. + pub delivery_id: S, + ///Event type that triggered the delivery. + pub event: S, + pub id: i64, + #[serde(skip_serializing_if = "Option::is_none")] + pub request_body: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub response_body: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub response_code: Option, + pub success: bool, + pub url: UriValue, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct ListWebhookDeliveries { + pub id: i64, + /// (min: 1, max: 100) + #[serde(skip_serializing_if = "Option::is_none")] + pub limit: Option, + pub repo_did: Did, +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct ListWebhookDeliveriesOutput { + pub deliveries: Vec>, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +impl LexiconSchema for Delivery { + fn nsid() -> &'static str { + "org.tangled.temp.repo.listWebhookDeliveries" + } + fn def_name() -> &'static str { + "delivery" + } + fn lexicon_doc() -> LexiconDoc<'static> { + lexicon_doc_org_tangled_temp_repo_listWebhookDeliveries() + } + fn validate(&self) -> Result<(), ConstraintError> { + Ok(()) + } +} + +/** Response marker for the `org.tangled.temp.repo.listWebhookDeliveries` query. + +Implements `jacquard_common::xrpc::XrpcResp`; successful bodies decode as `Self::Output`, which is `ListWebhookDeliveriesOutput` for this endpoint.*/ +pub struct ListWebhookDeliveriesResponse; +impl jacquard_common::xrpc::XrpcResp for ListWebhookDeliveriesResponse { + const NSID: &'static str = "org.tangled.temp.repo.listWebhookDeliveries"; + const ENCODING: &'static str = "application/json"; + type Output = ListWebhookDeliveriesOutput; + type Err = jacquard_common::xrpc::GenericError; +} + +impl jacquard_common::xrpc::XrpcRequest for ListWebhookDeliveries { + const NSID: &'static str = "org.tangled.temp.repo.listWebhookDeliveries"; + const METHOD: jacquard_common::xrpc::XrpcMethod = jacquard_common::xrpc::XrpcMethod::Query; + type Response = ListWebhookDeliveriesResponse; +} + +/** Endpoint marker for the `org.tangled.temp.repo.listWebhookDeliveries` query. + +Path: `/xrpc/org.tangled.temp.repo.listWebhookDeliveries`. The request payload type is `ListWebhookDeliveries`; send that request with `jacquard::Client` or use this marker through lower-level `XrpcEndpoint` APIs.*/ +pub struct ListWebhookDeliveriesRequest; +impl jacquard_common::xrpc::XrpcEndpoint for ListWebhookDeliveriesRequest { + const PATH: &'static str = "/xrpc/org.tangled.temp.repo.listWebhookDeliveries"; + const METHOD: jacquard_common::xrpc::XrpcMethod = jacquard_common::xrpc::XrpcMethod::Query; + type Request = ListWebhookDeliveries; + type Response = ListWebhookDeliveriesResponse; +} + +pub mod delivery_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 DeliveryId; + type Event; + type Id; + type Success; + type Url; + } + /// Empty state - all required fields are unset + pub struct Empty(()); + impl sealed::Sealed for Empty {} + impl State for Empty { + type CreatedAt = Unset; + type DeliveryId = Unset; + type Event = Unset; + type Id = Unset; + type Success = Unset; + type Url = 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 DeliveryId = St::DeliveryId; + type Event = St::Event; + type Id = St::Id; + type Success = St::Success; + type Url = St::Url; + } + ///State transition - sets the `delivery_id` field to Set + pub struct SetDeliveryId(PhantomData St>); + impl sealed::Sealed for SetDeliveryId {} + impl State for SetDeliveryId { + type CreatedAt = St::CreatedAt; + type DeliveryId = Set; + type Event = St::Event; + type Id = St::Id; + type Success = St::Success; + type Url = St::Url; + } + ///State transition - sets the `event` field to Set + pub struct SetEvent(PhantomData St>); + impl sealed::Sealed for SetEvent {} + impl State for SetEvent { + type CreatedAt = St::CreatedAt; + type DeliveryId = St::DeliveryId; + type Event = Set; + type Id = St::Id; + type Success = St::Success; + type Url = St::Url; + } + ///State transition - sets the `id` field to Set + pub struct SetId(PhantomData St>); + impl sealed::Sealed for SetId {} + impl State for SetId { + type CreatedAt = St::CreatedAt; + type DeliveryId = St::DeliveryId; + type Event = St::Event; + type Id = Set; + type Success = St::Success; + type Url = St::Url; + } + ///State transition - sets the `success` field to Set + pub struct SetSuccess(PhantomData St>); + impl sealed::Sealed for SetSuccess {} + impl State for SetSuccess { + type CreatedAt = St::CreatedAt; + type DeliveryId = St::DeliveryId; + type Event = St::Event; + type Id = St::Id; + type Success = Set; + type Url = St::Url; + } + ///State transition - sets the `url` field to Set + pub struct SetUrl(PhantomData St>); + impl sealed::Sealed for SetUrl {} + impl State for SetUrl { + type CreatedAt = St::CreatedAt; + type DeliveryId = St::DeliveryId; + type Event = St::Event; + type Id = St::Id; + type Success = St::Success; + type Url = 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 `delivery_id` field + pub struct delivery_id(()); + ///Marker type for the `event` field + pub struct event(()); + ///Marker type for the `id` field + pub struct id(()); + ///Marker type for the `success` field + pub struct success(()); + ///Marker type for the `url` field + pub struct url(()); + } +} + +/// Builder for constructing an instance of this type. +pub struct DeliveryBuilder { + _state: PhantomData St>, + _fields: ( + Option, + Option, + Option, + Option, + Option, + Option, + Option, + Option, + Option>, + ), + _type: PhantomData S>, +} + +impl Delivery { + /// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed + pub fn new() -> DeliveryBuilder { + DeliveryBuilder::new() + } +} + +impl Delivery { + /// Create a new builder for this type + pub fn builder() -> DeliveryBuilder { + DeliveryBuilder::builder() + } +} + +impl DeliveryBuilder { + /// Create a new builder with all fields unset, using the default string type, if needed + pub fn new() -> Self { + DeliveryBuilder { + _state: PhantomData, + _fields: (None, None, None, None, None, None, None, None, None), + _type: PhantomData, + } + } +} + +impl DeliveryBuilder { + /// Create a new builder with all fields unset + pub fn builder() -> Self { + DeliveryBuilder { + _state: PhantomData, + _fields: (None, None, None, None, None, None, None, None, None), + _type: PhantomData, + } + } +} + +impl DeliveryBuilder +where + St: delivery_state::State, + St::CreatedAt: delivery_state::IsUnset, +{ + /// Set the `createdAt` field (required) + pub fn created_at( + mut self, + value: impl Into, + ) -> DeliveryBuilder, S> { + self._fields.0 = Option::Some(value.into()); + DeliveryBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl DeliveryBuilder +where + St: delivery_state::State, + St::DeliveryId: delivery_state::IsUnset, +{ + /// Set the `deliveryId` field (required) + pub fn delivery_id( + mut self, + value: impl Into, + ) -> DeliveryBuilder, S> { + self._fields.1 = Option::Some(value.into()); + DeliveryBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl DeliveryBuilder +where + St: delivery_state::State, + St::Event: delivery_state::IsUnset, +{ + /// Set the `event` field (required) + pub fn event( + mut self, + value: impl Into, + ) -> DeliveryBuilder, S> { + self._fields.2 = Option::Some(value.into()); + DeliveryBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl DeliveryBuilder +where + St: delivery_state::State, + St::Id: delivery_state::IsUnset, +{ + /// Set the `id` field (required) + pub fn id(mut self, value: impl Into) -> DeliveryBuilder, S> { + self._fields.3 = Option::Some(value.into()); + DeliveryBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl DeliveryBuilder { + /// Set the `requestBody` field (optional) + pub fn request_body(mut self, value: impl Into>) -> Self { + self._fields.4 = value.into(); + self + } + /// Set the `requestBody` field to an Option value (optional) + pub fn maybe_request_body(mut self, value: Option) -> Self { + self._fields.4 = value; + self + } +} + +impl DeliveryBuilder { + /// Set the `responseBody` field (optional) + pub fn response_body(mut self, value: impl Into>) -> Self { + self._fields.5 = value.into(); + self + } + /// Set the `responseBody` field to an Option value (optional) + pub fn maybe_response_body(mut self, value: Option) -> Self { + self._fields.5 = value; + self + } +} + +impl DeliveryBuilder { + /// Set the `responseCode` field (optional) + pub fn response_code(mut self, value: impl Into>) -> Self { + self._fields.6 = value.into(); + self + } + /// Set the `responseCode` field to an Option value (optional) + pub fn maybe_response_code(mut self, value: Option) -> Self { + self._fields.6 = value; + self + } +} + +impl DeliveryBuilder +where + St: delivery_state::State, + St::Success: delivery_state::IsUnset, +{ + /// Set the `success` field (required) + pub fn success( + mut self, + value: impl Into, + ) -> DeliveryBuilder, S> { + self._fields.7 = Option::Some(value.into()); + DeliveryBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl DeliveryBuilder +where + St: delivery_state::State, + St::Url: delivery_state::IsUnset, +{ + /// Set the `url` field (required) + pub fn url( + mut self, + value: impl Into>, + ) -> DeliveryBuilder, S> { + self._fields.8 = Option::Some(value.into()); + DeliveryBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl DeliveryBuilder +where + St: delivery_state::State, + St::CreatedAt: delivery_state::IsSet, + St::DeliveryId: delivery_state::IsSet, + St::Event: delivery_state::IsSet, + St::Id: delivery_state::IsSet, + St::Success: delivery_state::IsSet, + St::Url: delivery_state::IsSet, +{ + /// Build the final struct. + pub fn build(self) -> Delivery { + Delivery { + created_at: self._fields.0.unwrap(), + delivery_id: self._fields.1.unwrap(), + event: self._fields.2.unwrap(), + id: self._fields.3.unwrap(), + request_body: self._fields.4, + response_body: self._fields.5, + response_code: self._fields.6, + success: self._fields.7.unwrap(), + url: self._fields.8.unwrap(), + extra_data: Default::default(), + } + } + /// Build the final struct with custom extra_data. + pub fn build_with_data(self, extra_data: BTreeMap>) -> Delivery { + Delivery { + created_at: self._fields.0.unwrap(), + delivery_id: self._fields.1.unwrap(), + event: self._fields.2.unwrap(), + id: self._fields.3.unwrap(), + request_body: self._fields.4, + response_body: self._fields.5, + response_code: self._fields.6, + success: self._fields.7.unwrap(), + url: self._fields.8.unwrap(), + extra_data: Some(extra_data), + } + } +} + +fn lexicon_doc_org_tangled_temp_repo_listWebhookDeliveries() -> 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("org.tangled.temp.repo.listWebhookDeliveries"), + defs: { + let mut map = BTreeMap::new(); + map.insert( + SmolStr::new_static("delivery"), + LexUserType::Object(LexObject { + required: Some(vec![ + SmolStr::new_static("id"), + SmolStr::new_static("deliveryId"), + SmolStr::new_static("event"), + SmolStr::new_static("url"), + SmolStr::new_static("success"), + 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("deliveryId"), + LexObjectProperty::String(LexString { + description: Some(CowStr::new_static( + "UUID for tracking this delivery attempt.", + )), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("event"), + LexObjectProperty::String(LexString { + description: Some(CowStr::new_static( + "Event type that triggered the delivery.", + )), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("id"), + LexObjectProperty::Integer(LexInteger { + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("requestBody"), + LexObjectProperty::String(LexString { + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("responseBody"), + LexObjectProperty::String(LexString { + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("responseCode"), + LexObjectProperty::Integer(LexInteger { + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("success"), + LexObjectProperty::Boolean(LexBoolean { + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("url"), + LexObjectProperty::String(LexString { + format: Some(LexStringFormat::Uri), + ..Default::default() + }), + ); + map + }, + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("main"), + LexUserType::XrpcQuery(LexXrpcQuery { + parameters: Some(LexXrpcQueryParameter::Params(LexXrpcParameters { + required: Some(vec![ + SmolStr::new_static("repoDid"), + SmolStr::new_static("id"), + ]), + properties: { + #[allow(unused_mut)] + let mut map = BTreeMap::new(); + map.insert( + SmolStr::new_static("id"), + LexXrpcParametersProperty::Integer(LexInteger { + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("limit"), + LexXrpcParametersProperty::Integer(LexInteger { + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("repoDid"), + LexXrpcParametersProperty::String(LexString { + description: Some(CowStr::new_static( + "DID of the repository as minted by the knot.", + )), + format: Some(LexStringFormat::Did), + ..Default::default() + }), + ); + map + }, + ..Default::default() + })), + ..Default::default() + }), + ); + map + }, + ..Default::default() + } +} + +pub mod list_webhook_deliveries_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 Id; + type RepoDid; + } + /// Empty state - all required fields are unset + pub struct Empty(()); + impl sealed::Sealed for Empty {} + impl State for Empty { + type Id = Unset; + type RepoDid = Unset; + } + ///State transition - sets the `id` field to Set + pub struct SetId(PhantomData St>); + impl sealed::Sealed for SetId {} + impl State for SetId { + type Id = Set; + type RepoDid = St::RepoDid; + } + ///State transition - sets the `repo_did` field to Set + pub struct SetRepoDid(PhantomData St>); + impl sealed::Sealed for SetRepoDid {} + impl State for SetRepoDid { + type Id = St::Id; + type RepoDid = Set; + } + /// Marker types for field names + #[allow(non_camel_case_types)] + pub mod members { + ///Marker type for the `id` field + pub struct id(()); + ///Marker type for the `repo_did` field + pub struct repo_did(()); + } +} + +/// Builder for constructing an instance of this type. +pub struct ListWebhookDeliveriesBuilder< + St: list_webhook_deliveries_state::State, + S: BosStr = DefaultStr, +> { + _state: PhantomData St>, + _fields: (Option, Option, Option>), + _type: PhantomData S>, +} + +impl ListWebhookDeliveries { + /// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed + pub fn new() -> ListWebhookDeliveriesBuilder { + ListWebhookDeliveriesBuilder::new() + } +} + +impl ListWebhookDeliveries { + /// Create a new builder for this type + pub fn builder() -> ListWebhookDeliveriesBuilder { + ListWebhookDeliveriesBuilder::builder() + } +} + +impl ListWebhookDeliveriesBuilder { + /// Create a new builder with all fields unset, using the default string type, if needed + pub fn new() -> Self { + ListWebhookDeliveriesBuilder { + _state: PhantomData, + _fields: (None, None, None), + _type: PhantomData, + } + } +} + +impl ListWebhookDeliveriesBuilder { + /// Create a new builder with all fields unset + pub fn builder() -> Self { + ListWebhookDeliveriesBuilder { + _state: PhantomData, + _fields: (None, None, None), + _type: PhantomData, + } + } +} + +impl ListWebhookDeliveriesBuilder +where + St: list_webhook_deliveries_state::State, + St::Id: list_webhook_deliveries_state::IsUnset, +{ + /// Set the `id` field (required) + pub fn id( + mut self, + value: impl Into, + ) -> ListWebhookDeliveriesBuilder, S> { + self._fields.0 = Option::Some(value.into()); + ListWebhookDeliveriesBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl ListWebhookDeliveriesBuilder { + /// Set the `limit` field (optional) + pub fn limit(mut self, value: impl Into>) -> Self { + self._fields.1 = value.into(); + self + } + /// Set the `limit` field to an Option value (optional) + pub fn maybe_limit(mut self, value: Option) -> Self { + self._fields.1 = value; + self + } +} + +impl ListWebhookDeliveriesBuilder +where + St: list_webhook_deliveries_state::State, + St::RepoDid: list_webhook_deliveries_state::IsUnset, +{ + /// Set the `repoDid` field (required) + pub fn repo_did( + mut self, + value: impl Into>, + ) -> ListWebhookDeliveriesBuilder, S> { + self._fields.2 = Option::Some(value.into()); + ListWebhookDeliveriesBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl ListWebhookDeliveriesBuilder +where + St: list_webhook_deliveries_state::State, + St::Id: list_webhook_deliveries_state::IsSet, + St::RepoDid: list_webhook_deliveries_state::IsSet, +{ + /// Build the final struct. + pub fn build(self) -> ListWebhookDeliveries { + ListWebhookDeliveries { + id: self._fields.0.unwrap(), + limit: self._fields.1, + repo_did: self._fields.2.unwrap(), + } + } +} diff --git a/crates/jacquard-api/src/org_tangled/temp/repo/list_webhooks.rs b/crates/jacquard-api/src/org_tangled/temp/repo/list_webhooks.rs new file mode 100644 index 000000000..ce4648ae4 --- /dev/null +++ b/crates/jacquard-api/src/org_tangled/temp/repo/list_webhooks.rs @@ -0,0 +1,611 @@ +// @generated by jacquard-lexicon. DO NOT EDIT. +// +// Lexicon: org.tangled.temp.repo.listWebhooks +// +// 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::string::{Datetime, Did, UriValue}; +use jacquard_common::types::value::Data; +use jacquard_derive::IntoStatic; +use jacquard_lexicon::lexicon::LexiconDoc; +use jacquard_lexicon::schema::LexiconSchema; + +use crate::org_tangled::temp::repo::list_webhooks; +#[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", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct ListWebhooks { + pub repo_did: Did, +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct ListWebhooksOutput { + pub webhooks: Vec>, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct Webhook { + ///Whether the webhook is currently enabled. + pub active: bool, + pub created_at: Datetime, + ///Event types this webhook is subscribed to (e.g. 'push', 'repository:renamed'). + pub events: Vec, + ///Webhook identifier. + pub id: i64, + #[serde(skip_serializing_if = "Option::is_none")] + pub updated_at: Option, + ///Endpoint URL that receives webhook payloads. + pub url: UriValue, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +/** Response marker for the `org.tangled.temp.repo.listWebhooks` query. + +Implements `jacquard_common::xrpc::XrpcResp`; successful bodies decode as `Self::Output`, which is `ListWebhooksOutput` for this endpoint.*/ +pub struct ListWebhooksResponse; +impl jacquard_common::xrpc::XrpcResp for ListWebhooksResponse { + const NSID: &'static str = "org.tangled.temp.repo.listWebhooks"; + const ENCODING: &'static str = "application/json"; + type Output = ListWebhooksOutput; + type Err = jacquard_common::xrpc::GenericError; +} + +impl jacquard_common::xrpc::XrpcRequest for ListWebhooks { + const NSID: &'static str = "org.tangled.temp.repo.listWebhooks"; + const METHOD: jacquard_common::xrpc::XrpcMethod = jacquard_common::xrpc::XrpcMethod::Query; + type Response = ListWebhooksResponse; +} + +/** Endpoint marker for the `org.tangled.temp.repo.listWebhooks` query. + +Path: `/xrpc/org.tangled.temp.repo.listWebhooks`. The request payload type is `ListWebhooks`; send that request with `jacquard::Client` or use this marker through lower-level `XrpcEndpoint` APIs.*/ +pub struct ListWebhooksRequest; +impl jacquard_common::xrpc::XrpcEndpoint for ListWebhooksRequest { + const PATH: &'static str = "/xrpc/org.tangled.temp.repo.listWebhooks"; + const METHOD: jacquard_common::xrpc::XrpcMethod = jacquard_common::xrpc::XrpcMethod::Query; + type Request = ListWebhooks; + type Response = ListWebhooksResponse; +} + +impl LexiconSchema for Webhook { + fn nsid() -> &'static str { + "org.tangled.temp.repo.listWebhooks" + } + fn def_name() -> &'static str { + "webhook" + } + fn lexicon_doc() -> LexiconDoc<'static> { + lexicon_doc_org_tangled_temp_repo_listWebhooks() + } + fn validate(&self) -> Result<(), ConstraintError> { + Ok(()) + } +} + +pub mod list_webhooks_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 RepoDid; + } + /// Empty state - all required fields are unset + pub struct Empty(()); + impl sealed::Sealed for Empty {} + impl State for Empty { + type RepoDid = Unset; + } + ///State transition - sets the `repo_did` field to Set + pub struct SetRepoDid(PhantomData St>); + impl sealed::Sealed for SetRepoDid {} + impl State for SetRepoDid { + type RepoDid = Set; + } + /// Marker types for field names + #[allow(non_camel_case_types)] + pub mod members { + ///Marker type for the `repo_did` field + pub struct repo_did(()); + } +} + +/// Builder for constructing an instance of this type. +pub struct ListWebhooksBuilder { + _state: PhantomData St>, + _fields: (Option>,), + _type: PhantomData S>, +} + +impl ListWebhooks { + /// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed + pub fn new() -> ListWebhooksBuilder { + ListWebhooksBuilder::new() + } +} + +impl ListWebhooks { + /// Create a new builder for this type + pub fn builder() -> ListWebhooksBuilder { + ListWebhooksBuilder::builder() + } +} + +impl ListWebhooksBuilder { + /// Create a new builder with all fields unset, using the default string type, if needed + pub fn new() -> Self { + ListWebhooksBuilder { + _state: PhantomData, + _fields: (None,), + _type: PhantomData, + } + } +} + +impl ListWebhooksBuilder { + /// Create a new builder with all fields unset + pub fn builder() -> Self { + ListWebhooksBuilder { + _state: PhantomData, + _fields: (None,), + _type: PhantomData, + } + } +} + +impl ListWebhooksBuilder +where + St: list_webhooks_state::State, + St::RepoDid: list_webhooks_state::IsUnset, +{ + /// Set the `repoDid` field (required) + pub fn repo_did( + mut self, + value: impl Into>, + ) -> ListWebhooksBuilder, S> { + self._fields.0 = Option::Some(value.into()); + ListWebhooksBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl ListWebhooksBuilder +where + St: list_webhooks_state::State, + St::RepoDid: list_webhooks_state::IsSet, +{ + /// Build the final struct. + pub fn build(self) -> ListWebhooks { + ListWebhooks { + repo_did: self._fields.0.unwrap(), + } + } +} + +pub mod webhook_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 Active; + type CreatedAt; + type Events; + type Id; + type Url; + } + /// Empty state - all required fields are unset + pub struct Empty(()); + impl sealed::Sealed for Empty {} + impl State for Empty { + type Active = Unset; + type CreatedAt = Unset; + type Events = Unset; + type Id = Unset; + type Url = Unset; + } + ///State transition - sets the `active` field to Set + pub struct SetActive(PhantomData St>); + impl sealed::Sealed for SetActive {} + impl State for SetActive { + type Active = Set; + type CreatedAt = St::CreatedAt; + type Events = St::Events; + type Id = St::Id; + type Url = St::Url; + } + ///State transition - sets the `created_at` field to Set + pub struct SetCreatedAt(PhantomData St>); + impl sealed::Sealed for SetCreatedAt {} + impl State for SetCreatedAt { + type Active = St::Active; + type CreatedAt = Set; + type Events = St::Events; + type Id = St::Id; + type Url = St::Url; + } + ///State transition - sets the `events` field to Set + pub struct SetEvents(PhantomData St>); + impl sealed::Sealed for SetEvents {} + impl State for SetEvents { + type Active = St::Active; + type CreatedAt = St::CreatedAt; + type Events = Set; + type Id = St::Id; + type Url = St::Url; + } + ///State transition - sets the `id` field to Set + pub struct SetId(PhantomData St>); + impl sealed::Sealed for SetId {} + impl State for SetId { + type Active = St::Active; + type CreatedAt = St::CreatedAt; + type Events = St::Events; + type Id = Set; + type Url = St::Url; + } + ///State transition - sets the `url` field to Set + pub struct SetUrl(PhantomData St>); + impl sealed::Sealed for SetUrl {} + impl State for SetUrl { + type Active = St::Active; + type CreatedAt = St::CreatedAt; + type Events = St::Events; + type Id = St::Id; + type Url = Set; + } + /// Marker types for field names + #[allow(non_camel_case_types)] + pub mod members { + ///Marker type for the `active` field + pub struct active(()); + ///Marker type for the `created_at` field + pub struct created_at(()); + ///Marker type for the `events` field + pub struct events(()); + ///Marker type for the `id` field + pub struct id(()); + ///Marker type for the `url` field + pub struct url(()); + } +} + +/// Builder for constructing an instance of this type. +pub struct WebhookBuilder { + _state: PhantomData St>, + _fields: ( + Option, + Option, + Option>, + Option, + Option, + Option>, + ), + _type: PhantomData S>, +} + +impl Webhook { + /// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed + pub fn new() -> WebhookBuilder { + WebhookBuilder::new() + } +} + +impl Webhook { + /// Create a new builder for this type + pub fn builder() -> WebhookBuilder { + WebhookBuilder::builder() + } +} + +impl WebhookBuilder { + /// Create a new builder with all fields unset, using the default string type, if needed + pub fn new() -> Self { + WebhookBuilder { + _state: PhantomData, + _fields: (None, None, None, None, None, None), + _type: PhantomData, + } + } +} + +impl WebhookBuilder { + /// Create a new builder with all fields unset + pub fn builder() -> Self { + WebhookBuilder { + _state: PhantomData, + _fields: (None, None, None, None, None, None), + _type: PhantomData, + } + } +} + +impl WebhookBuilder +where + St: webhook_state::State, + St::Active: webhook_state::IsUnset, +{ + /// Set the `active` field (required) + pub fn active( + mut self, + value: impl Into, + ) -> WebhookBuilder, S> { + self._fields.0 = Option::Some(value.into()); + WebhookBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl WebhookBuilder +where + St: webhook_state::State, + St::CreatedAt: webhook_state::IsUnset, +{ + /// Set the `createdAt` field (required) + pub fn created_at( + mut self, + value: impl Into, + ) -> WebhookBuilder, S> { + self._fields.1 = Option::Some(value.into()); + WebhookBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl WebhookBuilder +where + St: webhook_state::State, + St::Events: webhook_state::IsUnset, +{ + /// Set the `events` field (required) + pub fn events( + mut self, + value: impl Into>, + ) -> WebhookBuilder, S> { + self._fields.2 = Option::Some(value.into()); + WebhookBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl WebhookBuilder +where + St: webhook_state::State, + St::Id: webhook_state::IsUnset, +{ + /// Set the `id` field (required) + pub fn id(mut self, value: impl Into) -> WebhookBuilder, S> { + self._fields.3 = Option::Some(value.into()); + WebhookBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl WebhookBuilder { + /// Set the `updatedAt` field (optional) + pub fn updated_at(mut self, value: impl Into>) -> Self { + self._fields.4 = value.into(); + self + } + /// Set the `updatedAt` field to an Option value (optional) + pub fn maybe_updated_at(mut self, value: Option) -> Self { + self._fields.4 = value; + self + } +} + +impl WebhookBuilder +where + St: webhook_state::State, + St::Url: webhook_state::IsUnset, +{ + /// Set the `url` field (required) + pub fn url( + mut self, + value: impl Into>, + ) -> WebhookBuilder, S> { + self._fields.5 = Option::Some(value.into()); + WebhookBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl WebhookBuilder +where + St: webhook_state::State, + St::Active: webhook_state::IsSet, + St::CreatedAt: webhook_state::IsSet, + St::Events: webhook_state::IsSet, + St::Id: webhook_state::IsSet, + St::Url: webhook_state::IsSet, +{ + /// Build the final struct. + pub fn build(self) -> Webhook { + Webhook { + active: self._fields.0.unwrap(), + created_at: self._fields.1.unwrap(), + events: self._fields.2.unwrap(), + id: self._fields.3.unwrap(), + updated_at: self._fields.4, + url: self._fields.5.unwrap(), + extra_data: Default::default(), + } + } + /// Build the final struct with custom extra_data. + pub fn build_with_data(self, extra_data: BTreeMap>) -> Webhook { + Webhook { + active: self._fields.0.unwrap(), + created_at: self._fields.1.unwrap(), + events: self._fields.2.unwrap(), + id: self._fields.3.unwrap(), + updated_at: self._fields.4, + url: self._fields.5.unwrap(), + extra_data: Some(extra_data), + } + } +} + +fn lexicon_doc_org_tangled_temp_repo_listWebhooks() -> 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("org.tangled.temp.repo.listWebhooks"), + defs: { + let mut map = BTreeMap::new(); + map.insert( + SmolStr::new_static("main"), + LexUserType::XrpcQuery(LexXrpcQuery { + parameters: Some(LexXrpcQueryParameter::Params(LexXrpcParameters { + required: Some(vec![SmolStr::new_static("repoDid")]), + properties: { + #[allow(unused_mut)] + let mut map = BTreeMap::new(); + map.insert( + SmolStr::new_static("repoDid"), + LexXrpcParametersProperty::String(LexString { + description: Some(CowStr::new_static( + "DID of the repository as minted by the knot.", + )), + format: Some(LexStringFormat::Did), + ..Default::default() + }), + ); + map + }, + ..Default::default() + })), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("webhook"), + LexUserType::Object(LexObject { + required: Some( + vec![ + SmolStr::new_static("id"), SmolStr::new_static("url"), + SmolStr::new_static("active"), SmolStr::new_static("events"), + SmolStr::new_static("createdAt") + ], + ), + properties: { + #[allow(unused_mut)] + let mut map = BTreeMap::new(); + map.insert( + SmolStr::new_static("active"), + LexObjectProperty::Boolean(LexBoolean { + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("createdAt"), + LexObjectProperty::String(LexString { + format: Some(LexStringFormat::Datetime), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("events"), + LexObjectProperty::Array(LexArray { + description: Some( + CowStr::new_static( + "Event types this webhook is subscribed to (e.g. 'push', 'repository:renamed').", + ), + ), + items: LexArrayItem::String(LexString { + ..Default::default() + }), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("id"), + LexObjectProperty::Integer(LexInteger { + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("updatedAt"), + LexObjectProperty::String(LexString { + format: Some(LexStringFormat::Datetime), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("url"), + LexObjectProperty::String(LexString { + description: Some( + CowStr::new_static( + "Endpoint URL that receives webhook payloads.", + ), + ), + format: Some(LexStringFormat::Uri), + ..Default::default() + }), + ); + map + }, + ..Default::default() + }), + ); + map + }, + ..Default::default() + } +} diff --git a/crates/jacquard-api/src/org_tangled/temp/repo/retry_webhook_delivery.rs b/crates/jacquard-api/src/org_tangled/temp/repo/retry_webhook_delivery.rs new file mode 100644 index 000000000..9b02a3d15 --- /dev/null +++ b/crates/jacquard-api/src/org_tangled/temp/repo/retry_webhook_delivery.rs @@ -0,0 +1,300 @@ +// @generated by jacquard-lexicon. DO NOT EDIT. +// +// Lexicon: org.tangled.temp.repo.retryWebhookDelivery +// +// 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::deps::smol_str::SmolStr; +use jacquard_common::types::string::Did; +use jacquard_common::types::value::Data; +use jacquard_common::{BosStr, CowStr, DefaultStr, FromStaticStr}; +use jacquard_derive::{IntoStatic, open_union}; +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct RetryWebhookDelivery { + ///UUID of the delivery to retry. + pub delivery_id: S, + ///DID of the repository as minted by the knot. + pub repo_did: Did, + ///Webhook ID that owns the delivery. + pub webhook_id: i64, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +#[derive( + Serialize, Deserialize, Debug, Clone, PartialEq, Eq, thiserror::Error, miette::Diagnostic, +)] +#[serde(tag = "error", content = "message")] +pub enum RetryWebhookDeliveryError { + #[serde(rename = "WebhookNotFound")] + WebhookNotFound(Option), + #[serde(rename = "DeliveryNotFound")] + DeliveryNotFound(Option), + /// Catch-all for unknown error codes. + #[serde(untagged)] + Other { + error: SmolStr, + message: Option, + }, +} + +impl core::fmt::Display for RetryWebhookDeliveryError { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + match self { + Self::WebhookNotFound(msg) => { + write!(f, "WebhookNotFound")?; + if let Some(msg) = msg { + write!(f, ": {}", msg)?; + } + Ok(()) + } + Self::DeliveryNotFound(msg) => { + write!(f, "DeliveryNotFound")?; + if let Some(msg) = msg { + write!(f, ": {}", msg)?; + } + Ok(()) + } + Self::Other { error, message } => { + write!(f, "{}", error)?; + if let Some(msg) = message { + write!(f, ": {}", msg)?; + } + Ok(()) + } + } + } +} + +/** Response marker for the `org.tangled.temp.repo.retryWebhookDelivery` procedure. + +Implements `jacquard_common::xrpc::XrpcResp`; successful bodies decode as `Self::Output`, which is `()` for this endpoint.*/ +pub struct RetryWebhookDeliveryResponse; +impl jacquard_common::xrpc::XrpcResp for RetryWebhookDeliveryResponse { + const NSID: &'static str = "org.tangled.temp.repo.retryWebhookDelivery"; + const ENCODING: &'static str = "application/json"; + type Output = (); + type Err = RetryWebhookDeliveryError; +} + +impl jacquard_common::xrpc::XrpcRequest for RetryWebhookDelivery { + const NSID: &'static str = "org.tangled.temp.repo.retryWebhookDelivery"; + const METHOD: jacquard_common::xrpc::XrpcMethod = + jacquard_common::xrpc::XrpcMethod::Procedure("application/json"); + type Response = RetryWebhookDeliveryResponse; +} + +/** Endpoint marker for the `org.tangled.temp.repo.retryWebhookDelivery` procedure. + +Path: `/xrpc/org.tangled.temp.repo.retryWebhookDelivery`. The request payload type is `RetryWebhookDelivery`; send that request with `jacquard::Client` or use this marker through lower-level `XrpcEndpoint` APIs.*/ +pub struct RetryWebhookDeliveryRequest; +impl jacquard_common::xrpc::XrpcEndpoint for RetryWebhookDeliveryRequest { + const PATH: &'static str = "/xrpc/org.tangled.temp.repo.retryWebhookDelivery"; + const METHOD: jacquard_common::xrpc::XrpcMethod = + jacquard_common::xrpc::XrpcMethod::Procedure("application/json"); + type Request = RetryWebhookDelivery; + type Response = RetryWebhookDeliveryResponse; +} + +pub mod retry_webhook_delivery_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 DeliveryId; + type RepoDid; + type WebhookId; + } + /// Empty state - all required fields are unset + pub struct Empty(()); + impl sealed::Sealed for Empty {} + impl State for Empty { + type DeliveryId = Unset; + type RepoDid = Unset; + type WebhookId = Unset; + } + ///State transition - sets the `delivery_id` field to Set + pub struct SetDeliveryId(PhantomData St>); + impl sealed::Sealed for SetDeliveryId {} + impl State for SetDeliveryId { + type DeliveryId = Set; + type RepoDid = St::RepoDid; + type WebhookId = St::WebhookId; + } + ///State transition - sets the `repo_did` field to Set + pub struct SetRepoDid(PhantomData St>); + impl sealed::Sealed for SetRepoDid {} + impl State for SetRepoDid { + type DeliveryId = St::DeliveryId; + type RepoDid = Set; + type WebhookId = St::WebhookId; + } + ///State transition - sets the `webhook_id` field to Set + pub struct SetWebhookId(PhantomData St>); + impl sealed::Sealed for SetWebhookId {} + impl State for SetWebhookId { + type DeliveryId = St::DeliveryId; + type RepoDid = St::RepoDid; + type WebhookId = Set; + } + /// Marker types for field names + #[allow(non_camel_case_types)] + pub mod members { + ///Marker type for the `delivery_id` field + pub struct delivery_id(()); + ///Marker type for the `repo_did` field + pub struct repo_did(()); + ///Marker type for the `webhook_id` field + pub struct webhook_id(()); + } +} + +/// Builder for constructing an instance of this type. +pub struct RetryWebhookDeliveryBuilder< + St: retry_webhook_delivery_state::State, + S: BosStr = DefaultStr, +> { + _state: PhantomData St>, + _fields: (Option, Option>, Option), + _type: PhantomData S>, +} + +impl RetryWebhookDelivery { + /// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed + pub fn new() -> RetryWebhookDeliveryBuilder { + RetryWebhookDeliveryBuilder::new() + } +} + +impl RetryWebhookDelivery { + /// Create a new builder for this type + pub fn builder() -> RetryWebhookDeliveryBuilder { + RetryWebhookDeliveryBuilder::builder() + } +} + +impl RetryWebhookDeliveryBuilder { + /// Create a new builder with all fields unset, using the default string type, if needed + pub fn new() -> Self { + RetryWebhookDeliveryBuilder { + _state: PhantomData, + _fields: (None, None, None), + _type: PhantomData, + } + } +} + +impl RetryWebhookDeliveryBuilder { + /// Create a new builder with all fields unset + pub fn builder() -> Self { + RetryWebhookDeliveryBuilder { + _state: PhantomData, + _fields: (None, None, None), + _type: PhantomData, + } + } +} + +impl RetryWebhookDeliveryBuilder +where + St: retry_webhook_delivery_state::State, + St::DeliveryId: retry_webhook_delivery_state::IsUnset, +{ + /// Set the `deliveryId` field (required) + pub fn delivery_id( + mut self, + value: impl Into, + ) -> RetryWebhookDeliveryBuilder, S> { + self._fields.0 = Option::Some(value.into()); + RetryWebhookDeliveryBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl RetryWebhookDeliveryBuilder +where + St: retry_webhook_delivery_state::State, + St::RepoDid: retry_webhook_delivery_state::IsUnset, +{ + /// Set the `repoDid` field (required) + pub fn repo_did( + mut self, + value: impl Into>, + ) -> RetryWebhookDeliveryBuilder, S> { + self._fields.1 = Option::Some(value.into()); + RetryWebhookDeliveryBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl RetryWebhookDeliveryBuilder +where + St: retry_webhook_delivery_state::State, + St::WebhookId: retry_webhook_delivery_state::IsUnset, +{ + /// Set the `webhookId` field (required) + pub fn webhook_id( + mut self, + value: impl Into, + ) -> RetryWebhookDeliveryBuilder, S> { + self._fields.2 = Option::Some(value.into()); + RetryWebhookDeliveryBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl RetryWebhookDeliveryBuilder +where + St: retry_webhook_delivery_state::State, + St::DeliveryId: retry_webhook_delivery_state::IsSet, + St::RepoDid: retry_webhook_delivery_state::IsSet, + St::WebhookId: retry_webhook_delivery_state::IsSet, +{ + /// Build the final struct. + pub fn build(self) -> RetryWebhookDelivery { + RetryWebhookDelivery { + delivery_id: self._fields.0.unwrap(), + repo_did: self._fields.1.unwrap(), + webhook_id: 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>, + ) -> RetryWebhookDelivery { + RetryWebhookDelivery { + delivery_id: self._fields.0.unwrap(), + repo_did: self._fields.1.unwrap(), + webhook_id: self._fields.2.unwrap(), + extra_data: Some(extra_data), + } + } +} diff --git a/crates/jacquard-api/src/org_tangled/temp/repo/toggle_webhook.rs b/crates/jacquard-api/src/org_tangled/temp/repo/toggle_webhook.rs new file mode 100644 index 000000000..daeff414d --- /dev/null +++ b/crates/jacquard-api/src/org_tangled/temp/repo/toggle_webhook.rs @@ -0,0 +1,259 @@ +// @generated by jacquard-lexicon. DO NOT EDIT. +// +// Lexicon: org.tangled.temp.repo.toggleWebhook +// +// 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::deps::smol_str::SmolStr; +use jacquard_common::types::string::Did; +use jacquard_common::types::value::Data; +use jacquard_common::{BosStr, CowStr, DefaultStr, FromStaticStr}; +use jacquard_derive::{IntoStatic, open_union}; +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct ToggleWebhook { + ///Webhook ID to toggle. + pub id: i64, + ///DID of the repository as minted by the knot. + pub repo_did: Did, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct ToggleWebhookOutput { + ///New active state of the webhook. + pub active: bool, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +#[derive( + Serialize, Deserialize, Debug, Clone, PartialEq, Eq, thiserror::Error, miette::Diagnostic, +)] +#[serde(tag = "error", content = "message")] +pub enum ToggleWebhookError { + #[serde(rename = "WebhookNotFound")] + WebhookNotFound(Option), + /// Catch-all for unknown error codes. + #[serde(untagged)] + Other { + error: SmolStr, + message: Option, + }, +} + +impl core::fmt::Display for ToggleWebhookError { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + match self { + Self::WebhookNotFound(msg) => { + write!(f, "WebhookNotFound")?; + if let Some(msg) = msg { + write!(f, ": {}", msg)?; + } + Ok(()) + } + Self::Other { error, message } => { + write!(f, "{}", error)?; + if let Some(msg) = message { + write!(f, ": {}", msg)?; + } + Ok(()) + } + } + } +} + +/** Response marker for the `org.tangled.temp.repo.toggleWebhook` procedure. + +Implements `jacquard_common::xrpc::XrpcResp`; successful bodies decode as `Self::Output`, which is `ToggleWebhookOutput` for this endpoint.*/ +pub struct ToggleWebhookResponse; +impl jacquard_common::xrpc::XrpcResp for ToggleWebhookResponse { + const NSID: &'static str = "org.tangled.temp.repo.toggleWebhook"; + const ENCODING: &'static str = "application/json"; + type Output = ToggleWebhookOutput; + type Err = ToggleWebhookError; +} + +impl jacquard_common::xrpc::XrpcRequest for ToggleWebhook { + const NSID: &'static str = "org.tangled.temp.repo.toggleWebhook"; + const METHOD: jacquard_common::xrpc::XrpcMethod = + jacquard_common::xrpc::XrpcMethod::Procedure("application/json"); + type Response = ToggleWebhookResponse; +} + +/** Endpoint marker for the `org.tangled.temp.repo.toggleWebhook` procedure. + +Path: `/xrpc/org.tangled.temp.repo.toggleWebhook`. The request payload type is `ToggleWebhook`; send that request with `jacquard::Client` or use this marker through lower-level `XrpcEndpoint` APIs.*/ +pub struct ToggleWebhookRequest; +impl jacquard_common::xrpc::XrpcEndpoint for ToggleWebhookRequest { + const PATH: &'static str = "/xrpc/org.tangled.temp.repo.toggleWebhook"; + const METHOD: jacquard_common::xrpc::XrpcMethod = + jacquard_common::xrpc::XrpcMethod::Procedure("application/json"); + type Request = ToggleWebhook; + type Response = ToggleWebhookResponse; +} + +pub mod toggle_webhook_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 Id; + type RepoDid; + } + /// Empty state - all required fields are unset + pub struct Empty(()); + impl sealed::Sealed for Empty {} + impl State for Empty { + type Id = Unset; + type RepoDid = Unset; + } + ///State transition - sets the `id` field to Set + pub struct SetId(PhantomData St>); + impl sealed::Sealed for SetId {} + impl State for SetId { + type Id = Set; + type RepoDid = St::RepoDid; + } + ///State transition - sets the `repo_did` field to Set + pub struct SetRepoDid(PhantomData St>); + impl sealed::Sealed for SetRepoDid {} + impl State for SetRepoDid { + type Id = St::Id; + type RepoDid = Set; + } + /// Marker types for field names + #[allow(non_camel_case_types)] + pub mod members { + ///Marker type for the `id` field + pub struct id(()); + ///Marker type for the `repo_did` field + pub struct repo_did(()); + } +} + +/// Builder for constructing an instance of this type. +pub struct ToggleWebhookBuilder { + _state: PhantomData St>, + _fields: (Option, Option>), + _type: PhantomData S>, +} + +impl ToggleWebhook { + /// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed + pub fn new() -> ToggleWebhookBuilder { + ToggleWebhookBuilder::new() + } +} + +impl ToggleWebhook { + /// Create a new builder for this type + pub fn builder() -> ToggleWebhookBuilder { + ToggleWebhookBuilder::builder() + } +} + +impl ToggleWebhookBuilder { + /// Create a new builder with all fields unset, using the default string type, if needed + pub fn new() -> Self { + ToggleWebhookBuilder { + _state: PhantomData, + _fields: (None, None), + _type: PhantomData, + } + } +} + +impl ToggleWebhookBuilder { + /// Create a new builder with all fields unset + pub fn builder() -> Self { + ToggleWebhookBuilder { + _state: PhantomData, + _fields: (None, None), + _type: PhantomData, + } + } +} + +impl ToggleWebhookBuilder +where + St: toggle_webhook_state::State, + St::Id: toggle_webhook_state::IsUnset, +{ + /// Set the `id` field (required) + pub fn id( + mut self, + value: impl Into, + ) -> ToggleWebhookBuilder, S> { + self._fields.0 = Option::Some(value.into()); + ToggleWebhookBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl ToggleWebhookBuilder +where + St: toggle_webhook_state::State, + St::RepoDid: toggle_webhook_state::IsUnset, +{ + /// Set the `repoDid` field (required) + pub fn repo_did( + mut self, + value: impl Into>, + ) -> ToggleWebhookBuilder, S> { + self._fields.1 = Option::Some(value.into()); + ToggleWebhookBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl ToggleWebhookBuilder +where + St: toggle_webhook_state::State, + St::Id: toggle_webhook_state::IsSet, + St::RepoDid: toggle_webhook_state::IsSet, +{ + /// Build the final struct. + pub fn build(self) -> ToggleWebhook { + ToggleWebhook { + id: self._fields.0.unwrap(), + repo_did: self._fields.1.unwrap(), + extra_data: Default::default(), + } + } + /// Build the final struct with custom extra_data. + pub fn build_with_data(self, extra_data: BTreeMap>) -> ToggleWebhook { + ToggleWebhook { + id: self._fields.0.unwrap(), + repo_did: self._fields.1.unwrap(), + extra_data: Some(extra_data), + } + } +} diff --git a/crates/jacquard-api/src/org_tangled/temp/repo/update_site_config.rs b/crates/jacquard-api/src/org_tangled/temp/repo/update_site_config.rs new file mode 100644 index 000000000..93bc84888 --- /dev/null +++ b/crates/jacquard-api/src/org_tangled/temp/repo/update_site_config.rs @@ -0,0 +1,304 @@ +// @generated by jacquard-lexicon. DO NOT EDIT. +// +// Lexicon: org.tangled.temp.repo.updateSiteConfig +// +// 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::deps::smol_str::SmolStr; +use jacquard_common::types::string::Did; +use jacquard_common::types::value::Data; +use jacquard_common::{BosStr, CowStr, DefaultStr, FromStaticStr}; +use jacquard_derive::{IntoStatic, open_union}; +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct UpdateSiteConfig { + ///Branch to deploy from. + pub branch: S, + ///Directory within the repository to deploy (e.g. '/' or '/docs'). + pub dir: S, + ///Whether this repo should serve as the index (root) for the claimed domain. + #[serde(skip_serializing_if = "Option::is_none")] + pub is_index: Option, + ///DID of the repository as minted by the knot. + pub repo_did: Did, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +#[derive( + Serialize, Deserialize, Debug, Clone, PartialEq, Eq, thiserror::Error, miette::Diagnostic, +)] +#[serde(tag = "error", content = "message")] +pub enum UpdateSiteConfigError { + /// The account does not have an active domain claim. + #[serde(rename = "NoDomainClaim")] + NoDomainClaim(Option), + /// Catch-all for unknown error codes. + #[serde(untagged)] + Other { + error: SmolStr, + message: Option, + }, +} + +impl core::fmt::Display for UpdateSiteConfigError { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + match self { + Self::NoDomainClaim(msg) => { + write!(f, "NoDomainClaim")?; + if let Some(msg) = msg { + write!(f, ": {}", msg)?; + } + Ok(()) + } + Self::Other { error, message } => { + write!(f, "{}", error)?; + if let Some(msg) = message { + write!(f, ": {}", msg)?; + } + Ok(()) + } + } + } +} + +/** Response marker for the `org.tangled.temp.repo.updateSiteConfig` procedure. + +Implements `jacquard_common::xrpc::XrpcResp`; successful bodies decode as `Self::Output`, which is `()` for this endpoint.*/ +pub struct UpdateSiteConfigResponse; +impl jacquard_common::xrpc::XrpcResp for UpdateSiteConfigResponse { + const NSID: &'static str = "org.tangled.temp.repo.updateSiteConfig"; + const ENCODING: &'static str = "application/json"; + type Output = (); + type Err = UpdateSiteConfigError; +} + +impl jacquard_common::xrpc::XrpcRequest for UpdateSiteConfig { + const NSID: &'static str = "org.tangled.temp.repo.updateSiteConfig"; + const METHOD: jacquard_common::xrpc::XrpcMethod = + jacquard_common::xrpc::XrpcMethod::Procedure("application/json"); + type Response = UpdateSiteConfigResponse; +} + +/** Endpoint marker for the `org.tangled.temp.repo.updateSiteConfig` procedure. + +Path: `/xrpc/org.tangled.temp.repo.updateSiteConfig`. The request payload type is `UpdateSiteConfig`; send that request with `jacquard::Client` or use this marker through lower-level `XrpcEndpoint` APIs.*/ +pub struct UpdateSiteConfigRequest; +impl jacquard_common::xrpc::XrpcEndpoint for UpdateSiteConfigRequest { + const PATH: &'static str = "/xrpc/org.tangled.temp.repo.updateSiteConfig"; + const METHOD: jacquard_common::xrpc::XrpcMethod = + jacquard_common::xrpc::XrpcMethod::Procedure("application/json"); + type Request = UpdateSiteConfig; + type Response = UpdateSiteConfigResponse; +} + +pub mod update_site_config_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 Branch; + type Dir; + type RepoDid; + } + /// Empty state - all required fields are unset + pub struct Empty(()); + impl sealed::Sealed for Empty {} + impl State for Empty { + type Branch = Unset; + type Dir = Unset; + type RepoDid = Unset; + } + ///State transition - sets the `branch` field to Set + pub struct SetBranch(PhantomData St>); + impl sealed::Sealed for SetBranch {} + impl State for SetBranch { + type Branch = Set; + type Dir = St::Dir; + type RepoDid = St::RepoDid; + } + ///State transition - sets the `dir` field to Set + pub struct SetDir(PhantomData St>); + impl sealed::Sealed for SetDir {} + impl State for SetDir { + type Branch = St::Branch; + type Dir = Set; + type RepoDid = St::RepoDid; + } + ///State transition - sets the `repo_did` field to Set + pub struct SetRepoDid(PhantomData St>); + impl sealed::Sealed for SetRepoDid {} + impl State for SetRepoDid { + type Branch = St::Branch; + type Dir = St::Dir; + type RepoDid = Set; + } + /// Marker types for field names + #[allow(non_camel_case_types)] + pub mod members { + ///Marker type for the `branch` field + pub struct branch(()); + ///Marker type for the `dir` field + pub struct dir(()); + ///Marker type for the `repo_did` field + pub struct repo_did(()); + } +} + +/// Builder for constructing an instance of this type. +pub struct UpdateSiteConfigBuilder { + _state: PhantomData St>, + _fields: (Option, Option, Option, Option>), + _type: PhantomData S>, +} + +impl UpdateSiteConfig { + /// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed + pub fn new() -> UpdateSiteConfigBuilder { + UpdateSiteConfigBuilder::new() + } +} + +impl UpdateSiteConfig { + /// Create a new builder for this type + pub fn builder() -> UpdateSiteConfigBuilder { + UpdateSiteConfigBuilder::builder() + } +} + +impl UpdateSiteConfigBuilder { + /// Create a new builder with all fields unset, using the default string type, if needed + pub fn new() -> Self { + UpdateSiteConfigBuilder { + _state: PhantomData, + _fields: (None, None, None, None), + _type: PhantomData, + } + } +} + +impl UpdateSiteConfigBuilder { + /// Create a new builder with all fields unset + pub fn builder() -> Self { + UpdateSiteConfigBuilder { + _state: PhantomData, + _fields: (None, None, None, None), + _type: PhantomData, + } + } +} + +impl UpdateSiteConfigBuilder +where + St: update_site_config_state::State, + St::Branch: update_site_config_state::IsUnset, +{ + /// Set the `branch` field (required) + pub fn branch( + mut self, + value: impl Into, + ) -> UpdateSiteConfigBuilder, S> { + self._fields.0 = Option::Some(value.into()); + UpdateSiteConfigBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl UpdateSiteConfigBuilder +where + St: update_site_config_state::State, + St::Dir: update_site_config_state::IsUnset, +{ + /// Set the `dir` field (required) + pub fn dir( + mut self, + value: impl Into, + ) -> UpdateSiteConfigBuilder, S> { + self._fields.1 = Option::Some(value.into()); + UpdateSiteConfigBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl UpdateSiteConfigBuilder { + /// Set the `isIndex` field (optional) + pub fn is_index(mut self, value: impl Into>) -> Self { + self._fields.2 = value.into(); + self + } + /// Set the `isIndex` field to an Option value (optional) + pub fn maybe_is_index(mut self, value: Option) -> Self { + self._fields.2 = value; + self + } +} + +impl UpdateSiteConfigBuilder +where + St: update_site_config_state::State, + St::RepoDid: update_site_config_state::IsUnset, +{ + /// Set the `repoDid` field (required) + pub fn repo_did( + mut self, + value: impl Into>, + ) -> UpdateSiteConfigBuilder, S> { + self._fields.3 = Option::Some(value.into()); + UpdateSiteConfigBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl UpdateSiteConfigBuilder +where + St: update_site_config_state::State, + St::Branch: update_site_config_state::IsSet, + St::Dir: update_site_config_state::IsSet, + St::RepoDid: update_site_config_state::IsSet, +{ + /// Build the final struct. + pub fn build(self) -> UpdateSiteConfig { + UpdateSiteConfig { + branch: self._fields.0.unwrap(), + dir: self._fields.1.unwrap(), + is_index: self._fields.2, + repo_did: self._fields.3.unwrap(), + extra_data: Default::default(), + } + } + /// Build the final struct with custom extra_data. + pub fn build_with_data(self, extra_data: BTreeMap>) -> UpdateSiteConfig { + UpdateSiteConfig { + branch: self._fields.0.unwrap(), + dir: self._fields.1.unwrap(), + is_index: self._fields.2, + repo_did: self._fields.3.unwrap(), + extra_data: Some(extra_data), + } + } +} diff --git a/crates/jacquard-api/src/org_tangled/temp/repo/update_webhook.rs b/crates/jacquard-api/src/org_tangled/temp/repo/update_webhook.rs new file mode 100644 index 000000000..4f94ec5c9 --- /dev/null +++ b/crates/jacquard-api/src/org_tangled/temp/repo/update_webhook.rs @@ -0,0 +1,322 @@ +// @generated by jacquard-lexicon. DO NOT EDIT. +// +// Lexicon: org.tangled.temp.repo.updateWebhook +// +// 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::deps::smol_str::SmolStr; +use jacquard_common::types::string::{Did, UriValue}; +use jacquard_common::types::value::Data; +use jacquard_common::{BosStr, CowStr, DefaultStr, FromStaticStr}; +use jacquard_derive::{IntoStatic, open_union}; +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct UpdateWebhook { + #[serde(skip_serializing_if = "Option::is_none")] + pub active: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub events: Option>, + ///Webhook ID to update. + pub id: i64, + ///DID of the repository as minted by the knot. + pub repo_did: Did, + #[serde(skip_serializing_if = "Option::is_none")] + pub secret: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub url: Option>, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +#[derive( + Serialize, Deserialize, Debug, Clone, PartialEq, Eq, thiserror::Error, miette::Diagnostic, +)] +#[serde(tag = "error", content = "message")] +pub enum UpdateWebhookError { + #[serde(rename = "WebhookNotFound")] + WebhookNotFound(Option), + /// Catch-all for unknown error codes. + #[serde(untagged)] + Other { + error: SmolStr, + message: Option, + }, +} + +impl core::fmt::Display for UpdateWebhookError { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + match self { + Self::WebhookNotFound(msg) => { + write!(f, "WebhookNotFound")?; + if let Some(msg) = msg { + write!(f, ": {}", msg)?; + } + Ok(()) + } + Self::Other { error, message } => { + write!(f, "{}", error)?; + if let Some(msg) = message { + write!(f, ": {}", msg)?; + } + Ok(()) + } + } + } +} + +/** Response marker for the `org.tangled.temp.repo.updateWebhook` procedure. + +Implements `jacquard_common::xrpc::XrpcResp`; successful bodies decode as `Self::Output`, which is `()` for this endpoint.*/ +pub struct UpdateWebhookResponse; +impl jacquard_common::xrpc::XrpcResp for UpdateWebhookResponse { + const NSID: &'static str = "org.tangled.temp.repo.updateWebhook"; + const ENCODING: &'static str = "application/json"; + type Output = (); + type Err = UpdateWebhookError; +} + +impl jacquard_common::xrpc::XrpcRequest for UpdateWebhook { + const NSID: &'static str = "org.tangled.temp.repo.updateWebhook"; + const METHOD: jacquard_common::xrpc::XrpcMethod = + jacquard_common::xrpc::XrpcMethod::Procedure("application/json"); + type Response = UpdateWebhookResponse; +} + +/** Endpoint marker for the `org.tangled.temp.repo.updateWebhook` procedure. + +Path: `/xrpc/org.tangled.temp.repo.updateWebhook`. The request payload type is `UpdateWebhook`; send that request with `jacquard::Client` or use this marker through lower-level `XrpcEndpoint` APIs.*/ +pub struct UpdateWebhookRequest; +impl jacquard_common::xrpc::XrpcEndpoint for UpdateWebhookRequest { + const PATH: &'static str = "/xrpc/org.tangled.temp.repo.updateWebhook"; + const METHOD: jacquard_common::xrpc::XrpcMethod = + jacquard_common::xrpc::XrpcMethod::Procedure("application/json"); + type Request = UpdateWebhook; + type Response = UpdateWebhookResponse; +} + +pub mod update_webhook_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 Id; + type RepoDid; + } + /// Empty state - all required fields are unset + pub struct Empty(()); + impl sealed::Sealed for Empty {} + impl State for Empty { + type Id = Unset; + type RepoDid = Unset; + } + ///State transition - sets the `id` field to Set + pub struct SetId(PhantomData St>); + impl sealed::Sealed for SetId {} + impl State for SetId { + type Id = Set; + type RepoDid = St::RepoDid; + } + ///State transition - sets the `repo_did` field to Set + pub struct SetRepoDid(PhantomData St>); + impl sealed::Sealed for SetRepoDid {} + impl State for SetRepoDid { + type Id = St::Id; + type RepoDid = Set; + } + /// Marker types for field names + #[allow(non_camel_case_types)] + pub mod members { + ///Marker type for the `id` field + pub struct id(()); + ///Marker type for the `repo_did` field + pub struct repo_did(()); + } +} + +/// Builder for constructing an instance of this type. +pub struct UpdateWebhookBuilder { + _state: PhantomData St>, + _fields: ( + Option, + Option>, + Option, + Option>, + Option, + Option>, + ), + _type: PhantomData S>, +} + +impl UpdateWebhook { + /// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed + pub fn new() -> UpdateWebhookBuilder { + UpdateWebhookBuilder::new() + } +} + +impl UpdateWebhook { + /// Create a new builder for this type + pub fn builder() -> UpdateWebhookBuilder { + UpdateWebhookBuilder::builder() + } +} + +impl UpdateWebhookBuilder { + /// Create a new builder with all fields unset, using the default string type, if needed + pub fn new() -> Self { + UpdateWebhookBuilder { + _state: PhantomData, + _fields: (None, None, None, None, None, None), + _type: PhantomData, + } + } +} + +impl UpdateWebhookBuilder { + /// Create a new builder with all fields unset + pub fn builder() -> Self { + UpdateWebhookBuilder { + _state: PhantomData, + _fields: (None, None, None, None, None, None), + _type: PhantomData, + } + } +} + +impl UpdateWebhookBuilder { + /// Set the `active` field (optional) + pub fn active(mut self, value: impl Into>) -> Self { + self._fields.0 = value.into(); + self + } + /// Set the `active` field to an Option value (optional) + pub fn maybe_active(mut self, value: Option) -> Self { + self._fields.0 = value; + self + } +} + +impl UpdateWebhookBuilder { + /// Set the `events` field (optional) + pub fn events(mut self, value: impl Into>>) -> Self { + self._fields.1 = value.into(); + self + } + /// Set the `events` field to an Option value (optional) + pub fn maybe_events(mut self, value: Option>) -> Self { + self._fields.1 = value; + self + } +} + +impl UpdateWebhookBuilder +where + St: update_webhook_state::State, + St::Id: update_webhook_state::IsUnset, +{ + /// Set the `id` field (required) + pub fn id( + mut self, + value: impl Into, + ) -> UpdateWebhookBuilder, S> { + self._fields.2 = Option::Some(value.into()); + UpdateWebhookBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl UpdateWebhookBuilder +where + St: update_webhook_state::State, + St::RepoDid: update_webhook_state::IsUnset, +{ + /// Set the `repoDid` field (required) + pub fn repo_did( + mut self, + value: impl Into>, + ) -> UpdateWebhookBuilder, S> { + self._fields.3 = Option::Some(value.into()); + UpdateWebhookBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl UpdateWebhookBuilder { + /// Set the `secret` field (optional) + pub fn secret(mut self, value: impl Into>) -> Self { + self._fields.4 = value.into(); + self + } + /// Set the `secret` field to an Option value (optional) + pub fn maybe_secret(mut self, value: Option) -> Self { + self._fields.4 = value; + self + } +} + +impl UpdateWebhookBuilder { + /// Set the `url` field (optional) + pub fn url(mut self, value: impl Into>>) -> Self { + self._fields.5 = value.into(); + self + } + /// Set the `url` field to an Option value (optional) + pub fn maybe_url(mut self, value: Option>) -> Self { + self._fields.5 = value; + self + } +} + +impl UpdateWebhookBuilder +where + St: update_webhook_state::State, + St::Id: update_webhook_state::IsSet, + St::RepoDid: update_webhook_state::IsSet, +{ + /// Build the final struct. + pub fn build(self) -> UpdateWebhook { + UpdateWebhook { + active: self._fields.0, + events: self._fields.1, + id: self._fields.2.unwrap(), + repo_did: self._fields.3.unwrap(), + secret: self._fields.4, + url: self._fields.5, + extra_data: Default::default(), + } + } + /// Build the final struct with custom extra_data. + pub fn build_with_data(self, extra_data: BTreeMap>) -> UpdateWebhook { + UpdateWebhook { + active: self._fields.0, + events: self._fields.1, + id: self._fields.2.unwrap(), + repo_did: self._fields.3.unwrap(), + secret: self._fields.4, + url: self._fields.5, + extra_data: Some(extra_data), + } + } +} diff --git a/crates/jacquard-api/src/org_tangled/temp/search.rs b/crates/jacquard-api/src/org_tangled/temp/search.rs new file mode 100644 index 000000000..cf2b98463 --- /dev/null +++ b/crates/jacquard-api/src/org_tangled/temp/search.rs @@ -0,0 +1,7 @@ +// @generated by jacquard-lexicon. DO NOT EDIT. +// +// This file was automatically generated from Lexicon schemas. +// Any manual changes will be overwritten on the next regeneration. + +//! Generated bindings for the `org.tangled.temp.search` Lexicon namespace/module. +pub mod search_code; diff --git a/crates/jacquard-api/src/org_tangled/temp/search/search_code.rs b/crates/jacquard-api/src/org_tangled/temp/search/search_code.rs new file mode 100644 index 000000000..428ce68b5 --- /dev/null +++ b/crates/jacquard-api/src/org_tangled/temp/search/search_code.rs @@ -0,0 +1,1060 @@ +// @generated by jacquard-lexicon. DO NOT EDIT. +// +// Lexicon: org.tangled.temp.search.searchCode +// +// 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::string::Did; +use jacquard_common::types::value::Data; +use jacquard_derive::IntoStatic; +use jacquard_lexicon::lexicon::LexiconDoc; +use jacquard_lexicon::schema::LexiconSchema; + +use crate::org_tangled::temp::search::search_code; +#[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", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct Chunk { + ///Source lines for this match chunk. + pub content: S, + ///Byte-offset ranges within content that match the query. + #[serde(skip_serializing_if = "Option::is_none")] + pub highlights: Option>>, + ///1-based line number of the first line in content. + pub line_start: i64, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct FileResult { + pub chunks: Vec>, + ///Detected programming language. + #[serde(skip_serializing_if = "Option::is_none")] + pub language: Option, + ///File path relative to repository root. + pub path: S, + ///DID of the repository as minted by the knot. + pub repo_did: Did, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct Highlight { + ///End byte offset (exclusive) within the chunk content string. + pub end: i64, + ///Start byte offset within the chunk content string. + pub start: i64, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct SearchCode { + #[serde(skip_serializing_if = "Option::is_none")] + pub cursor: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub lang: Option, + /// (min: 1, max: 100) + #[serde(skip_serializing_if = "Option::is_none")] + pub limit: Option, + pub q: S, + #[serde(skip_serializing_if = "Option::is_none")] + pub repo_did: Option>, +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct SearchCodeOutput { + #[serde(skip_serializing_if = "Option::is_none")] + pub cursor: Option, + pub results: Vec>, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +impl LexiconSchema for Chunk { + fn nsid() -> &'static str { + "org.tangled.temp.search.searchCode" + } + fn def_name() -> &'static str { + "chunk" + } + fn lexicon_doc() -> LexiconDoc<'static> { + lexicon_doc_org_tangled_temp_search_searchCode() + } + fn validate(&self) -> Result<(), ConstraintError> { + Ok(()) + } +} + +impl LexiconSchema for FileResult { + fn nsid() -> &'static str { + "org.tangled.temp.search.searchCode" + } + fn def_name() -> &'static str { + "fileResult" + } + fn lexicon_doc() -> LexiconDoc<'static> { + lexicon_doc_org_tangled_temp_search_searchCode() + } + fn validate(&self) -> Result<(), ConstraintError> { + Ok(()) + } +} + +impl LexiconSchema for Highlight { + fn nsid() -> &'static str { + "org.tangled.temp.search.searchCode" + } + fn def_name() -> &'static str { + "highlight" + } + fn lexicon_doc() -> LexiconDoc<'static> { + lexicon_doc_org_tangled_temp_search_searchCode() + } + fn validate(&self) -> Result<(), ConstraintError> { + Ok(()) + } +} + +/** Response marker for the `org.tangled.temp.search.searchCode` query. + +Implements `jacquard_common::xrpc::XrpcResp`; successful bodies decode as `Self::Output`, which is `SearchCodeOutput` for this endpoint.*/ +pub struct SearchCodeResponse; +impl jacquard_common::xrpc::XrpcResp for SearchCodeResponse { + const NSID: &'static str = "org.tangled.temp.search.searchCode"; + const ENCODING: &'static str = "application/json"; + type Output = SearchCodeOutput; + type Err = jacquard_common::xrpc::GenericError; +} + +impl jacquard_common::xrpc::XrpcRequest for SearchCode { + const NSID: &'static str = "org.tangled.temp.search.searchCode"; + const METHOD: jacquard_common::xrpc::XrpcMethod = jacquard_common::xrpc::XrpcMethod::Query; + type Response = SearchCodeResponse; +} + +/** Endpoint marker for the `org.tangled.temp.search.searchCode` query. + +Path: `/xrpc/org.tangled.temp.search.searchCode`. The request payload type is `SearchCode`; send that request with `jacquard::Client` or use this marker through lower-level `XrpcEndpoint` APIs.*/ +pub struct SearchCodeRequest; +impl jacquard_common::xrpc::XrpcEndpoint for SearchCodeRequest { + const PATH: &'static str = "/xrpc/org.tangled.temp.search.searchCode"; + const METHOD: jacquard_common::xrpc::XrpcMethod = jacquard_common::xrpc::XrpcMethod::Query; + type Request = SearchCode; + type Response = SearchCodeResponse; +} + +pub mod chunk_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 Content; + type LineStart; + } + /// Empty state - all required fields are unset + pub struct Empty(()); + impl sealed::Sealed for Empty {} + impl State for Empty { + type Content = Unset; + type LineStart = Unset; + } + ///State transition - sets the `content` field to Set + pub struct SetContent(PhantomData St>); + impl sealed::Sealed for SetContent {} + impl State for SetContent { + type Content = Set; + type LineStart = St::LineStart; + } + ///State transition - sets the `line_start` field to Set + pub struct SetLineStart(PhantomData St>); + impl sealed::Sealed for SetLineStart {} + impl State for SetLineStart { + type Content = St::Content; + type LineStart = Set; + } + /// Marker types for field names + #[allow(non_camel_case_types)] + pub mod members { + ///Marker type for the `content` field + pub struct content(()); + ///Marker type for the `line_start` field + pub struct line_start(()); + } +} + +/// Builder for constructing an instance of this type. +pub struct ChunkBuilder { + _state: PhantomData St>, + _fields: ( + Option, + Option>>, + Option, + ), + _type: PhantomData S>, +} + +impl Chunk { + /// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed + pub fn new() -> ChunkBuilder { + ChunkBuilder::new() + } +} + +impl Chunk { + /// Create a new builder for this type + pub fn builder() -> ChunkBuilder { + ChunkBuilder::builder() + } +} + +impl ChunkBuilder { + /// Create a new builder with all fields unset, using the default string type, if needed + pub fn new() -> Self { + ChunkBuilder { + _state: PhantomData, + _fields: (None, None, None), + _type: PhantomData, + } + } +} + +impl ChunkBuilder { + /// Create a new builder with all fields unset + pub fn builder() -> Self { + ChunkBuilder { + _state: PhantomData, + _fields: (None, None, None), + _type: PhantomData, + } + } +} + +impl ChunkBuilder +where + St: chunk_state::State, + St::Content: chunk_state::IsUnset, +{ + /// Set the `content` field (required) + pub fn content(mut self, value: impl Into) -> ChunkBuilder, S> { + self._fields.0 = Option::Some(value.into()); + ChunkBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl ChunkBuilder { + /// Set the `highlights` field (optional) + pub fn highlights(mut self, value: impl Into>>>) -> Self { + self._fields.1 = value.into(); + self + } + /// Set the `highlights` field to an Option value (optional) + pub fn maybe_highlights(mut self, value: Option>>) -> Self { + self._fields.1 = value; + self + } +} + +impl ChunkBuilder +where + St: chunk_state::State, + St::LineStart: chunk_state::IsUnset, +{ + /// Set the `lineStart` field (required) + pub fn line_start( + mut self, + value: impl Into, + ) -> ChunkBuilder, S> { + self._fields.2 = Option::Some(value.into()); + ChunkBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl ChunkBuilder +where + St: chunk_state::State, + St::Content: chunk_state::IsSet, + St::LineStart: chunk_state::IsSet, +{ + /// Build the final struct. + pub fn build(self) -> Chunk { + Chunk { + content: self._fields.0.unwrap(), + highlights: self._fields.1, + line_start: 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>) -> Chunk { + Chunk { + content: self._fields.0.unwrap(), + highlights: self._fields.1, + line_start: self._fields.2.unwrap(), + extra_data: Some(extra_data), + } + } +} + +fn lexicon_doc_org_tangled_temp_search_searchCode() -> 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("org.tangled.temp.search.searchCode"), + defs: { + let mut map = BTreeMap::new(); + map.insert( + SmolStr::new_static("chunk"), + LexUserType::Object(LexObject { + required: Some(vec![ + SmolStr::new_static("content"), + SmolStr::new_static("lineStart"), + ]), + properties: { + #[allow(unused_mut)] + let mut map = BTreeMap::new(); + map.insert( + SmolStr::new_static("content"), + LexObjectProperty::String(LexString { + description: Some(CowStr::new_static( + "Source lines for this match chunk.", + )), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("highlights"), + LexObjectProperty::Array(LexArray { + description: Some(CowStr::new_static( + "Byte-offset ranges within content that match the query.", + )), + items: LexArrayItem::Ref(LexRef { + r#ref: CowStr::new_static("#highlight"), + ..Default::default() + }), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("lineStart"), + LexObjectProperty::Integer(LexInteger { + ..Default::default() + }), + ); + map + }, + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("fileResult"), + LexUserType::Object(LexObject { + required: Some(vec![ + SmolStr::new_static("repoDid"), + SmolStr::new_static("path"), + SmolStr::new_static("chunks"), + ]), + properties: { + #[allow(unused_mut)] + let mut map = BTreeMap::new(); + map.insert( + SmolStr::new_static("chunks"), + LexObjectProperty::Array(LexArray { + items: LexArrayItem::Ref(LexRef { + r#ref: CowStr::new_static("#chunk"), + ..Default::default() + }), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("language"), + LexObjectProperty::String(LexString { + description: Some(CowStr::new_static( + "Detected programming language.", + )), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("path"), + LexObjectProperty::String(LexString { + description: Some(CowStr::new_static( + "File path relative to repository root.", + )), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("repoDid"), + LexObjectProperty::String(LexString { + description: Some(CowStr::new_static( + "DID of the repository as minted by the knot.", + )), + format: Some(LexStringFormat::Did), + ..Default::default() + }), + ); + map + }, + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("highlight"), + LexUserType::Object(LexObject { + required: Some(vec![ + SmolStr::new_static("start"), + SmolStr::new_static("end"), + ]), + properties: { + #[allow(unused_mut)] + let mut map = BTreeMap::new(); + map.insert( + SmolStr::new_static("end"), + LexObjectProperty::Integer(LexInteger { + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("start"), + LexObjectProperty::Integer(LexInteger { + ..Default::default() + }), + ); + map + }, + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("main"), + LexUserType::XrpcQuery(LexXrpcQuery { + parameters: Some( + LexXrpcQueryParameter::Params(LexXrpcParameters { + required: Some(vec![SmolStr::new_static("q")]), + properties: { + #[allow(unused_mut)] + let mut map = BTreeMap::new(); + map.insert( + SmolStr::new_static("cursor"), + LexXrpcParametersProperty::String(LexString { + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("lang"), + LexXrpcParametersProperty::String(LexString { + description: Some( + CowStr::new_static( + "Restrict search to a specific programming language (e.g. 'go', 'rust').", + ), + ), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("limit"), + LexXrpcParametersProperty::Integer(LexInteger { + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("q"), + LexXrpcParametersProperty::String(LexString { + description: Some( + CowStr::new_static("Search query string."), + ), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("repoDid"), + LexXrpcParametersProperty::String(LexString { + description: Some( + CowStr::new_static( + "Restrict search to a specific repository, by its DID.", + ), + ), + format: Some(LexStringFormat::Did), + ..Default::default() + }), + ); + map + }, + ..Default::default() + }), + ), + ..Default::default() + }), + ); + map + }, + ..Default::default() + } +} + +pub mod file_result_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 Chunks; + type Path; + type RepoDid; + } + /// Empty state - all required fields are unset + pub struct Empty(()); + impl sealed::Sealed for Empty {} + impl State for Empty { + type Chunks = Unset; + type Path = Unset; + type RepoDid = Unset; + } + ///State transition - sets the `chunks` field to Set + pub struct SetChunks(PhantomData St>); + impl sealed::Sealed for SetChunks {} + impl State for SetChunks { + type Chunks = Set; + type Path = St::Path; + type RepoDid = St::RepoDid; + } + ///State transition - sets the `path` field to Set + pub struct SetPath(PhantomData St>); + impl sealed::Sealed for SetPath {} + impl State for SetPath { + type Chunks = St::Chunks; + type Path = Set; + type RepoDid = St::RepoDid; + } + ///State transition - sets the `repo_did` field to Set + pub struct SetRepoDid(PhantomData St>); + impl sealed::Sealed for SetRepoDid {} + impl State for SetRepoDid { + type Chunks = St::Chunks; + type Path = St::Path; + type RepoDid = Set; + } + /// Marker types for field names + #[allow(non_camel_case_types)] + pub mod members { + ///Marker type for the `chunks` field + pub struct chunks(()); + ///Marker type for the `path` field + pub struct path(()); + ///Marker type for the `repo_did` field + pub struct repo_did(()); + } +} + +/// Builder for constructing an instance of this type. +pub struct FileResultBuilder { + _state: PhantomData St>, + _fields: ( + Option>>, + Option, + Option, + Option>, + ), + _type: PhantomData S>, +} + +impl FileResult { + /// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed + pub fn new() -> FileResultBuilder { + FileResultBuilder::new() + } +} + +impl FileResult { + /// Create a new builder for this type + pub fn builder() -> FileResultBuilder { + FileResultBuilder::builder() + } +} + +impl FileResultBuilder { + /// Create a new builder with all fields unset, using the default string type, if needed + pub fn new() -> Self { + FileResultBuilder { + _state: PhantomData, + _fields: (None, None, None, None), + _type: PhantomData, + } + } +} + +impl FileResultBuilder { + /// Create a new builder with all fields unset + pub fn builder() -> Self { + FileResultBuilder { + _state: PhantomData, + _fields: (None, None, None, None), + _type: PhantomData, + } + } +} + +impl FileResultBuilder +where + St: file_result_state::State, + St::Chunks: file_result_state::IsUnset, +{ + /// Set the `chunks` field (required) + pub fn chunks( + mut self, + value: impl Into>>, + ) -> FileResultBuilder, S> { + self._fields.0 = Option::Some(value.into()); + FileResultBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl FileResultBuilder { + /// Set the `language` field (optional) + pub fn language(mut self, value: impl Into>) -> Self { + self._fields.1 = value.into(); + self + } + /// Set the `language` field to an Option value (optional) + pub fn maybe_language(mut self, value: Option) -> Self { + self._fields.1 = value; + self + } +} + +impl FileResultBuilder +where + St: file_result_state::State, + St::Path: file_result_state::IsUnset, +{ + /// Set the `path` field (required) + pub fn path( + mut self, + value: impl Into, + ) -> FileResultBuilder, S> { + self._fields.2 = Option::Some(value.into()); + FileResultBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl FileResultBuilder +where + St: file_result_state::State, + St::RepoDid: file_result_state::IsUnset, +{ + /// Set the `repoDid` field (required) + pub fn repo_did( + mut self, + value: impl Into>, + ) -> FileResultBuilder, S> { + self._fields.3 = Option::Some(value.into()); + FileResultBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl FileResultBuilder +where + St: file_result_state::State, + St::Chunks: file_result_state::IsSet, + St::Path: file_result_state::IsSet, + St::RepoDid: file_result_state::IsSet, +{ + /// Build the final struct. + pub fn build(self) -> FileResult { + FileResult { + chunks: self._fields.0.unwrap(), + language: self._fields.1, + path: self._fields.2.unwrap(), + repo_did: self._fields.3.unwrap(), + extra_data: Default::default(), + } + } + /// Build the final struct with custom extra_data. + pub fn build_with_data(self, extra_data: BTreeMap>) -> FileResult { + FileResult { + chunks: self._fields.0.unwrap(), + language: self._fields.1, + path: self._fields.2.unwrap(), + repo_did: self._fields.3.unwrap(), + extra_data: Some(extra_data), + } + } +} + +pub mod highlight_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 End; + type Start; + } + /// Empty state - all required fields are unset + pub struct Empty(()); + impl sealed::Sealed for Empty {} + impl State for Empty { + type End = Unset; + type Start = Unset; + } + ///State transition - sets the `end` field to Set + pub struct SetEnd(PhantomData St>); + impl sealed::Sealed for SetEnd {} + impl State for SetEnd { + type End = Set; + type Start = St::Start; + } + ///State transition - sets the `start` field to Set + pub struct SetStart(PhantomData St>); + impl sealed::Sealed for SetStart {} + impl State for SetStart { + type End = St::End; + type Start = Set; + } + /// Marker types for field names + #[allow(non_camel_case_types)] + pub mod members { + ///Marker type for the `end` field + pub struct end(()); + ///Marker type for the `start` field + pub struct start(()); + } +} + +/// Builder for constructing an instance of this type. +pub struct HighlightBuilder { + _state: PhantomData St>, + _fields: (Option, Option), + _type: PhantomData S>, +} + +impl Highlight { + /// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed + pub fn new() -> HighlightBuilder { + HighlightBuilder::new() + } +} + +impl Highlight { + /// Create a new builder for this type + pub fn builder() -> HighlightBuilder { + HighlightBuilder::builder() + } +} + +impl HighlightBuilder { + /// Create a new builder with all fields unset, using the default string type, if needed + pub fn new() -> Self { + HighlightBuilder { + _state: PhantomData, + _fields: (None, None), + _type: PhantomData, + } + } +} + +impl HighlightBuilder { + /// Create a new builder with all fields unset + pub fn builder() -> Self { + HighlightBuilder { + _state: PhantomData, + _fields: (None, None), + _type: PhantomData, + } + } +} + +impl HighlightBuilder +where + St: highlight_state::State, + St::End: highlight_state::IsUnset, +{ + /// Set the `end` field (required) + pub fn end( + mut self, + value: impl Into, + ) -> HighlightBuilder, S> { + self._fields.0 = Option::Some(value.into()); + HighlightBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl HighlightBuilder +where + St: highlight_state::State, + St::Start: highlight_state::IsUnset, +{ + /// Set the `start` field (required) + pub fn start( + mut self, + value: impl Into, + ) -> HighlightBuilder, S> { + self._fields.1 = Option::Some(value.into()); + HighlightBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl HighlightBuilder +where + St: highlight_state::State, + St::End: highlight_state::IsSet, + St::Start: highlight_state::IsSet, +{ + /// Build the final struct. + pub fn build(self) -> Highlight { + Highlight { + end: self._fields.0.unwrap(), + start: self._fields.1.unwrap(), + extra_data: Default::default(), + } + } + /// Build the final struct with custom extra_data. + pub fn build_with_data(self, extra_data: BTreeMap>) -> Highlight { + Highlight { + end: self._fields.0.unwrap(), + start: self._fields.1.unwrap(), + extra_data: Some(extra_data), + } + } +} + +pub mod search_code_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 Q; + } + /// Empty state - all required fields are unset + pub struct Empty(()); + impl sealed::Sealed for Empty {} + impl State for Empty { + type Q = Unset; + } + ///State transition - sets the `q` field to Set + pub struct SetQ(PhantomData St>); + impl sealed::Sealed for SetQ {} + impl State for SetQ { + type Q = Set; + } + /// Marker types for field names + #[allow(non_camel_case_types)] + pub mod members { + ///Marker type for the `q` field + pub struct q(()); + } +} + +/// Builder for constructing an instance of this type. +pub struct SearchCodeBuilder { + _state: PhantomData St>, + _fields: (Option, Option, Option, Option, Option>), + _type: PhantomData S>, +} + +impl SearchCode { + /// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed + pub fn new() -> SearchCodeBuilder { + SearchCodeBuilder::new() + } +} + +impl SearchCode { + /// Create a new builder for this type + pub fn builder() -> SearchCodeBuilder { + SearchCodeBuilder::builder() + } +} + +impl SearchCodeBuilder { + /// Create a new builder with all fields unset, using the default string type, if needed + pub fn new() -> Self { + SearchCodeBuilder { + _state: PhantomData, + _fields: (None, None, None, None, None), + _type: PhantomData, + } + } +} + +impl SearchCodeBuilder { + /// Create a new builder with all fields unset + pub fn builder() -> Self { + SearchCodeBuilder { + _state: PhantomData, + _fields: (None, None, None, None, None), + _type: PhantomData, + } + } +} + +impl SearchCodeBuilder { + /// Set the `cursor` field (optional) + pub fn cursor(mut self, value: impl Into>) -> Self { + self._fields.0 = value.into(); + self + } + /// Set the `cursor` field to an Option value (optional) + pub fn maybe_cursor(mut self, value: Option) -> Self { + self._fields.0 = value; + self + } +} + +impl SearchCodeBuilder { + /// Set the `lang` field (optional) + pub fn lang(mut self, value: impl Into>) -> Self { + self._fields.1 = value.into(); + self + } + /// Set the `lang` field to an Option value (optional) + pub fn maybe_lang(mut self, value: Option) -> Self { + self._fields.1 = value; + self + } +} + +impl SearchCodeBuilder { + /// Set the `limit` field (optional) + pub fn limit(mut self, value: impl Into>) -> Self { + self._fields.2 = value.into(); + self + } + /// Set the `limit` field to an Option value (optional) + pub fn maybe_limit(mut self, value: Option) -> Self { + self._fields.2 = value; + self + } +} + +impl SearchCodeBuilder +where + St: search_code_state::State, + St::Q: search_code_state::IsUnset, +{ + /// Set the `q` field (required) + pub fn q(mut self, value: impl Into) -> SearchCodeBuilder, S> { + self._fields.3 = Option::Some(value.into()); + SearchCodeBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl SearchCodeBuilder { + /// Set the `repoDid` field (optional) + pub fn repo_did(mut self, value: impl Into>>) -> Self { + self._fields.4 = value.into(); + self + } + /// Set the `repoDid` field to an Option value (optional) + pub fn maybe_repo_did(mut self, value: Option>) -> Self { + self._fields.4 = value; + self + } +} + +impl SearchCodeBuilder +where + St: search_code_state::State, + St::Q: search_code_state::IsSet, +{ + /// Build the final struct. + pub fn build(self) -> SearchCode { + SearchCode { + cursor: self._fields.0, + lang: self._fields.1, + limit: self._fields.2, + q: self._fields.3.unwrap(), + repo_did: self._fields.4, + } + } +} diff --git a/crates/jacquard-api/src/org_tangled/temp/site.rs b/crates/jacquard-api/src/org_tangled/temp/site.rs new file mode 100644 index 000000000..f2e26cbfb --- /dev/null +++ b/crates/jacquard-api/src/org_tangled/temp/site.rs @@ -0,0 +1,9 @@ +// @generated by jacquard-lexicon. DO NOT EDIT. +// +// This file was automatically generated from Lexicon schemas. +// Any manual changes will be overwritten on the next regeneration. + +//! Generated bindings for the `org.tangled.temp.site` Lexicon namespace/module. +pub mod claim_domain; +pub mod get_domain_claim; +pub mod release_domain; diff --git a/crates/jacquard-api/src/org_tangled/temp/site/claim_domain.rs b/crates/jacquard-api/src/org_tangled/temp/site/claim_domain.rs new file mode 100644 index 000000000..9b9705190 --- /dev/null +++ b/crates/jacquard-api/src/org_tangled/temp/site/claim_domain.rs @@ -0,0 +1,126 @@ +// @generated by jacquard-lexicon. DO NOT EDIT. +// +// Lexicon: org.tangled.temp.site.claimDomain +// +// 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::deps::smol_str::SmolStr; +use jacquard_common::types::value::Data; +use jacquard_common::{BosStr, CowStr, DefaultStr, FromStaticStr}; +use jacquard_derive::{IntoStatic, open_union}; +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic, Default)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct ClaimDomain { + ///Desired subdomain label (lowercase letters, digits, and hyphens; 4–63 characters). + pub subdomain: S, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +#[derive( + Serialize, Deserialize, Debug, Clone, PartialEq, Eq, thiserror::Error, miette::Diagnostic, +)] +#[serde(tag = "error", content = "message")] +pub enum ClaimDomainError { + /// That subdomain is already claimed by another user. + #[serde(rename = "DomainTaken")] + DomainTaken(Option), + /// That subdomain was recently released and is in a cooldown period. + #[serde(rename = "DomainCooldown")] + DomainCooldown(Option), + /// You already have a domain claimed. Release it before claiming a new one. + #[serde(rename = "AlreadyClaimed")] + AlreadyClaimed(Option), + /// The subdomain label is invalid. + #[serde(rename = "InvalidSubdomain")] + InvalidSubdomain(Option), + /// Catch-all for unknown error codes. + #[serde(untagged)] + Other { + error: SmolStr, + message: Option, + }, +} + +impl core::fmt::Display for ClaimDomainError { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + match self { + Self::DomainTaken(msg) => { + write!(f, "DomainTaken")?; + if let Some(msg) = msg { + write!(f, ": {}", msg)?; + } + Ok(()) + } + Self::DomainCooldown(msg) => { + write!(f, "DomainCooldown")?; + if let Some(msg) = msg { + write!(f, ": {}", msg)?; + } + Ok(()) + } + Self::AlreadyClaimed(msg) => { + write!(f, "AlreadyClaimed")?; + if let Some(msg) = msg { + write!(f, ": {}", msg)?; + } + Ok(()) + } + Self::InvalidSubdomain(msg) => { + write!(f, "InvalidSubdomain")?; + if let Some(msg) = msg { + write!(f, ": {}", msg)?; + } + Ok(()) + } + Self::Other { error, message } => { + write!(f, "{}", error)?; + if let Some(msg) = message { + write!(f, ": {}", msg)?; + } + Ok(()) + } + } + } +} + +/** Response marker for the `org.tangled.temp.site.claimDomain` procedure. + +Implements `jacquard_common::xrpc::XrpcResp`; successful bodies decode as `Self::Output`, which is `()` for this endpoint.*/ +pub struct ClaimDomainResponse; +impl jacquard_common::xrpc::XrpcResp for ClaimDomainResponse { + const NSID: &'static str = "org.tangled.temp.site.claimDomain"; + const ENCODING: &'static str = "application/json"; + type Output = (); + type Err = ClaimDomainError; +} + +impl jacquard_common::xrpc::XrpcRequest for ClaimDomain { + const NSID: &'static str = "org.tangled.temp.site.claimDomain"; + const METHOD: jacquard_common::xrpc::XrpcMethod = + jacquard_common::xrpc::XrpcMethod::Procedure("application/json"); + type Response = ClaimDomainResponse; +} + +/** Endpoint marker for the `org.tangled.temp.site.claimDomain` procedure. + +Path: `/xrpc/org.tangled.temp.site.claimDomain`. The request payload type is `ClaimDomain`; send that request with `jacquard::Client` or use this marker through lower-level `XrpcEndpoint` APIs.*/ +pub struct ClaimDomainRequest; +impl jacquard_common::xrpc::XrpcEndpoint for ClaimDomainRequest { + const PATH: &'static str = "/xrpc/org.tangled.temp.site.claimDomain"; + const METHOD: jacquard_common::xrpc::XrpcMethod = + jacquard_common::xrpc::XrpcMethod::Procedure("application/json"); + type Request = ClaimDomain; + type Response = ClaimDomainResponse; +} diff --git a/crates/jacquard-api/src/org_tangled/temp/site/get_domain_claim.rs b/crates/jacquard-api/src/org_tangled/temp/site/get_domain_claim.rs new file mode 100644 index 000000000..f0bbb3333 --- /dev/null +++ b/crates/jacquard-api/src/org_tangled/temp/site/get_domain_claim.rs @@ -0,0 +1,64 @@ +// @generated by jacquard-lexicon. DO NOT EDIT. +// +// Lexicon: org.tangled.temp.site.getDomainClaim +// +// 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::deps::smol_str::SmolStr; +use jacquard_common::types::value::Data; +use jacquard_common::{BosStr, CowStr, DefaultStr, FromStaticStr}; +use jacquard_derive::IntoStatic; +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic, Default)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct GetDomainClaimOutput { + ///The claimed domain (e.g. 'alice.sites.tangled.sh'). Absent if no active claim. + #[serde(skip_serializing_if = "Option::is_none")] + pub domain: Option, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +/** Request marker for the `org.tangled.temp.site.getDomainClaim` query. + +This endpoint has no request parameters or input body; send this marker with `jacquard::Client`.*/ + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic, Copy)] +pub struct GetDomainClaim; +/** Response marker for the `org.tangled.temp.site.getDomainClaim` query. + +Implements `jacquard_common::xrpc::XrpcResp`; successful bodies decode as `Self::Output`, which is `GetDomainClaimOutput` for this endpoint.*/ +pub struct GetDomainClaimResponse; +impl jacquard_common::xrpc::XrpcResp for GetDomainClaimResponse { + const NSID: &'static str = "org.tangled.temp.site.getDomainClaim"; + const ENCODING: &'static str = "application/json"; + type Output = GetDomainClaimOutput; + type Err = jacquard_common::xrpc::GenericError; +} + +impl jacquard_common::xrpc::XrpcRequest for GetDomainClaim { + const NSID: &'static str = "org.tangled.temp.site.getDomainClaim"; + const METHOD: jacquard_common::xrpc::XrpcMethod = jacquard_common::xrpc::XrpcMethod::Query; + type Response = GetDomainClaimResponse; +} + +/** Endpoint marker for the `org.tangled.temp.site.getDomainClaim` query. + +Path: `/xrpc/org.tangled.temp.site.getDomainClaim`. The request payload type is `GetDomainClaim`; use this marker with lower-level `XrpcEndpoint` APIs when you need endpoint metadata.*/ +pub struct GetDomainClaimRequest; +impl jacquard_common::xrpc::XrpcEndpoint for GetDomainClaimRequest { + const PATH: &'static str = "/xrpc/org.tangled.temp.site.getDomainClaim"; + const METHOD: jacquard_common::xrpc::XrpcMethod = jacquard_common::xrpc::XrpcMethod::Query; + type Request = GetDomainClaim; + type Response = GetDomainClaimResponse; +} diff --git a/crates/jacquard-api/src/org_tangled/temp/site/release_domain.rs b/crates/jacquard-api/src/org_tangled/temp/site/release_domain.rs new file mode 100644 index 000000000..102250d1b --- /dev/null +++ b/crates/jacquard-api/src/org_tangled/temp/site/release_domain.rs @@ -0,0 +1,96 @@ +// @generated by jacquard-lexicon. DO NOT EDIT. +// +// Lexicon: org.tangled.temp.site.releaseDomain +// +// 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::deps::smol_str::SmolStr; +use jacquard_common::types::value::Data; +use jacquard_common::{BosStr, CowStr, DefaultStr, FromStaticStr}; +use jacquard_derive::{IntoStatic, open_union}; +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic, Default)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct ReleaseDomain { + ///Full domain to release (must match the user's active claim). + pub domain: S, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +#[derive( + Serialize, Deserialize, Debug, Clone, PartialEq, Eq, thiserror::Error, miette::Diagnostic, +)] +#[serde(tag = "error", content = "message")] +pub enum ReleaseDomainError { + /// No active claim found for the given domain under this account. + #[serde(rename = "DomainNotFound")] + DomainNotFound(Option), + /// Catch-all for unknown error codes. + #[serde(untagged)] + Other { + error: SmolStr, + message: Option, + }, +} + +impl core::fmt::Display for ReleaseDomainError { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + match self { + Self::DomainNotFound(msg) => { + write!(f, "DomainNotFound")?; + if let Some(msg) = msg { + write!(f, ": {}", msg)?; + } + Ok(()) + } + Self::Other { error, message } => { + write!(f, "{}", error)?; + if let Some(msg) = message { + write!(f, ": {}", msg)?; + } + Ok(()) + } + } + } +} + +/** Response marker for the `org.tangled.temp.site.releaseDomain` procedure. + +Implements `jacquard_common::xrpc::XrpcResp`; successful bodies decode as `Self::Output`, which is `()` for this endpoint.*/ +pub struct ReleaseDomainResponse; +impl jacquard_common::xrpc::XrpcResp for ReleaseDomainResponse { + const NSID: &'static str = "org.tangled.temp.site.releaseDomain"; + const ENCODING: &'static str = "application/json"; + type Output = (); + type Err = ReleaseDomainError; +} + +impl jacquard_common::xrpc::XrpcRequest for ReleaseDomain { + const NSID: &'static str = "org.tangled.temp.site.releaseDomain"; + const METHOD: jacquard_common::xrpc::XrpcMethod = + jacquard_common::xrpc::XrpcMethod::Procedure("application/json"); + type Response = ReleaseDomainResponse; +} + +/** Endpoint marker for the `org.tangled.temp.site.releaseDomain` procedure. + +Path: `/xrpc/org.tangled.temp.site.releaseDomain`. The request payload type is `ReleaseDomain`; send that request with `jacquard::Client` or use this marker through lower-level `XrpcEndpoint` APIs.*/ +pub struct ReleaseDomainRequest; +impl jacquard_common::xrpc::XrpcEndpoint for ReleaseDomainRequest { + const PATH: &'static str = "/xrpc/org.tangled.temp.site.releaseDomain"; + const METHOD: jacquard_common::xrpc::XrpcMethod = + jacquard_common::xrpc::XrpcMethod::Procedure("application/json"); + type Request = ReleaseDomain; + type Response = ReleaseDomainResponse; +} diff --git a/crates/jacquard-api/src/pink_vase/pod/show.rs b/crates/jacquard-api/src/pink_vase/pod/show.rs index 2df9874ff..8ea6dbae9 100644 --- a/crates/jacquard-api/src/pink_vase/pod/show.rs +++ b/crates/jacquard-api/src/pink_vase/pod/show.rs @@ -126,6 +126,18 @@ impl LexiconSchema for Show { }); } } + if let Some(values) = &self.categories { + for value in values { + #[allow(unused_comparisons)] + if ::len(value.as_ref()) > 100usize { + return Err(ConstraintError::MaxLength { + path: ValidationPath::from_field("categories"), + max: 100usize, + actual: ::len(value.as_ref()), + }); + } + } + } if let Some(ref value) = self.cover_art { { let size = value.blob().size; diff --git a/crates/jacquard-api/src/place_stream.rs b/crates/jacquard-api/src/place_stream.rs index 522860ab3..69c0ee334 100644 --- a/crates/jacquard-api/src/place_stream.rs +++ b/crates/jacquard-api/src/place_stream.rs @@ -6,6 +6,7 @@ // Any manual changes will be overwritten on the next regeneration. //! Generated bindings for the `place.stream` Lexicon namespace/module. +pub mod auth_full; pub mod badge; pub mod beta; pub mod branding; @@ -86,6 +87,7 @@ pub struct ActivityLabel { pub enum ActivityLabelLabel { Events, JustChatting, + Podcasting, Music, Art, SoftwareDev, @@ -102,6 +104,7 @@ impl ActivityLabelLabel { match self { Self::Events => "events", Self::JustChatting => "just_chatting", + Self::Podcasting => "podcasting", Self::Music => "music", Self::Art => "art", Self::SoftwareDev => "software_dev", @@ -118,6 +121,7 @@ impl ActivityLabelLabel { match s.as_ref() { "events" => Self::Events, "just_chatting" => Self::JustChatting, + "podcasting" => Self::Podcasting, "music" => Self::Music, "art" => Self::Art, "software_dev" => Self::SoftwareDev, @@ -178,6 +182,7 @@ where match self { ActivityLabelLabel::Events => ActivityLabelLabel::Events, ActivityLabelLabel::JustChatting => ActivityLabelLabel::JustChatting, + ActivityLabelLabel::Podcasting => ActivityLabelLabel::Podcasting, ActivityLabelLabel::Music => ActivityLabelLabel::Music, ActivityLabelLabel::Art => ActivityLabelLabel::Art, ActivityLabelLabel::SoftwareDev => ActivityLabelLabel::SoftwareDev, diff --git a/crates/jacquard-api/src/place_stream/auth_full.rs b/crates/jacquard-api/src/place_stream/auth_full.rs new file mode 100644 index 000000000..4d6932905 --- /dev/null +++ b/crates/jacquard-api/src/place_stream/auth_full.rs @@ -0,0 +1,8 @@ +// @generated by jacquard-lexicon. DO NOT EDIT. +// +// Lexicon: place.stream.authFull +// +// This file was automatically generated from Lexicon schemas. +// Any manual changes will be overwritten on the next regeneration. + +use jacquard_common::{BosStr, DefaultStr, FromStaticStr}; diff --git a/crates/jacquard-api/src/place_stream/broadcast/get_broadcaster.rs b/crates/jacquard-api/src/place_stream/broadcast/get_broadcaster.rs index b918c38b6..eebcf0d29 100644 --- a/crates/jacquard-api/src/place_stream/broadcast/get_broadcaster.rs +++ b/crates/jacquard-api/src/place_stream/broadcast/get_broadcaster.rs @@ -39,33 +39,6 @@ pub struct GetBroadcasterOutput { pub extra_data: Option>>, } -#[derive( - Serialize, Deserialize, Debug, Clone, PartialEq, Eq, thiserror::Error, miette::Diagnostic, -)] -#[serde(tag = "error", content = "message")] -pub enum GetBroadcasterError { - /// Catch-all for unknown error codes. - #[serde(untagged)] - Other { - error: SmolStr, - message: Option, - }, -} - -impl core::fmt::Display for GetBroadcasterError { - fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { - match self { - Self::Other { error, message } => { - write!(f, "{}", error)?; - if let Some(msg) = message { - write!(f, ": {}", msg)?; - } - Ok(()) - } - } - } -} - /** Response marker for the `place.stream.broadcast.getBroadcaster` query. Implements `jacquard_common::xrpc::XrpcResp`; successful bodies decode as `Self::Output`, which is `GetBroadcasterOutput` for this endpoint.*/ @@ -74,7 +47,7 @@ impl jacquard_common::xrpc::XrpcResp for GetBroadcasterResponse { const NSID: &'static str = "place.stream.broadcast.getBroadcaster"; const ENCODING: &'static str = "application/json"; type Output = GetBroadcasterOutput; - type Err = GetBroadcasterError; + type Err = jacquard_common::xrpc::GenericError; } impl jacquard_common::xrpc::XrpcRequest for GetBroadcaster { diff --git a/crates/jacquard-api/src/place_stream/chat/profile.rs b/crates/jacquard-api/src/place_stream/chat/profile.rs index f89474a7b..27275d877 100644 --- a/crates/jacquard-api/src/place_stream/chat/profile.rs +++ b/crates/jacquard-api/src/place_stream/chat/profile.rs @@ -449,7 +449,6 @@ fn lexicon_doc_place_stream_chat_profile() -> LexiconDoc<'static> { )), key: Some(CowStr::new_static("literal:self")), record: LexRecordRecord::Object(LexObject { - required: Some(vec![]), properties: { #[allow(unused_mut)] let mut map = BTreeMap::new(); diff --git a/crates/jacquard-api/src/place_stream/live/subscribe_segments.rs b/crates/jacquard-api/src/place_stream/live/subscribe_segments.rs index df1f57f86..c1dd590e6 100644 --- a/crates/jacquard-api/src/place_stream/live/subscribe_segments.rs +++ b/crates/jacquard-api/src/place_stream/live/subscribe_segments.rs @@ -51,33 +51,6 @@ impl SubscribeSegmentsMessage { } } -#[derive( - Serialize, Deserialize, Debug, Clone, PartialEq, Eq, thiserror::Error, miette::Diagnostic, -)] -#[serde(tag = "error", content = "message")] -pub enum SubscribeSegmentsError { - /// Catch-all for unknown error codes. - #[serde(untagged)] - Other { - error: jacquard_common::deps::smol_str::SmolStr, - message: Option, - }, -} - -impl core::fmt::Display for SubscribeSegmentsError { - fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { - match self { - Self::Other { error, message } => { - write!(f, "{}", error)?; - if let Some(msg) = message { - write!(f, ": {}", msg)?; - } - Ok(()) - } - } - } -} - pub type Segment = Bytes; ///Stream response type for ///place.stream.live.subscribeSegments @@ -87,7 +60,7 @@ impl jacquard_common::xrpc::SubscriptionResp for SubscribeSegmentsStream { const ENCODING: jacquard_common::xrpc::MessageEncoding = jacquard_common::xrpc::MessageEncoding::Json; type Message = SubscribeSegmentsMessage; - type Error = SubscribeSegmentsError; + type Error = jacquard_common::xrpc::GenericError; } impl jacquard_common::xrpc::XrpcSubscription for SubscribeSegments { diff --git a/crates/jacquard-api/src/place_stream/live/teleport.rs b/crates/jacquard-api/src/place_stream/live/teleport.rs index cd2c6bc1f..7e1b7f25d 100644 --- a/crates/jacquard-api/src/place_stream/live/teleport.rs +++ b/crates/jacquard-api/src/place_stream/live/teleport.rs @@ -24,6 +24,7 @@ use jacquard_derive::{IntoStatic, lexicon}; use jacquard_lexicon::lexicon::LexiconDoc; use jacquard_lexicon::schema::LexiconSchema; +use crate::com_atproto::repo::strong_ref::StrongRef; #[allow(unused_imports)] use jacquard_lexicon::validation::{ConstraintError, ValidationPath}; use serde::{Deserialize, Serialize}; @@ -40,6 +41,9 @@ pub struct Teleport { ///The time limit in seconds for the teleport. If not set, the teleport is permanent. Must be at least 60 seconds, and no more than 32,400 seconds (9 hours). #[serde(skip_serializing_if = "Option::is_none")] pub duration_seconds: Option, + ///The source livestream this teleport is sending viewers away from. When the teleport fires, this is the livestream that gets ended (the same update place.stream.live.stopLivestream performs), so the source streamer returns to pre-live. Teleports without an origin livestream are treated as a no-op. + #[serde(skip_serializing_if = "Option::is_none")] + pub livestream: Option>, ///The time the teleport becomes active. pub starts_at: Datetime, ///The DID of the streamer to teleport to. @@ -172,7 +176,12 @@ pub mod teleport_state { /// Builder for constructing an instance of this type. pub struct TeleportBuilder { _state: PhantomData St>, - _fields: (Option, Option, Option>), + _fields: ( + Option, + Option>, + Option, + Option>, + ), _type: PhantomData S>, } @@ -195,7 +204,7 @@ impl TeleportBuilder { pub fn new() -> Self { TeleportBuilder { _state: PhantomData, - _fields: (None, None, None), + _fields: (None, None, None, None), _type: PhantomData, } } @@ -206,7 +215,7 @@ impl TeleportBuilder { pub fn builder() -> Self { TeleportBuilder { _state: PhantomData, - _fields: (None, None, None), + _fields: (None, None, None, None), _type: PhantomData, } } @@ -225,6 +234,19 @@ impl TeleportBuilder { } } +impl TeleportBuilder { + /// Set the `livestream` field (optional) + pub fn livestream(mut self, value: impl Into>>) -> Self { + self._fields.1 = value.into(); + self + } + /// Set the `livestream` field to an Option value (optional) + pub fn maybe_livestream(mut self, value: Option>) -> Self { + self._fields.1 = value; + self + } +} + impl TeleportBuilder where St: teleport_state::State, @@ -235,7 +257,7 @@ where mut self, value: impl Into, ) -> TeleportBuilder, S> { - self._fields.1 = Option::Some(value.into()); + self._fields.2 = Option::Some(value.into()); TeleportBuilder { _state: PhantomData, _fields: self._fields, @@ -254,7 +276,7 @@ where mut self, value: impl Into>, ) -> TeleportBuilder, S> { - self._fields.2 = Option::Some(value.into()); + self._fields.3 = Option::Some(value.into()); TeleportBuilder { _state: PhantomData, _fields: self._fields, @@ -273,8 +295,9 @@ where pub fn build(self) -> Teleport { Teleport { duration_seconds: self._fields.0, - starts_at: self._fields.1.unwrap(), - streamer: self._fields.2.unwrap(), + livestream: self._fields.1, + starts_at: self._fields.2.unwrap(), + streamer: self._fields.3.unwrap(), extra_data: Default::default(), } } @@ -282,8 +305,9 @@ where pub fn build_with_data(self, extra_data: BTreeMap>) -> Teleport { Teleport { duration_seconds: self._fields.0, - starts_at: self._fields.1.unwrap(), - streamer: self._fields.2.unwrap(), + livestream: self._fields.1, + starts_at: self._fields.2.unwrap(), + streamer: self._fields.3.unwrap(), extra_data: Some(extra_data), } } @@ -322,6 +346,13 @@ fn lexicon_doc_place_stream_live_teleport() -> LexiconDoc<'static> { ..Default::default() }), ); + map.insert( + SmolStr::new_static("livestream"), + LexObjectProperty::Ref(LexRef { + r#ref: CowStr::new_static("com.atproto.repo.strongRef"), + ..Default::default() + }), + ); map.insert( SmolStr::new_static("startsAt"), LexObjectProperty::String(LexString { diff --git a/crates/jacquard-api/src/place_stream/livestream.rs b/crates/jacquard-api/src/place_stream/livestream.rs index d0cf19635..ebefda7d1 100644 --- a/crates/jacquard-api/src/place_stream/livestream.rs +++ b/crates/jacquard-api/src/place_stream/livestream.rs @@ -291,6 +291,32 @@ impl LexiconSchema for Livestream { }); } } + if let Some(values) = &self.tags { + for value in values { + #[allow(unused_comparisons)] + if ::len(value.as_ref()) > 640usize { + return Err(ConstraintError::MaxLength { + path: ValidationPath::from_field("tags"), + max: 640usize, + actual: ::len(value.as_ref()), + }); + } + } + } + if let Some(values) = &self.tags { + for value in values { + { + let count = UnicodeSegmentation::graphemes(value.as_ref(), true).count(); + if count > 64usize { + return Err(ConstraintError::MaxGraphemes { + path: ValidationPath::from_field("tags"), + max: 64usize, + actual: count, + }); + } + } + } + } if let Some(ref value) = self.thumb { { let size = value.blob().size; @@ -950,7 +976,6 @@ fn lexicon_doc_place_stream_livestream() -> LexiconDoc<'static> { map.insert( SmolStr::new_static("notificationSettings"), LexUserType::Object(LexObject { - required: Some(vec![]), properties: { #[allow(unused_mut)] let mut map = BTreeMap::new(); diff --git a/crates/jacquard-api/src/place_stream/media.rs b/crates/jacquard-api/src/place_stream/media.rs index fea2e20a6..24f4dd590 100644 --- a/crates/jacquard-api/src/place_stream/media.rs +++ b/crates/jacquard-api/src/place_stream/media.rs @@ -7,6 +7,7 @@ //! Generated bindings for the `place.stream.media` Lexicon namespace/module. pub mod create_upload; +pub mod finalize_livestream; pub mod get_upload_status; pub mod get_video; pub mod get_video_list; diff --git a/crates/jacquard-api/src/place_stream/media/create_upload.rs b/crates/jacquard-api/src/place_stream/media/create_upload.rs index 5ecaab3b9..c19ad0f87 100644 --- a/crates/jacquard-api/src/place_stream/media/create_upload.rs +++ b/crates/jacquard-api/src/place_stream/media/create_upload.rs @@ -23,6 +23,9 @@ use serde::{Deserialize, Serialize}; bound(deserialize = "S: Deserialize<'de> + BosStr") )] pub struct CreateUpload { + ///Optional ats:// URI of a draft VOD created via place.stream.vod.createDraft. When supplied, the upload's processing fills that draft (rather than creating a new one), so the user can edit metadata while the upload runs and re-upload if it fails. The draft's origin_upload_id is set to this upload. + #[serde(skip_serializing_if = "Option::is_none")] + pub draft_uri: Option, ///Optional filename hint to attach as upload metadata. #[serde(skip_serializing_if = "Option::is_none")] pub filename: Option, @@ -176,7 +179,7 @@ pub mod create_upload_state { /// Builder for constructing an instance of this type. pub struct CreateUploadBuilder { _state: PhantomData St>, - _fields: (Option, Option, Option), + _fields: (Option, Option, Option, Option), _type: PhantomData S>, } @@ -199,7 +202,7 @@ impl CreateUploadBuilder { pub fn new() -> Self { CreateUploadBuilder { _state: PhantomData, - _fields: (None, None, None), + _fields: (None, None, None, None), _type: PhantomData, } } @@ -210,21 +213,34 @@ impl CreateUploadBuilder { pub fn builder() -> Self { CreateUploadBuilder { _state: PhantomData, - _fields: (None, None, None), + _fields: (None, None, None, None), _type: PhantomData, } } } +impl CreateUploadBuilder { + /// Set the `draftUri` field (optional) + pub fn draft_uri(mut self, value: impl Into>) -> Self { + self._fields.0 = value.into(); + self + } + /// Set the `draftUri` field to an Option value (optional) + pub fn maybe_draft_uri(mut self, value: Option) -> Self { + self._fields.0 = value; + self + } +} + impl CreateUploadBuilder { /// Set the `filename` field (optional) pub fn filename(mut self, value: impl Into>) -> Self { - self._fields.0 = value.into(); + self._fields.1 = value.into(); self } /// Set the `filename` field to an Option value (optional) pub fn maybe_filename(mut self, value: Option) -> Self { - self._fields.0 = value; + self._fields.1 = value; self } } @@ -239,7 +255,7 @@ where mut self, value: impl Into, ) -> CreateUploadBuilder, S> { - self._fields.1 = Option::Some(value.into()); + self._fields.2 = Option::Some(value.into()); CreateUploadBuilder { _state: PhantomData, _fields: self._fields, @@ -258,7 +274,7 @@ where mut self, value: impl Into, ) -> CreateUploadBuilder, S> { - self._fields.2 = Option::Some(value.into()); + self._fields.3 = Option::Some(value.into()); CreateUploadBuilder { _state: PhantomData, _fields: self._fields, @@ -276,18 +292,20 @@ where /// Build the final struct. pub fn build(self) -> CreateUpload { CreateUpload { - filename: self._fields.0, - mime_type: self._fields.1.unwrap(), - size: self._fields.2.unwrap(), + draft_uri: self._fields.0, + filename: self._fields.1, + mime_type: self._fields.2.unwrap(), + size: self._fields.3.unwrap(), extra_data: Default::default(), } } /// Build the final struct with custom extra_data. pub fn build_with_data(self, extra_data: BTreeMap>) -> CreateUpload { CreateUpload { - filename: self._fields.0, - mime_type: self._fields.1.unwrap(), - size: self._fields.2.unwrap(), + draft_uri: self._fields.0, + filename: self._fields.1, + mime_type: self._fields.2.unwrap(), + size: self._fields.3.unwrap(), extra_data: Some(extra_data), } } diff --git a/crates/jacquard-api/src/place_stream/media/finalize_livestream.rs b/crates/jacquard-api/src/place_stream/media/finalize_livestream.rs new file mode 100644 index 000000000..4210118cb --- /dev/null +++ b/crates/jacquard-api/src/place_stream/media/finalize_livestream.rs @@ -0,0 +1,236 @@ +// @generated by jacquard-lexicon. DO NOT EDIT. +// +// Lexicon: place.stream.media.finalizeLivestream +// +// 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::deps::smol_str::SmolStr; +use jacquard_common::types::string::AtUri; +use jacquard_common::types::value::Data; +use jacquard_common::{BosStr, CowStr, DefaultStr, FromStaticStr}; +use jacquard_derive::{IntoStatic, open_union}; +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct FinalizeLivestream { + ///AT-URI of the place.stream.livestream record to finalize into a VOD. Must belong to the authenticated user. + pub livestream: AtUri, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic, Default)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct FinalizeLivestreamOutput { + ///The ats:// URI of the draft VOD created for this finalize. The draft reaches status 'ready' when processing completes; the user publishes it from the Drafts tab via place.stream.vod.publishDraft. + pub draft_uri: S, + ///Identifier for the finalize job. Retained for backwards compatibility; the draft flow no longer requires the client to poll getUploadStatus. + pub upload_id: S, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +#[derive( + Serialize, Deserialize, Debug, Clone, PartialEq, Eq, thiserror::Error, miette::Diagnostic, +)] +#[serde(tag = "error", content = "message")] +pub enum FinalizeLivestreamError { + /// No livestream with the given URI is known, or it does not belong to the authenticated user. + #[serde(rename = "LivestreamNotFound")] + LivestreamNotFound(Option), + /// The livestream has no recorded MUXL segments to finalize (recording was not enabled, or none completed). + #[serde(rename = "NoRecording")] + NoRecording(Option), + /// Catch-all for unknown error codes. + #[serde(untagged)] + Other { + error: SmolStr, + message: Option, + }, +} + +impl core::fmt::Display for FinalizeLivestreamError { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + match self { + Self::LivestreamNotFound(msg) => { + write!(f, "LivestreamNotFound")?; + if let Some(msg) = msg { + write!(f, ": {}", msg)?; + } + Ok(()) + } + Self::NoRecording(msg) => { + write!(f, "NoRecording")?; + if let Some(msg) = msg { + write!(f, ": {}", msg)?; + } + Ok(()) + } + Self::Other { error, message } => { + write!(f, "{}", error)?; + if let Some(msg) = message { + write!(f, ": {}", msg)?; + } + Ok(()) + } + } + } +} + +/** Response marker for the `place.stream.media.finalizeLivestream` procedure. + +Implements `jacquard_common::xrpc::XrpcResp`; successful bodies decode as `Self::Output`, which is `FinalizeLivestreamOutput` for this endpoint.*/ +pub struct FinalizeLivestreamResponse; +impl jacquard_common::xrpc::XrpcResp for FinalizeLivestreamResponse { + const NSID: &'static str = "place.stream.media.finalizeLivestream"; + const ENCODING: &'static str = "application/json"; + type Output = FinalizeLivestreamOutput; + type Err = FinalizeLivestreamError; +} + +impl jacquard_common::xrpc::XrpcRequest for FinalizeLivestream { + const NSID: &'static str = "place.stream.media.finalizeLivestream"; + const METHOD: jacquard_common::xrpc::XrpcMethod = + jacquard_common::xrpc::XrpcMethod::Procedure("application/json"); + type Response = FinalizeLivestreamResponse; +} + +/** Endpoint marker for the `place.stream.media.finalizeLivestream` procedure. + +Path: `/xrpc/place.stream.media.finalizeLivestream`. The request payload type is `FinalizeLivestream`; send that request with `jacquard::Client` or use this marker through lower-level `XrpcEndpoint` APIs.*/ +pub struct FinalizeLivestreamRequest; +impl jacquard_common::xrpc::XrpcEndpoint for FinalizeLivestreamRequest { + const PATH: &'static str = "/xrpc/place.stream.media.finalizeLivestream"; + const METHOD: jacquard_common::xrpc::XrpcMethod = + jacquard_common::xrpc::XrpcMethod::Procedure("application/json"); + type Request = FinalizeLivestream; + type Response = FinalizeLivestreamResponse; +} + +pub mod finalize_livestream_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 Livestream; + } + /// Empty state - all required fields are unset + pub struct Empty(()); + impl sealed::Sealed for Empty {} + impl State for Empty { + type Livestream = Unset; + } + ///State transition - sets the `livestream` field to Set + pub struct SetLivestream(PhantomData St>); + impl sealed::Sealed for SetLivestream {} + impl State for SetLivestream { + type Livestream = Set; + } + /// Marker types for field names + #[allow(non_camel_case_types)] + pub mod members { + ///Marker type for the `livestream` field + pub struct livestream(()); + } +} + +/// Builder for constructing an instance of this type. +pub struct FinalizeLivestreamBuilder { + _state: PhantomData St>, + _fields: (Option>,), + _type: PhantomData S>, +} + +impl FinalizeLivestream { + /// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed + pub fn new() -> FinalizeLivestreamBuilder { + FinalizeLivestreamBuilder::new() + } +} + +impl FinalizeLivestream { + /// Create a new builder for this type + pub fn builder() -> FinalizeLivestreamBuilder { + FinalizeLivestreamBuilder::builder() + } +} + +impl FinalizeLivestreamBuilder { + /// Create a new builder with all fields unset, using the default string type, if needed + pub fn new() -> Self { + FinalizeLivestreamBuilder { + _state: PhantomData, + _fields: (None,), + _type: PhantomData, + } + } +} + +impl FinalizeLivestreamBuilder { + /// Create a new builder with all fields unset + pub fn builder() -> Self { + FinalizeLivestreamBuilder { + _state: PhantomData, + _fields: (None,), + _type: PhantomData, + } + } +} + +impl FinalizeLivestreamBuilder +where + St: finalize_livestream_state::State, + St::Livestream: finalize_livestream_state::IsUnset, +{ + /// Set the `livestream` field (required) + pub fn livestream( + mut self, + value: impl Into>, + ) -> FinalizeLivestreamBuilder, S> { + self._fields.0 = Option::Some(value.into()); + FinalizeLivestreamBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl FinalizeLivestreamBuilder +where + St: finalize_livestream_state::State, + St::Livestream: finalize_livestream_state::IsSet, +{ + /// Build the final struct. + pub fn build(self) -> FinalizeLivestream { + FinalizeLivestream { + livestream: self._fields.0.unwrap(), + extra_data: Default::default(), + } + } + /// Build the final struct with custom extra_data. + pub fn build_with_data(self, extra_data: BTreeMap>) -> FinalizeLivestream { + FinalizeLivestream { + livestream: self._fields.0.unwrap(), + extra_data: Some(extra_data), + } + } +} diff --git a/crates/jacquard-api/src/place_stream/server.rs b/crates/jacquard-api/src/place_stream/server.rs index c71eeaa61..87341c2e1 100644 --- a/crates/jacquard-api/src/place_stream/server.rs +++ b/crates/jacquard-api/src/place_stream/server.rs @@ -201,6 +201,18 @@ impl LexiconSchema for Webhook { }); } } + if let Some(values) = &self.mute_words { + for value in values { + #[allow(unused_comparisons)] + if ::len(value.as_ref()) > 100usize { + return Err(ConstraintError::MaxLength { + path: ValidationPath::from_field("mute_words"), + max: 100usize, + actual: ::len(value.as_ref()), + }); + } + } + } if let Some(ref value) = self.name { #[allow(unused_comparisons)] if ::len(value.as_ref()) > 100usize { diff --git a/crates/jacquard-api/src/place_stream/server/settings.rs b/crates/jacquard-api/src/place_stream/server/settings.rs index c5df7adea..d66266a81 100644 --- a/crates/jacquard-api/src/place_stream/server/settings.rs +++ b/crates/jacquard-api/src/place_stream/server/settings.rs @@ -40,6 +40,9 @@ pub struct Settings { ///Whether this node may archive your livestream for improving the service #[serde(skip_serializing_if = "Option::is_none")] pub debug_recording: Option, + ///Whether this node should record your livestreams into VODs that you can publish + #[serde(skip_serializing_if = "Option::is_none")] + pub livestream_recording: Option, #[serde(flatten, default, skip_serializing_if = "Option::is_none")] pub extra_data: Option>>, } @@ -125,7 +128,7 @@ pub mod settings_state { /// Builder for constructing an instance of this type. pub struct SettingsBuilder { _state: PhantomData St>, - _fields: (Option,), + _fields: (Option, Option), _type: PhantomData S>, } @@ -148,7 +151,7 @@ impl SettingsBuilder { pub fn new() -> Self { SettingsBuilder { _state: PhantomData, - _fields: (None,), + _fields: (None, None), _type: PhantomData, } } @@ -159,7 +162,7 @@ impl SettingsBuilder { pub fn builder() -> Self { SettingsBuilder { _state: PhantomData, - _fields: (None,), + _fields: (None, None), _type: PhantomData, } } @@ -178,6 +181,19 @@ impl SettingsBuilder { } } +impl SettingsBuilder { + /// Set the `livestreamRecording` field (optional) + pub fn livestream_recording(mut self, value: impl Into>) -> Self { + self._fields.1 = value.into(); + self + } + /// Set the `livestreamRecording` field to an Option value (optional) + pub fn maybe_livestream_recording(mut self, value: Option) -> Self { + self._fields.1 = value; + self + } +} + impl SettingsBuilder where St: settings_state::State, @@ -186,6 +202,7 @@ where pub fn build(self) -> Settings { Settings { debug_recording: self._fields.0, + livestream_recording: self._fields.1, extra_data: Default::default(), } } @@ -193,6 +210,7 @@ where pub fn build_with_data(self, extra_data: BTreeMap>) -> Settings { Settings { debug_recording: self._fields.0, + livestream_recording: self._fields.1, extra_data: Some(extra_data), } } @@ -216,7 +234,6 @@ fn lexicon_doc_place_stream_server_settings() -> LexiconDoc<'static> { )), key: Some(CowStr::new_static("any")), record: LexRecordRecord::Object(LexObject { - required: Some(vec![]), properties: { #[allow(unused_mut)] let mut map = BTreeMap::new(); @@ -226,6 +243,12 @@ fn lexicon_doc_place_stream_server_settings() -> LexiconDoc<'static> { ..Default::default() }), ); + map.insert( + SmolStr::new_static("livestreamRecording"), + LexObjectProperty::Boolean(LexBoolean { + ..Default::default() + }), + ); map }, ..Default::default() diff --git a/crates/jacquard-api/src/place_stream/video.rs b/crates/jacquard-api/src/place_stream/video.rs index a8d4f6d84..95b1e9a46 100644 --- a/crates/jacquard-api/src/place_stream/video.rs +++ b/crates/jacquard-api/src/place_stream/video.rs @@ -218,6 +218,32 @@ impl LexiconSchema for Video { }); } } + if let Some(values) = &self.tags { + for value in values { + #[allow(unused_comparisons)] + if ::len(value.as_ref()) > 640usize { + return Err(ConstraintError::MaxLength { + path: ValidationPath::from_field("tags"), + max: 640usize, + actual: ::len(value.as_ref()), + }); + } + } + } + if let Some(values) = &self.tags { + for value in values { + { + let count = UnicodeSegmentation::graphemes(value.as_ref(), true).count(); + if count > 64usize { + return Err(ConstraintError::MaxGraphemes { + path: ValidationPath::from_field("tags"), + max: 64usize, + actual: count, + }); + } + } + } + } if let Some(ref value) = self.thumb { { let size = value.blob().size; diff --git a/crates/jacquard-api/src/place_stream/vod.rs b/crates/jacquard-api/src/place_stream/vod.rs index dee8d7a69..7f31ce652 100644 --- a/crates/jacquard-api/src/place_stream/vod.rs +++ b/crates/jacquard-api/src/place_stream/vod.rs @@ -7,8 +7,16 @@ //! Generated bindings for the `place.stream.vod` Lexicon namespace/module. pub mod comment; +pub mod create_draft; +pub mod delete_draft; +pub mod draft_defs; +pub mod draft_video; pub mod gate; pub mod get_comments; +pub mod get_draft; +pub mod list_drafts; +pub mod publish_draft; +pub mod update_draft; #[allow(unused_imports)] use alloc::collections::BTreeMap; diff --git a/crates/jacquard-api/src/place_stream/vod/create_draft.rs b/crates/jacquard-api/src/place_stream/vod/create_draft.rs new file mode 100644 index 000000000..3d93f69c7 --- /dev/null +++ b/crates/jacquard-api/src/place_stream/vod/create_draft.rs @@ -0,0 +1,69 @@ +// @generated by jacquard-lexicon. DO NOT EDIT. +// +// Lexicon: place.stream.vod.createDraft +// +// 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::deps::smol_str::SmolStr; +use jacquard_common::types::value::Data; +use jacquard_common::{BosStr, CowStr, DefaultStr, FromStaticStr}; +use jacquard_derive::IntoStatic; +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic, Default)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct CreateDraft { + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic, Default)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct CreateDraftOutput { + ///The ats:// URI of the newly created draft record. + pub uri: S, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +/** Response marker for the `place.stream.vod.createDraft` procedure. + +Implements `jacquard_common::xrpc::XrpcResp`; successful bodies decode as `Self::Output`, which is `CreateDraftOutput` for this endpoint.*/ +pub struct CreateDraftResponse; +impl jacquard_common::xrpc::XrpcResp for CreateDraftResponse { + const NSID: &'static str = "place.stream.vod.createDraft"; + const ENCODING: &'static str = "application/json"; + type Output = CreateDraftOutput; + type Err = jacquard_common::xrpc::GenericError; +} + +impl jacquard_common::xrpc::XrpcRequest for CreateDraft { + const NSID: &'static str = "place.stream.vod.createDraft"; + const METHOD: jacquard_common::xrpc::XrpcMethod = + jacquard_common::xrpc::XrpcMethod::Procedure("application/json"); + type Response = CreateDraftResponse; +} + +/** Endpoint marker for the `place.stream.vod.createDraft` procedure. + +Path: `/xrpc/place.stream.vod.createDraft`. The request payload type is `CreateDraft`; send that request with `jacquard::Client` or use this marker through lower-level `XrpcEndpoint` APIs.*/ +pub struct CreateDraftRequest; +impl jacquard_common::xrpc::XrpcEndpoint for CreateDraftRequest { + const PATH: &'static str = "/xrpc/place.stream.vod.createDraft"; + const METHOD: jacquard_common::xrpc::XrpcMethod = + jacquard_common::xrpc::XrpcMethod::Procedure("application/json"); + type Request = CreateDraft; + type Response = CreateDraftResponse; +} diff --git a/crates/jacquard-api/src/place_stream/vod/delete_draft.rs b/crates/jacquard-api/src/place_stream/vod/delete_draft.rs new file mode 100644 index 000000000..68ce663a5 --- /dev/null +++ b/crates/jacquard-api/src/place_stream/vod/delete_draft.rs @@ -0,0 +1,106 @@ +// @generated by jacquard-lexicon. DO NOT EDIT. +// +// Lexicon: place.stream.vod.deleteDraft +// +// 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::deps::smol_str::SmolStr; +use jacquard_common::types::value::Data; +use jacquard_common::{BosStr, CowStr, DefaultStr, FromStaticStr}; +use jacquard_derive::{IntoStatic, open_union}; +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic, Default)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct DeleteDraft { + ///The ats:// URI of the draft to discard. + pub uri: S, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic, Default)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct DeleteDraftOutput { + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +#[derive( + Serialize, Deserialize, Debug, Clone, PartialEq, Eq, thiserror::Error, miette::Diagnostic, +)] +#[serde(tag = "error", content = "message")] +pub enum DeleteDraftError { + /// No draft exists with the given URI for the authenticated user. + #[serde(rename = "NotFound")] + NotFound(Option), + /// Catch-all for unknown error codes. + #[serde(untagged)] + Other { + error: SmolStr, + message: Option, + }, +} + +impl core::fmt::Display for DeleteDraftError { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + match self { + Self::NotFound(msg) => { + write!(f, "NotFound")?; + if let Some(msg) = msg { + write!(f, ": {}", msg)?; + } + Ok(()) + } + Self::Other { error, message } => { + write!(f, "{}", error)?; + if let Some(msg) = message { + write!(f, ": {}", msg)?; + } + Ok(()) + } + } + } +} + +/** Response marker for the `place.stream.vod.deleteDraft` procedure. + +Implements `jacquard_common::xrpc::XrpcResp`; successful bodies decode as `Self::Output`, which is `DeleteDraftOutput` for this endpoint.*/ +pub struct DeleteDraftResponse; +impl jacquard_common::xrpc::XrpcResp for DeleteDraftResponse { + const NSID: &'static str = "place.stream.vod.deleteDraft"; + const ENCODING: &'static str = "application/json"; + type Output = DeleteDraftOutput; + type Err = DeleteDraftError; +} + +impl jacquard_common::xrpc::XrpcRequest for DeleteDraft { + const NSID: &'static str = "place.stream.vod.deleteDraft"; + const METHOD: jacquard_common::xrpc::XrpcMethod = + jacquard_common::xrpc::XrpcMethod::Procedure("application/json"); + type Response = DeleteDraftResponse; +} + +/** Endpoint marker for the `place.stream.vod.deleteDraft` procedure. + +Path: `/xrpc/place.stream.vod.deleteDraft`. The request payload type is `DeleteDraft`; send that request with `jacquard::Client` or use this marker through lower-level `XrpcEndpoint` APIs.*/ +pub struct DeleteDraftRequest; +impl jacquard_common::xrpc::XrpcEndpoint for DeleteDraftRequest { + const PATH: &'static str = "/xrpc/place.stream.vod.deleteDraft"; + const METHOD: jacquard_common::xrpc::XrpcMethod = + jacquard_common::xrpc::XrpcMethod::Procedure("application/json"); + type Request = DeleteDraft; + type Response = DeleteDraftResponse; +} diff --git a/crates/jacquard-api/src/place_stream/vod/draft_defs.rs b/crates/jacquard-api/src/place_stream/vod/draft_defs.rs new file mode 100644 index 000000000..fa01c809c --- /dev/null +++ b/crates/jacquard-api/src/place_stream/vod/draft_defs.rs @@ -0,0 +1,300 @@ +// @generated by jacquard-lexicon. DO NOT EDIT. +// +// Lexicon: place.stream.vod.draftDefs +// +// 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::value::Data; +use jacquard_derive::IntoStatic; +use jacquard_lexicon::lexicon::LexiconDoc; +use jacquard_lexicon::schema::LexiconSchema; + +#[allow(unused_imports)] +use jacquard_lexicon::validation::{ConstraintError, ValidationPath}; +use serde::{Deserialize, Serialize}; +/// A draft VOD with its ats:// URI and CID, for list/get responses. + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct DraftView { + ///CID (sha256 of CBOR record bytes, base32) of the draft record. + pub cid: S, + ///The place.stream.vod.draftVideo record body. Typed as unknown (matching commentView/livestreamView/videoView) because the @atproto/api client validator cannot validate a ref to a record-type lexicon. + pub record: Data, + ///The ats:// URI of the draft record. + pub uri: S, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +impl LexiconSchema for DraftView { + fn nsid() -> &'static str { + "place.stream.vod.draftDefs" + } + fn def_name() -> &'static str { + "draftView" + } + fn lexicon_doc() -> LexiconDoc<'static> { + lexicon_doc_place_stream_vod_draftDefs() + } + fn validate(&self) -> Result<(), ConstraintError> { + Ok(()) + } +} + +pub mod draft_view_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 Cid; + type Record; + type Uri; + } + /// Empty state - all required fields are unset + pub struct Empty(()); + impl sealed::Sealed for Empty {} + impl State for Empty { + type Cid = Unset; + type Record = Unset; + type Uri = Unset; + } + ///State transition - sets the `cid` field to Set + pub struct SetCid(PhantomData St>); + impl sealed::Sealed for SetCid {} + impl State for SetCid { + type Cid = Set; + type Record = St::Record; + type Uri = St::Uri; + } + ///State transition - sets the `record` field to Set + pub struct SetRecord(PhantomData St>); + impl sealed::Sealed for SetRecord {} + impl State for SetRecord { + type Cid = St::Cid; + type Record = Set; + type Uri = St::Uri; + } + ///State transition - sets the `uri` field to Set + pub struct SetUri(PhantomData St>); + impl sealed::Sealed for SetUri {} + impl State for SetUri { + type Cid = St::Cid; + type Record = St::Record; + type Uri = Set; + } + /// Marker types for field names + #[allow(non_camel_case_types)] + pub mod members { + ///Marker type for the `cid` field + pub struct cid(()); + ///Marker type for the `record` field + pub struct record(()); + ///Marker type for the `uri` field + pub struct uri(()); + } +} + +/// Builder for constructing an instance of this type. +pub struct DraftViewBuilder { + _state: PhantomData St>, + _fields: (Option, Option>, Option), + _type: PhantomData S>, +} + +impl DraftView { + /// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed + pub fn new() -> DraftViewBuilder { + DraftViewBuilder::new() + } +} + +impl DraftView { + /// Create a new builder for this type + pub fn builder() -> DraftViewBuilder { + DraftViewBuilder::builder() + } +} + +impl DraftViewBuilder { + /// Create a new builder with all fields unset, using the default string type, if needed + pub fn new() -> Self { + DraftViewBuilder { + _state: PhantomData, + _fields: (None, None, None), + _type: PhantomData, + } + } +} + +impl DraftViewBuilder { + /// Create a new builder with all fields unset + pub fn builder() -> Self { + DraftViewBuilder { + _state: PhantomData, + _fields: (None, None, None), + _type: PhantomData, + } + } +} + +impl DraftViewBuilder +where + St: draft_view_state::State, + St::Cid: draft_view_state::IsUnset, +{ + /// Set the `cid` field (required) + pub fn cid(mut self, value: impl Into) -> DraftViewBuilder, S> { + self._fields.0 = Option::Some(value.into()); + DraftViewBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl DraftViewBuilder +where + St: draft_view_state::State, + St::Record: draft_view_state::IsUnset, +{ + /// Set the `record` field (required) + pub fn record( + mut self, + value: impl Into>, + ) -> DraftViewBuilder, S> { + self._fields.1 = Option::Some(value.into()); + DraftViewBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl DraftViewBuilder +where + St: draft_view_state::State, + St::Uri: draft_view_state::IsUnset, +{ + /// Set the `uri` field (required) + pub fn uri(mut self, value: impl Into) -> DraftViewBuilder, S> { + self._fields.2 = Option::Some(value.into()); + DraftViewBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl DraftViewBuilder +where + St: draft_view_state::State, + St::Cid: draft_view_state::IsSet, + St::Record: draft_view_state::IsSet, + St::Uri: draft_view_state::IsSet, +{ + /// Build the final struct. + pub fn build(self) -> DraftView { + DraftView { + cid: self._fields.0.unwrap(), + record: self._fields.1.unwrap(), + uri: 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>) -> DraftView { + DraftView { + cid: self._fields.0.unwrap(), + record: self._fields.1.unwrap(), + uri: self._fields.2.unwrap(), + extra_data: Some(extra_data), + } + } +} + +fn lexicon_doc_place_stream_vod_draftDefs() -> 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("place.stream.vod.draftDefs"), + defs: { + let mut map = BTreeMap::new(); + map.insert( + SmolStr::new_static("draftView"), + LexUserType::Object(LexObject { + description: Some( + CowStr::new_static( + "A draft VOD with its ats:// URI and CID, for list/get responses.", + ), + ), + required: Some( + vec![ + SmolStr::new_static("uri"), SmolStr::new_static("cid"), + SmolStr::new_static("record") + ], + ), + properties: { + #[allow(unused_mut)] + let mut map = BTreeMap::new(); + map.insert( + SmolStr::new_static("cid"), + LexObjectProperty::String(LexString { + description: Some( + CowStr::new_static( + "CID (sha256 of CBOR record bytes, base32) of the draft record.", + ), + ), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("record"), + LexObjectProperty::Unknown(LexUnknown { + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("uri"), + LexObjectProperty::String(LexString { + description: Some( + CowStr::new_static("The ats:// URI of the draft record."), + ), + ..Default::default() + }), + ); + map + }, + ..Default::default() + }), + ); + map + }, + ..Default::default() + } +} diff --git a/crates/jacquard-api/src/place_stream/vod/draft_video.rs b/crates/jacquard-api/src/place_stream/vod/draft_video.rs new file mode 100644 index 000000000..13069774f --- /dev/null +++ b/crates/jacquard-api/src/place_stream/vod/draft_video.rs @@ -0,0 +1,935 @@ +// @generated by jacquard-lexicon. DO NOT EDIT. +// +// Lexicon: place.stream.vod.draftVideo +// +// 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::blob::BlobRef; +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, open_union}; +use jacquard_lexicon::lexicon::LexiconDoc; +use jacquard_lexicon::schema::LexiconSchema; + +use crate::place_stream::ActivityGame; +use crate::place_stream::ActivityLabel; +use crate::place_stream::media::SourceClip; +use crate::place_stream::media::SourceTracks; +use crate::place_stream::metadata::content_rights::ContentRights; +use crate::place_stream::metadata::content_warnings::ContentWarnings; +use crate::place_stream::richtext::video_facet::VideoFacet; +use crate::place_stream::video::Connection; +#[allow(unused_imports)] +use jacquard_lexicon::validation::{ConstraintError, ValidationPath}; +use serde::{Deserialize, Serialize}; +/// A draft VOD: pre-publication video metadata and processing state. Modeled as a permissioned-data-style record (CBOR-serialized, addressed by an ats:// URI) stored in statedb until the permissioned-data spec ships (bluesky-social/proposals PR #94, the 0016-permissioned-data proposal). Publishing promotes it to a public place.stream.video record. + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + rename = "place.stream.vod.draftVideo", + tag = "$type", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct DraftVideo { + ///The game or activity in the video. + #[serde(skip_serializing_if = "Option::is_none")] + pub activity: Option>, + ///Related records (e.g. the source livestream for a finalized VOD). + #[serde(skip_serializing_if = "Option::is_none")] + pub connections: Option>>, + #[serde(skip_serializing_if = "Option::is_none")] + pub content_rights: Option>, + #[serde(skip_serializing_if = "Option::is_none")] + pub content_warnings: Option>, + pub created_at: Datetime, + ///Description of the video. + #[serde(skip_serializing_if = "Option::is_none")] + pub description: Option, + ///Annotations of text (mentions, URLs, etc). + #[serde(skip_serializing_if = "Option::is_none")] + pub description_facets: Option>>, + ///Duration in milliseconds. Filled when status is 'ready'. + #[serde(skip_serializing_if = "Option::is_none")] + pub duration_ms: Option, + ///Error message when status is 'error'. + #[serde(skip_serializing_if = "Option::is_none")] + pub error: Option, + ///Source tracks. Filled by the server when processing completes (status 'ready'). + #[serde(skip_serializing_if = "Option::is_none")] + pub source: Option>, + ///Processing state: 'processing' while the job runs, 'ready' when publishable, 'error' if processing failed. + pub status: DraftVideoStatus, + ///Freeform tags (same rules as place.stream.video). + #[serde(skip_serializing_if = "Option::is_none")] + pub tags: Option>, + ///Thumbnail image. Generated by the server at publish time if absent. + #[serde(skip_serializing_if = "Option::is_none")] + pub thumb: Option>, + ///Title of the video. May be a placeholder while processing; the user edits before publishing. + pub title: S, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +#[open_union] +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde(tag = "$type", bound(deserialize = "S: Deserialize<'de> + BosStr"))] +pub enum DraftVideoActivity { + #[serde(rename = "place.stream.defs#activityGame")] + ActivityGame(Box>), + #[serde(rename = "place.stream.defs#activityLabel")] + ActivityLabel(Box>), +} + +#[open_union] +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde(tag = "$type", bound(deserialize = "S: Deserialize<'de> + BosStr"))] +pub enum DraftVideoSource { + #[serde(rename = "place.stream.media.defs#sourceTracks")] + SourceTracks(Box>), + #[serde(rename = "place.stream.media.defs#sourceClip")] + SourceClip(Box>), +} + +/// Processing state: 'processing' while the job runs, 'ready' when publishable, 'error' if processing failed. + +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub enum DraftVideoStatus { + Processing, + Ready, + Error, + Other(S), +} + +impl DraftVideoStatus { + pub fn as_str(&self) -> &str { + match self { + Self::Processing => "processing", + Self::Ready => "ready", + Self::Error => "error", + 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() { + "processing" => Self::Processing, + "ready" => Self::Ready, + "error" => Self::Error, + _ => Self::Other(s), + } + } +} + +impl core::fmt::Display for DraftVideoStatus { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!(f, "{}", self.as_str()) + } +} + +impl AsRef for DraftVideoStatus { + fn as_ref(&self) -> &str { + self.as_str() + } +} + +impl Serialize for DraftVideoStatus { + 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 DraftVideoStatus { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = S::deserialize(deserializer)?; + Ok(Self::from_value(s)) + } +} + +impl Default for DraftVideoStatus { + fn default() -> Self { + Self::Other(Default::default()) + } +} + +impl jacquard_common::IntoStatic for DraftVideoStatus +where + S: BosStr + jacquard_common::IntoStatic, + S::Output: BosStr, +{ + type Output = DraftVideoStatus; + fn into_static(self) -> Self::Output { + match self { + DraftVideoStatus::Processing => DraftVideoStatus::Processing, + DraftVideoStatus::Ready => DraftVideoStatus::Ready, + DraftVideoStatus::Error => DraftVideoStatus::Error, + DraftVideoStatus::Other(v) => DraftVideoStatus::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 DraftVideoGetRecordOutput { + #[serde(skip_serializing_if = "Option::is_none")] + pub cid: Option>, + pub uri: AtUri, + pub value: DraftVideo, +} + +impl DraftVideo { + 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 DraftVideoRecord; +impl XrpcResp for DraftVideoRecord { + const NSID: &'static str = "place.stream.vod.draftVideo"; + const ENCODING: &'static str = "application/json"; + type Output = DraftVideoGetRecordOutput; + type Err = RecordError; +} + +impl From> for DraftVideo { + fn from(output: DraftVideoGetRecordOutput) -> Self { + output.value + } +} + +impl Collection for DraftVideo { + const NSID: &'static str = "place.stream.vod.draftVideo"; + type Record = DraftVideoRecord; +} + +impl Collection for DraftVideoRecord { + const NSID: &'static str = "place.stream.vod.draftVideo"; + type Record = DraftVideoRecord; +} + +impl LexiconSchema for DraftVideo { + fn nsid() -> &'static str { + "place.stream.vod.draftVideo" + } + fn def_name() -> &'static str { + "main" + } + fn lexicon_doc() -> LexiconDoc<'static> { + lexicon_doc_place_stream_vod_draftVideo() + } + fn validate(&self) -> Result<(), ConstraintError> { + if let Some(ref value) = self.description { + #[allow(unused_comparisons)] + if ::len(value.as_ref()) > 50000usize { + return Err(ConstraintError::MaxLength { + path: ValidationPath::from_field("description"), + max: 50000usize, + actual: ::len(value.as_ref()), + }); + } + } + if let Some(ref value) = self.description { + { + let count = UnicodeSegmentation::graphemes(value.as_ref(), true).count(); + if count > 5000usize { + return Err(ConstraintError::MaxGraphemes { + path: ValidationPath::from_field("description"), + max: 5000usize, + actual: count, + }); + } + } + } + if let Some(ref value) = self.tags { + #[allow(unused_comparisons)] + if value.len() > 10usize { + return Err(ConstraintError::MaxLength { + path: ValidationPath::from_field("tags"), + max: 10usize, + actual: value.len(), + }); + } + } + if let Some(values) = &self.tags { + for value in values { + #[allow(unused_comparisons)] + if ::len(value.as_ref()) > 640usize { + return Err(ConstraintError::MaxLength { + path: ValidationPath::from_field("tags"), + max: 640usize, + actual: ::len(value.as_ref()), + }); + } + } + } + if let Some(values) = &self.tags { + for value in values { + { + let count = UnicodeSegmentation::graphemes(value.as_ref(), true).count(); + if count > 64usize { + return Err(ConstraintError::MaxGraphemes { + path: ValidationPath::from_field("tags"), + max: 64usize, + actual: count, + }); + } + } + } + } + if let Some(ref value) = self.thumb { + { + let size = value.blob().size; + if size > 1000000usize { + return Err(ConstraintError::BlobTooLarge { + path: ValidationPath::from_field("thumb"), + max: 1000000usize, + actual: size, + }); + } + } + } + if let Some(ref value) = self.thumb { + { + let mime = value.blob().mime_type.as_str(); + let accepted: &[&str] = &["image/*"]; + let matched = accepted.iter().any(|pattern| { + if *pattern == "*/*" { + true + } else if pattern.ends_with("/*") { + let prefix = &pattern[..pattern.len() - 2]; + mime.starts_with(prefix) && mime.as_bytes().get(prefix.len()) == Some(&b'/') + } else { + mime == *pattern + } + }); + if !matched { + return Err(ConstraintError::BlobMimeTypeNotAccepted { + path: ValidationPath::from_field("thumb"), + accepted: vec!["image/*".to_string()], + actual: mime.to_string(), + }); + } + } + } + { + let value = &self.title; + #[allow(unused_comparisons)] + if ::len(value.as_ref()) > 1400usize { + return Err(ConstraintError::MaxLength { + path: ValidationPath::from_field("title"), + max: 1400usize, + actual: ::len(value.as_ref()), + }); + } + } + { + let value = &self.title; + { + let count = UnicodeSegmentation::graphemes(value.as_ref(), true).count(); + if count > 140usize { + return Err(ConstraintError::MaxGraphemes { + path: ValidationPath::from_field("title"), + max: 140usize, + actual: count, + }); + } + } + } + Ok(()) + } +} + +pub mod draft_video_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 Status; + 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 Status = 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 Status = St::Status; + type Title = St::Title; + } + ///State transition - sets the `status` field to Set + pub struct SetStatus(PhantomData St>); + impl sealed::Sealed for SetStatus {} + impl State for SetStatus { + type CreatedAt = St::CreatedAt; + type Status = 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 Status = St::Status; + 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 `status` field + pub struct status(()); + ///Marker type for the `title` field + pub struct title(()); + } +} + +/// Builder for constructing an instance of this type. +pub struct DraftVideoBuilder { + _state: PhantomData St>, + _fields: ( + Option>, + Option>>, + Option>, + Option>, + Option, + Option, + Option>>, + Option, + Option, + Option>, + Option>, + Option>, + Option>, + Option, + ), + _type: PhantomData S>, +} + +impl DraftVideo { + /// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed + pub fn new() -> DraftVideoBuilder { + DraftVideoBuilder::new() + } +} + +impl DraftVideo { + /// Create a new builder for this type + pub fn builder() -> DraftVideoBuilder { + DraftVideoBuilder::builder() + } +} + +impl DraftVideoBuilder { + /// Create a new builder with all fields unset, using the default string type, if needed + pub fn new() -> Self { + DraftVideoBuilder { + _state: PhantomData, + _fields: ( + None, None, None, None, None, None, None, None, None, None, None, None, None, None, + ), + _type: PhantomData, + } + } +} + +impl DraftVideoBuilder { + /// Create a new builder with all fields unset + pub fn builder() -> Self { + DraftVideoBuilder { + _state: PhantomData, + _fields: ( + None, None, None, None, None, None, None, None, None, None, None, None, None, None, + ), + _type: PhantomData, + } + } +} + +impl DraftVideoBuilder { + /// Set the `activity` field (optional) + pub fn activity(mut self, value: impl Into>>) -> Self { + self._fields.0 = value.into(); + self + } + /// Set the `activity` field to an Option value (optional) + pub fn maybe_activity(mut self, value: Option>) -> Self { + self._fields.0 = value; + self + } +} + +impl DraftVideoBuilder { + /// Set the `connections` field (optional) + pub fn connections(mut self, value: impl Into>>>) -> Self { + self._fields.1 = value.into(); + self + } + /// Set the `connections` field to an Option value (optional) + pub fn maybe_connections(mut self, value: Option>>) -> Self { + self._fields.1 = value; + self + } +} + +impl DraftVideoBuilder { + /// Set the `contentRights` field (optional) + pub fn content_rights(mut self, value: impl Into>>) -> Self { + self._fields.2 = value.into(); + self + } + /// Set the `contentRights` field to an Option value (optional) + pub fn maybe_content_rights(mut self, value: Option>) -> Self { + self._fields.2 = value; + self + } +} + +impl DraftVideoBuilder { + /// Set the `contentWarnings` field (optional) + pub fn content_warnings(mut self, value: impl Into>>) -> Self { + self._fields.3 = value.into(); + self + } + /// Set the `contentWarnings` field to an Option value (optional) + pub fn maybe_content_warnings(mut self, value: Option>) -> Self { + self._fields.3 = value; + self + } +} + +impl DraftVideoBuilder +where + St: draft_video_state::State, + St::CreatedAt: draft_video_state::IsUnset, +{ + /// Set the `createdAt` field (required) + pub fn created_at( + mut self, + value: impl Into, + ) -> DraftVideoBuilder, S> { + self._fields.4 = Option::Some(value.into()); + DraftVideoBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl DraftVideoBuilder { + /// Set the `description` field (optional) + pub fn description(mut self, value: impl Into>) -> Self { + self._fields.5 = value.into(); + self + } + /// Set the `description` field to an Option value (optional) + pub fn maybe_description(mut self, value: Option) -> Self { + self._fields.5 = value; + self + } +} + +impl DraftVideoBuilder { + /// Set the `descriptionFacets` field (optional) + pub fn description_facets(mut self, value: impl Into>>>) -> Self { + self._fields.6 = value.into(); + self + } + /// Set the `descriptionFacets` field to an Option value (optional) + pub fn maybe_description_facets(mut self, value: Option>>) -> Self { + self._fields.6 = value; + self + } +} + +impl DraftVideoBuilder { + /// Set the `durationMs` field (optional) + pub fn duration_ms(mut self, value: impl Into>) -> Self { + self._fields.7 = value.into(); + self + } + /// Set the `durationMs` field to an Option value (optional) + pub fn maybe_duration_ms(mut self, value: Option) -> Self { + self._fields.7 = value; + self + } +} + +impl DraftVideoBuilder { + /// Set the `error` field (optional) + pub fn error(mut self, value: impl Into>) -> Self { + self._fields.8 = value.into(); + self + } + /// Set the `error` field to an Option value (optional) + pub fn maybe_error(mut self, value: Option) -> Self { + self._fields.8 = value; + self + } +} + +impl DraftVideoBuilder { + /// Set the `source` field (optional) + pub fn source(mut self, value: impl Into>>) -> Self { + self._fields.9 = value.into(); + self + } + /// Set the `source` field to an Option value (optional) + pub fn maybe_source(mut self, value: Option>) -> Self { + self._fields.9 = value; + self + } +} + +impl DraftVideoBuilder +where + St: draft_video_state::State, + St::Status: draft_video_state::IsUnset, +{ + /// Set the `status` field (required) + pub fn status( + mut self, + value: impl Into>, + ) -> DraftVideoBuilder, S> { + self._fields.10 = Option::Some(value.into()); + DraftVideoBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl DraftVideoBuilder { + /// Set the `tags` field (optional) + pub fn tags(mut self, value: impl Into>>) -> Self { + self._fields.11 = value.into(); + self + } + /// Set the `tags` field to an Option value (optional) + pub fn maybe_tags(mut self, value: Option>) -> Self { + self._fields.11 = value; + self + } +} + +impl DraftVideoBuilder { + /// Set the `thumb` field (optional) + pub fn thumb(mut self, value: impl Into>>) -> Self { + self._fields.12 = value.into(); + self + } + /// Set the `thumb` field to an Option value (optional) + pub fn maybe_thumb(mut self, value: Option>) -> Self { + self._fields.12 = value; + self + } +} + +impl DraftVideoBuilder +where + St: draft_video_state::State, + St::Title: draft_video_state::IsUnset, +{ + /// Set the `title` field (required) + pub fn title( + mut self, + value: impl Into, + ) -> DraftVideoBuilder, S> { + self._fields.13 = Option::Some(value.into()); + DraftVideoBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl DraftVideoBuilder +where + St: draft_video_state::State, + St::CreatedAt: draft_video_state::IsSet, + St::Status: draft_video_state::IsSet, + St::Title: draft_video_state::IsSet, +{ + /// Build the final struct. + pub fn build(self) -> DraftVideo { + DraftVideo { + activity: self._fields.0, + connections: self._fields.1, + content_rights: self._fields.2, + content_warnings: self._fields.3, + created_at: self._fields.4.unwrap(), + description: self._fields.5, + description_facets: self._fields.6, + duration_ms: self._fields.7, + error: self._fields.8, + source: self._fields.9, + status: self._fields.10.unwrap(), + tags: self._fields.11, + thumb: self._fields.12, + title: self._fields.13.unwrap(), + extra_data: Default::default(), + } + } + /// Build the final struct with custom extra_data. + pub fn build_with_data(self, extra_data: BTreeMap>) -> DraftVideo { + DraftVideo { + activity: self._fields.0, + connections: self._fields.1, + content_rights: self._fields.2, + content_warnings: self._fields.3, + created_at: self._fields.4.unwrap(), + description: self._fields.5, + description_facets: self._fields.6, + duration_ms: self._fields.7, + error: self._fields.8, + source: self._fields.9, + status: self._fields.10.unwrap(), + tags: self._fields.11, + thumb: self._fields.12, + title: self._fields.13.unwrap(), + extra_data: Some(extra_data), + } + } +} + +fn lexicon_doc_place_stream_vod_draftVideo() -> 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("place.stream.vod.draftVideo"), + defs: { + let mut map = BTreeMap::new(); + map.insert( + SmolStr::new_static("main"), + LexUserType::Record(LexRecord { + description: Some( + CowStr::new_static( + "A draft VOD: pre-publication video metadata and processing state. Modeled as a permissioned-data-style record (CBOR-serialized, addressed by an ats:// URI) stored in statedb until the permissioned-data spec ships (bluesky-social/proposals PR #94, the 0016-permissioned-data proposal). Publishing promotes it to a public place.stream.video record.", + ), + ), + key: Some(CowStr::new_static("tid")), + record: LexRecordRecord::Object(LexObject { + required: Some( + vec![ + SmolStr::new_static("title"), SmolStr::new_static("status"), + SmolStr::new_static("createdAt") + ], + ), + properties: { + #[allow(unused_mut)] + let mut map = BTreeMap::new(); + map.insert( + SmolStr::new_static("activity"), + LexObjectProperty::Union(LexRefUnion { + description: Some( + CowStr::new_static("The game or activity in the video."), + ), + refs: vec![ + CowStr::new_static("place.stream.defs#activityGame"), + CowStr::new_static("place.stream.defs#activityLabel") + ], + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("connections"), + LexObjectProperty::Array(LexArray { + description: Some( + CowStr::new_static( + "Related records (e.g. the source livestream for a finalized VOD).", + ), + ), + items: LexArrayItem::Union(LexRefUnion { + refs: vec![ + CowStr::new_static("place.stream.video#connection") + ], + ..Default::default() + }), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("contentRights"), + LexObjectProperty::Ref(LexRef { + r#ref: CowStr::new_static( + "place.stream.metadata.contentRights", + ), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("contentWarnings"), + LexObjectProperty::Ref(LexRef { + r#ref: CowStr::new_static( + "place.stream.metadata.contentWarnings", + ), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("createdAt"), + LexObjectProperty::String(LexString { + format: Some(LexStringFormat::Datetime), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("description"), + LexObjectProperty::String(LexString { + description: Some( + CowStr::new_static("Description of the video."), + ), + max_length: Some(50000usize), + max_graphemes: Some(5000usize), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("descriptionFacets"), + LexObjectProperty::Array(LexArray { + description: Some( + CowStr::new_static( + "Annotations of text (mentions, URLs, etc).", + ), + ), + items: LexArrayItem::Ref(LexRef { + r#ref: CowStr::new_static( + "place.stream.richtext.videoFacet", + ), + ..Default::default() + }), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("durationMs"), + LexObjectProperty::Integer(LexInteger { + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("error"), + LexObjectProperty::String(LexString { + description: Some( + CowStr::new_static("Error message when status is 'error'."), + ), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("source"), + LexObjectProperty::Union(LexRefUnion { + description: Some( + CowStr::new_static( + "Source tracks. Filled by the server when processing completes (status 'ready').", + ), + ), + refs: vec![ + CowStr::new_static("place.stream.media.defs#sourceTracks"), + CowStr::new_static("place.stream.media.defs#sourceClip") + ], + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("status"), + LexObjectProperty::String(LexString { + description: Some( + CowStr::new_static( + "Processing state: 'processing' while the job runs, 'ready' when publishable, 'error' if processing failed.", + ), + ), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("tags"), + LexObjectProperty::Array(LexArray { + description: Some( + CowStr::new_static( + "Freeform tags (same rules as place.stream.video).", + ), + ), + items: LexArrayItem::String(LexString { + max_length: Some(640usize), + max_graphemes: Some(64usize), + ..Default::default() + }), + max_length: Some(10usize), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("thumb"), + LexObjectProperty::Blob(LexBlob { ..Default::default() }), + ); + map.insert( + SmolStr::new_static("title"), + LexObjectProperty::String(LexString { + description: Some( + CowStr::new_static( + "Title of the video. May be a placeholder while processing; the user edits before publishing.", + ), + ), + max_length: Some(1400usize), + max_graphemes: Some(140usize), + ..Default::default() + }), + ); + map + }, + ..Default::default() + }), + ..Default::default() + }), + ); + map + }, + ..Default::default() + } +} diff --git a/crates/jacquard-api/src/place_stream/vod/get_draft.rs b/crates/jacquard-api/src/place_stream/vod/get_draft.rs new file mode 100644 index 000000000..5018ffe38 --- /dev/null +++ b/crates/jacquard-api/src/place_stream/vod/get_draft.rs @@ -0,0 +1,207 @@ +// @generated by jacquard-lexicon. DO NOT EDIT. +// +// Lexicon: place.stream.vod.getDraft +// +// 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; + +use crate::place_stream::vod::draft_defs::DraftView; +#[allow(unused_imports)] +use core::marker::PhantomData; +use jacquard_common::deps::smol_str::SmolStr; +use jacquard_common::types::value::Data; +use jacquard_common::{BosStr, CowStr, DefaultStr, FromStaticStr}; +use jacquard_derive::{IntoStatic, open_union}; +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct GetDraft { + pub uri: S, +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct GetDraftOutput { + pub draft: DraftView, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +#[derive( + Serialize, Deserialize, Debug, Clone, PartialEq, Eq, thiserror::Error, miette::Diagnostic, +)] +#[serde(tag = "error", content = "message")] +pub enum GetDraftError { + /// No draft exists with the given URI for the authenticated user. + #[serde(rename = "NotFound")] + NotFound(Option), + /// Catch-all for unknown error codes. + #[serde(untagged)] + Other { + error: SmolStr, + message: Option, + }, +} + +impl core::fmt::Display for GetDraftError { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + match self { + Self::NotFound(msg) => { + write!(f, "NotFound")?; + if let Some(msg) = msg { + write!(f, ": {}", msg)?; + } + Ok(()) + } + Self::Other { error, message } => { + write!(f, "{}", error)?; + if let Some(msg) = message { + write!(f, ": {}", msg)?; + } + Ok(()) + } + } + } +} + +/** Response marker for the `place.stream.vod.getDraft` query. + +Implements `jacquard_common::xrpc::XrpcResp`; successful bodies decode as `Self::Output`, which is `GetDraftOutput` for this endpoint.*/ +pub struct GetDraftResponse; +impl jacquard_common::xrpc::XrpcResp for GetDraftResponse { + const NSID: &'static str = "place.stream.vod.getDraft"; + const ENCODING: &'static str = "application/json"; + type Output = GetDraftOutput; + type Err = GetDraftError; +} + +impl jacquard_common::xrpc::XrpcRequest for GetDraft { + const NSID: &'static str = "place.stream.vod.getDraft"; + const METHOD: jacquard_common::xrpc::XrpcMethod = jacquard_common::xrpc::XrpcMethod::Query; + type Response = GetDraftResponse; +} + +/** Endpoint marker for the `place.stream.vod.getDraft` query. + +Path: `/xrpc/place.stream.vod.getDraft`. The request payload type is `GetDraft`; send that request with `jacquard::Client` or use this marker through lower-level `XrpcEndpoint` APIs.*/ +pub struct GetDraftRequest; +impl jacquard_common::xrpc::XrpcEndpoint for GetDraftRequest { + const PATH: &'static str = "/xrpc/place.stream.vod.getDraft"; + const METHOD: jacquard_common::xrpc::XrpcMethod = jacquard_common::xrpc::XrpcMethod::Query; + type Request = GetDraft; + type Response = GetDraftResponse; +} + +pub mod get_draft_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 Uri; + } + /// Empty state - all required fields are unset + pub struct Empty(()); + impl sealed::Sealed for Empty {} + impl State for Empty { + type Uri = Unset; + } + ///State transition - sets the `uri` field to Set + pub struct SetUri(PhantomData St>); + impl sealed::Sealed for SetUri {} + impl State for SetUri { + type Uri = Set; + } + /// Marker types for field names + #[allow(non_camel_case_types)] + pub mod members { + ///Marker type for the `uri` field + pub struct uri(()); + } +} + +/// Builder for constructing an instance of this type. +pub struct GetDraftBuilder { + _state: PhantomData St>, + _fields: (Option,), + _type: PhantomData S>, +} + +impl GetDraft { + /// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed + pub fn new() -> GetDraftBuilder { + GetDraftBuilder::new() + } +} + +impl GetDraft { + /// Create a new builder for this type + pub fn builder() -> GetDraftBuilder { + GetDraftBuilder::builder() + } +} + +impl GetDraftBuilder { + /// Create a new builder with all fields unset, using the default string type, if needed + pub fn new() -> Self { + GetDraftBuilder { + _state: PhantomData, + _fields: (None,), + _type: PhantomData, + } + } +} + +impl GetDraftBuilder { + /// Create a new builder with all fields unset + pub fn builder() -> Self { + GetDraftBuilder { + _state: PhantomData, + _fields: (None,), + _type: PhantomData, + } + } +} + +impl GetDraftBuilder +where + St: get_draft_state::State, + St::Uri: get_draft_state::IsUnset, +{ + /// Set the `uri` field (required) + pub fn uri(mut self, value: impl Into) -> GetDraftBuilder, S> { + self._fields.0 = Option::Some(value.into()); + GetDraftBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl GetDraftBuilder +where + St: get_draft_state::State, + St::Uri: get_draft_state::IsSet, +{ + /// Build the final struct. + pub fn build(self) -> GetDraft { + GetDraft { + uri: self._fields.0.unwrap(), + } + } +} diff --git a/crates/jacquard-api/src/place_stream/vod/list_drafts.rs b/crates/jacquard-api/src/place_stream/vod/list_drafts.rs new file mode 100644 index 000000000..a27748b20 --- /dev/null +++ b/crates/jacquard-api/src/place_stream/vod/list_drafts.rs @@ -0,0 +1,179 @@ +// @generated by jacquard-lexicon. DO NOT EDIT. +// +// Lexicon: place.stream.vod.listDrafts +// +// 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; + +use crate::place_stream::vod::draft_defs::DraftView; +#[allow(unused_imports)] +use core::marker::PhantomData; +use jacquard_common::deps::smol_str::SmolStr; +use jacquard_common::types::value::Data; +use jacquard_common::{BosStr, CowStr, DefaultStr, FromStaticStr}; +use jacquard_derive::IntoStatic; +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct ListDrafts { + #[serde(skip_serializing_if = "Option::is_none")] + pub cursor: Option, + /// Defaults to `50`. Min: 1. Max: 100. + #[serde(default = "_default_limit")] + #[serde(skip_serializing_if = "Option::is_none")] + pub limit: Option, +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct ListDraftsOutput { + ///Pagination cursor for the next page, if more results exist. + #[serde(skip_serializing_if = "Option::is_none")] + pub cursor: Option, + pub drafts: Vec>, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +/** Response marker for the `place.stream.vod.listDrafts` query. + +Implements `jacquard_common::xrpc::XrpcResp`; successful bodies decode as `Self::Output`, which is `ListDraftsOutput` for this endpoint.*/ +pub struct ListDraftsResponse; +impl jacquard_common::xrpc::XrpcResp for ListDraftsResponse { + const NSID: &'static str = "place.stream.vod.listDrafts"; + const ENCODING: &'static str = "application/json"; + type Output = ListDraftsOutput; + type Err = jacquard_common::xrpc::GenericError; +} + +impl jacquard_common::xrpc::XrpcRequest for ListDrafts { + const NSID: &'static str = "place.stream.vod.listDrafts"; + const METHOD: jacquard_common::xrpc::XrpcMethod = jacquard_common::xrpc::XrpcMethod::Query; + type Response = ListDraftsResponse; +} + +/** Endpoint marker for the `place.stream.vod.listDrafts` query. + +Path: `/xrpc/place.stream.vod.listDrafts`. The request payload type is `ListDrafts`; send that request with `jacquard::Client` or use this marker through lower-level `XrpcEndpoint` APIs.*/ +pub struct ListDraftsRequest; +impl jacquard_common::xrpc::XrpcEndpoint for ListDraftsRequest { + const PATH: &'static str = "/xrpc/place.stream.vod.listDrafts"; + const METHOD: jacquard_common::xrpc::XrpcMethod = jacquard_common::xrpc::XrpcMethod::Query; + type Request = ListDrafts; + type Response = ListDraftsResponse; +} + +fn _default_limit() -> Option { + Some(50i64) +} + +pub mod list_drafts_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 {} + /// Empty state - all required fields are unset + pub struct Empty(()); + impl sealed::Sealed for Empty {} + impl State for Empty {} + /// Marker types for field names + #[allow(non_camel_case_types)] + pub mod members {} +} + +/// Builder for constructing an instance of this type. +pub struct ListDraftsBuilder { + _state: PhantomData St>, + _fields: (Option, Option), + _type: PhantomData S>, +} + +impl ListDrafts { + /// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed + pub fn new() -> ListDraftsBuilder { + ListDraftsBuilder::new() + } +} + +impl ListDrafts { + /// Create a new builder for this type + pub fn builder() -> ListDraftsBuilder { + ListDraftsBuilder::builder() + } +} + +impl ListDraftsBuilder { + /// Create a new builder with all fields unset, using the default string type, if needed + pub fn new() -> Self { + ListDraftsBuilder { + _state: PhantomData, + _fields: (None, None), + _type: PhantomData, + } + } +} + +impl ListDraftsBuilder { + /// Create a new builder with all fields unset + pub fn builder() -> Self { + ListDraftsBuilder { + _state: PhantomData, + _fields: (None, None), + _type: PhantomData, + } + } +} + +impl ListDraftsBuilder { + /// Set the `cursor` field (optional) + pub fn cursor(mut self, value: impl Into>) -> Self { + self._fields.0 = value.into(); + self + } + /// Set the `cursor` field to an Option value (optional) + pub fn maybe_cursor(mut self, value: Option) -> Self { + self._fields.0 = value; + self + } +} + +impl ListDraftsBuilder { + /// Set the `limit` field (optional) + pub fn limit(mut self, value: impl Into>) -> Self { + self._fields.1 = value.into(); + self + } + /// Set the `limit` field to an Option value (optional) + pub fn maybe_limit(mut self, value: Option) -> Self { + self._fields.1 = value; + self + } +} + +impl ListDraftsBuilder +where + St: list_drafts_state::State, +{ + /// Build the final struct. + pub fn build(self) -> ListDrafts { + ListDrafts { + cursor: self._fields.0, + limit: self._fields.1, + } + } +} diff --git a/crates/jacquard-api/src/place_stream/vod/publish_draft.rs b/crates/jacquard-api/src/place_stream/vod/publish_draft.rs new file mode 100644 index 000000000..3d04da446 --- /dev/null +++ b/crates/jacquard-api/src/place_stream/vod/publish_draft.rs @@ -0,0 +1,121 @@ +// @generated by jacquard-lexicon. DO NOT EDIT. +// +// Lexicon: place.stream.vod.publishDraft +// +// 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::deps::smol_str::SmolStr; +use jacquard_common::types::string::{AtUri, Cid}; +use jacquard_common::types::value::Data; +use jacquard_common::{BosStr, CowStr, DefaultStr, FromStaticStr}; +use jacquard_derive::{IntoStatic, open_union}; +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic, Default)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct PublishDraft { + ///The ats:// URI of the draft to publish. Must have status 'ready'. + pub uri: S, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct PublishDraftOutput { + ///CID of the created place.stream.video record. + pub video_cid: Cid, + ///AT-URI of the created place.stream.video record. + pub video_uri: AtUri, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +#[derive( + Serialize, Deserialize, Debug, Clone, PartialEq, Eq, thiserror::Error, miette::Diagnostic, +)] +#[serde(tag = "error", content = "message")] +pub enum PublishDraftError { + /// No draft exists with the given URI for the authenticated user. + #[serde(rename = "NotFound")] + NotFound(Option), + /// The draft is not ready to publish (status is 'processing' or 'error'). + #[serde(rename = "NotReady")] + NotReady(Option), + /// Catch-all for unknown error codes. + #[serde(untagged)] + Other { + error: SmolStr, + message: Option, + }, +} + +impl core::fmt::Display for PublishDraftError { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + match self { + Self::NotFound(msg) => { + write!(f, "NotFound")?; + if let Some(msg) = msg { + write!(f, ": {}", msg)?; + } + Ok(()) + } + Self::NotReady(msg) => { + write!(f, "NotReady")?; + if let Some(msg) = msg { + write!(f, ": {}", msg)?; + } + Ok(()) + } + Self::Other { error, message } => { + write!(f, "{}", error)?; + if let Some(msg) = message { + write!(f, ": {}", msg)?; + } + Ok(()) + } + } + } +} + +/** Response marker for the `place.stream.vod.publishDraft` procedure. + +Implements `jacquard_common::xrpc::XrpcResp`; successful bodies decode as `Self::Output`, which is `PublishDraftOutput` for this endpoint.*/ +pub struct PublishDraftResponse; +impl jacquard_common::xrpc::XrpcResp for PublishDraftResponse { + const NSID: &'static str = "place.stream.vod.publishDraft"; + const ENCODING: &'static str = "application/json"; + type Output = PublishDraftOutput; + type Err = PublishDraftError; +} + +impl jacquard_common::xrpc::XrpcRequest for PublishDraft { + const NSID: &'static str = "place.stream.vod.publishDraft"; + const METHOD: jacquard_common::xrpc::XrpcMethod = + jacquard_common::xrpc::XrpcMethod::Procedure("application/json"); + type Response = PublishDraftResponse; +} + +/** Endpoint marker for the `place.stream.vod.publishDraft` procedure. + +Path: `/xrpc/place.stream.vod.publishDraft`. The request payload type is `PublishDraft`; send that request with `jacquard::Client` or use this marker through lower-level `XrpcEndpoint` APIs.*/ +pub struct PublishDraftRequest; +impl jacquard_common::xrpc::XrpcEndpoint for PublishDraftRequest { + const PATH: &'static str = "/xrpc/place.stream.vod.publishDraft"; + const METHOD: jacquard_common::xrpc::XrpcMethod = + jacquard_common::xrpc::XrpcMethod::Procedure("application/json"); + type Request = PublishDraft; + type Response = PublishDraftResponse; +} diff --git a/crates/jacquard-api/src/place_stream/vod/update_draft.rs b/crates/jacquard-api/src/place_stream/vod/update_draft.rs new file mode 100644 index 000000000..c3701adea --- /dev/null +++ b/crates/jacquard-api/src/place_stream/vod/update_draft.rs @@ -0,0 +1,140 @@ +// @generated by jacquard-lexicon. DO NOT EDIT. +// +// Lexicon: place.stream.vod.updateDraft +// +// 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; + +use crate::place_stream::ActivityGame; +use crate::place_stream::ActivityLabel; +use crate::place_stream::metadata::content_rights::ContentRights; +use crate::place_stream::metadata::content_warnings::ContentWarnings; +use crate::place_stream::richtext::video_facet::VideoFacet; +use crate::place_stream::vod::draft_defs::DraftView; +#[allow(unused_imports)] +use core::marker::PhantomData; +use jacquard_common::deps::smol_str::SmolStr; +use jacquard_common::types::blob::BlobRef; +use jacquard_common::types::value::Data; +use jacquard_common::{BosStr, CowStr, DefaultStr, FromStaticStr}; +use jacquard_derive::{IntoStatic, open_union}; +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic, Default)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct UpdateDraft { + #[serde(skip_serializing_if = "Option::is_none")] + pub activity: Option>, + #[serde(skip_serializing_if = "Option::is_none")] + pub content_rights: Option>, + #[serde(skip_serializing_if = "Option::is_none")] + pub content_warnings: Option>, + #[serde(skip_serializing_if = "Option::is_none")] + pub description: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub description_facets: Option>>, + #[serde(skip_serializing_if = "Option::is_none")] + pub tags: Option>, + #[serde(skip_serializing_if = "Option::is_none")] + pub thumb: Option>, + #[serde(skip_serializing_if = "Option::is_none")] + pub title: Option, + ///The ats:// URI of the draft to update. + pub uri: S, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +#[open_union] +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde(tag = "$type", bound(deserialize = "S: Deserialize<'de> + BosStr"))] +pub enum UpdateDraftActivity { + #[serde(rename = "place.stream.defs#activityGame")] + ActivityGame(Box>), + #[serde(rename = "place.stream.defs#activityLabel")] + ActivityLabel(Box>), +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct UpdateDraftOutput { + pub draft: DraftView, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +#[derive( + Serialize, Deserialize, Debug, Clone, PartialEq, Eq, thiserror::Error, miette::Diagnostic, +)] +#[serde(tag = "error", content = "message")] +pub enum UpdateDraftError { + /// No draft exists with the given URI for the authenticated user. + #[serde(rename = "NotFound")] + NotFound(Option), + /// Catch-all for unknown error codes. + #[serde(untagged)] + Other { + error: SmolStr, + message: Option, + }, +} + +impl core::fmt::Display for UpdateDraftError { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + match self { + Self::NotFound(msg) => { + write!(f, "NotFound")?; + if let Some(msg) = msg { + write!(f, ": {}", msg)?; + } + Ok(()) + } + Self::Other { error, message } => { + write!(f, "{}", error)?; + if let Some(msg) = message { + write!(f, ": {}", msg)?; + } + Ok(()) + } + } + } +} + +/** Response marker for the `place.stream.vod.updateDraft` procedure. + +Implements `jacquard_common::xrpc::XrpcResp`; successful bodies decode as `Self::Output`, which is `UpdateDraftOutput` for this endpoint.*/ +pub struct UpdateDraftResponse; +impl jacquard_common::xrpc::XrpcResp for UpdateDraftResponse { + const NSID: &'static str = "place.stream.vod.updateDraft"; + const ENCODING: &'static str = "application/json"; + type Output = UpdateDraftOutput; + type Err = UpdateDraftError; +} + +impl jacquard_common::xrpc::XrpcRequest for UpdateDraft { + const NSID: &'static str = "place.stream.vod.updateDraft"; + const METHOD: jacquard_common::xrpc::XrpcMethod = + jacquard_common::xrpc::XrpcMethod::Procedure("application/json"); + type Response = UpdateDraftResponse; +} + +/** Endpoint marker for the `place.stream.vod.updateDraft` procedure. + +Path: `/xrpc/place.stream.vod.updateDraft`. The request payload type is `UpdateDraft`; send that request with `jacquard::Client` or use this marker through lower-level `XrpcEndpoint` APIs.*/ +pub struct UpdateDraftRequest; +impl jacquard_common::xrpc::XrpcEndpoint for UpdateDraftRequest { + const PATH: &'static str = "/xrpc/place.stream.vod.updateDraft"; + const METHOD: jacquard_common::xrpc::XrpcMethod = + jacquard_common::xrpc::XrpcMethod::Procedure("application/json"); + type Request = UpdateDraft; + type Response = UpdateDraftResponse; +} diff --git a/crates/jacquard-api/src/place_wisp/settings.rs b/crates/jacquard-api/src/place_wisp/settings.rs index d38867b72..757caa429 100644 --- a/crates/jacquard-api/src/place_wisp/settings.rs +++ b/crates/jacquard-api/src/place_wisp/settings.rs @@ -213,6 +213,18 @@ impl LexiconSchema for Settings { }); } } + if let Some(values) = &self.index_files { + for value in values { + #[allow(unused_comparisons)] + if ::len(value.as_ref()) > 255usize { + return Err(ConstraintError::MaxLength { + path: ValidationPath::from_field("index_files"), + max: 255usize, + actual: ::len(value.as_ref()), + }); + } + } + } if let Some(ref value) = self.spa_mode { #[allow(unused_comparisons)] if ::len(value.as_ref()) > 500usize { diff --git a/crates/jacquard-api/src/pub_leaflet/blocks.rs b/crates/jacquard-api/src/pub_leaflet/blocks.rs index 852e1d5d2..6ed7a26b9 100644 --- a/crates/jacquard-api/src/pub_leaflet/blocks.rs +++ b/crates/jacquard-api/src/pub_leaflet/blocks.rs @@ -10,15 +10,19 @@ pub mod button; pub mod code; pub mod header; pub mod horizontal_rule; +pub mod html; pub mod iframe; pub mod image; +pub mod image_gallery; pub mod math; +pub mod members_only_delimiter; pub mod ordered_list; pub mod page; pub mod poll; pub mod posts_list; pub mod signup; pub mod standard_site_post; +pub mod standard_site_publication; pub mod text; pub mod unordered_list; pub mod website; diff --git a/crates/jacquard-api/src/pub_leaflet/blocks/html.rs b/crates/jacquard-api/src/pub_leaflet/blocks/html.rs new file mode 100644 index 000000000..8def4c4b6 --- /dev/null +++ b/crates/jacquard-api/src/pub_leaflet/blocks/html.rs @@ -0,0 +1,332 @@ +// @generated by jacquard-lexicon. DO NOT EDIT. +// +// Lexicon: pub.leaflet.blocks.html +// +// 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::value::Data; +use jacquard_derive::IntoStatic; +use jacquard_lexicon::lexicon::LexiconDoc; +use jacquard_lexicon::schema::LexiconSchema; + +use crate::pub_leaflet::blocks::html; +#[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", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct AspectRatio { + pub height: i64, + pub width: i64, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic, Default)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct Html { + #[serde(skip_serializing_if = "Option::is_none")] + pub aspect_ratio: Option>, + #[serde(skip_serializing_if = "Option::is_none")] + pub height: Option, + ///Inline HTML rendered via a sandboxed iframe's srcdoc attribute. + pub html: S, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +impl LexiconSchema for AspectRatio { + fn nsid() -> &'static str { + "pub.leaflet.blocks.html" + } + fn def_name() -> &'static str { + "aspectRatio" + } + fn lexicon_doc() -> LexiconDoc<'static> { + lexicon_doc_pub_leaflet_blocks_html() + } + fn validate(&self) -> Result<(), ConstraintError> { + Ok(()) + } +} + +impl LexiconSchema for Html { + fn nsid() -> &'static str { + "pub.leaflet.blocks.html" + } + fn def_name() -> &'static str { + "main" + } + fn lexicon_doc() -> LexiconDoc<'static> { + lexicon_doc_pub_leaflet_blocks_html() + } + fn validate(&self) -> Result<(), ConstraintError> { + if let Some(ref value) = self.height { + if *value > 1600i64 { + return Err(ConstraintError::Maximum { + path: ValidationPath::from_field("height"), + max: 1600i64, + actual: *value, + }); + } + } + if let Some(ref value) = self.height { + if *value < 16i64 { + return Err(ConstraintError::Minimum { + path: ValidationPath::from_field("height"), + min: 16i64, + actual: *value, + }); + } + } + Ok(()) + } +} + +pub mod aspect_ratio_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 Height; + type Width; + } + /// Empty state - all required fields are unset + pub struct Empty(()); + impl sealed::Sealed for Empty {} + impl State for Empty { + type Height = Unset; + type Width = Unset; + } + ///State transition - sets the `height` field to Set + pub struct SetHeight(PhantomData St>); + impl sealed::Sealed for SetHeight {} + impl State for SetHeight { + type Height = Set; + type Width = St::Width; + } + ///State transition - sets the `width` field to Set + pub struct SetWidth(PhantomData St>); + impl sealed::Sealed for SetWidth {} + impl State for SetWidth { + type Height = St::Height; + type Width = Set; + } + /// Marker types for field names + #[allow(non_camel_case_types)] + pub mod members { + ///Marker type for the `height` field + pub struct height(()); + ///Marker type for the `width` field + pub struct width(()); + } +} + +/// Builder for constructing an instance of this type. +pub struct AspectRatioBuilder { + _state: PhantomData St>, + _fields: (Option, Option), + _type: PhantomData S>, +} + +impl AspectRatio { + /// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed + pub fn new() -> AspectRatioBuilder { + AspectRatioBuilder::new() + } +} + +impl AspectRatio { + /// Create a new builder for this type + pub fn builder() -> AspectRatioBuilder { + AspectRatioBuilder::builder() + } +} + +impl AspectRatioBuilder { + /// Create a new builder with all fields unset, using the default string type, if needed + pub fn new() -> Self { + AspectRatioBuilder { + _state: PhantomData, + _fields: (None, None), + _type: PhantomData, + } + } +} + +impl AspectRatioBuilder { + /// Create a new builder with all fields unset + pub fn builder() -> Self { + AspectRatioBuilder { + _state: PhantomData, + _fields: (None, None), + _type: PhantomData, + } + } +} + +impl AspectRatioBuilder +where + St: aspect_ratio_state::State, + St::Height: aspect_ratio_state::IsUnset, +{ + /// Set the `height` field (required) + pub fn height( + mut self, + value: impl Into, + ) -> AspectRatioBuilder, S> { + self._fields.0 = Option::Some(value.into()); + AspectRatioBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl AspectRatioBuilder +where + St: aspect_ratio_state::State, + St::Width: aspect_ratio_state::IsUnset, +{ + /// Set the `width` field (required) + pub fn width( + mut self, + value: impl Into, + ) -> AspectRatioBuilder, S> { + self._fields.1 = Option::Some(value.into()); + AspectRatioBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl AspectRatioBuilder +where + St: aspect_ratio_state::State, + St::Height: aspect_ratio_state::IsSet, + St::Width: aspect_ratio_state::IsSet, +{ + /// Build the final struct. + pub fn build(self) -> AspectRatio { + AspectRatio { + height: self._fields.0.unwrap(), + width: self._fields.1.unwrap(), + extra_data: Default::default(), + } + } + /// Build the final struct with custom extra_data. + pub fn build_with_data(self, extra_data: BTreeMap>) -> AspectRatio { + AspectRatio { + height: self._fields.0.unwrap(), + width: self._fields.1.unwrap(), + extra_data: Some(extra_data), + } + } +} + +fn lexicon_doc_pub_leaflet_blocks_html() -> 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("pub.leaflet.blocks.html"), + defs: { + let mut map = BTreeMap::new(); + map.insert( + SmolStr::new_static("aspectRatio"), + LexUserType::Object(LexObject { + required: Some(vec![ + SmolStr::new_static("width"), + SmolStr::new_static("height"), + ]), + properties: { + #[allow(unused_mut)] + let mut map = BTreeMap::new(); + map.insert( + SmolStr::new_static("height"), + LexObjectProperty::Integer(LexInteger { + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("width"), + LexObjectProperty::Integer(LexInteger { + ..Default::default() + }), + ); + map + }, + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("main"), + LexUserType::Object(LexObject { + required: Some(vec![SmolStr::new_static("html")]), + properties: { + #[allow(unused_mut)] + let mut map = BTreeMap::new(); + map.insert( + SmolStr::new_static("aspectRatio"), + LexObjectProperty::Ref(LexRef { + r#ref: CowStr::new_static("#aspectRatio"), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("height"), + LexObjectProperty::Integer(LexInteger { + minimum: Some(16i64), + maximum: Some(1600i64), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("html"), + LexObjectProperty::String(LexString { + description: Some( + CowStr::new_static( + "Inline HTML rendered via a sandboxed iframe's srcdoc attribute.", + ), + ), + ..Default::default() + }), + ); + map + }, + ..Default::default() + }), + ); + map + }, + ..Default::default() + } +} diff --git a/crates/jacquard-api/src/pub_leaflet/blocks/iframe.rs b/crates/jacquard-api/src/pub_leaflet/blocks/iframe.rs index d66b90c7d..5b9383c43 100644 --- a/crates/jacquard-api/src/pub_leaflet/blocks/iframe.rs +++ b/crates/jacquard-api/src/pub_leaflet/blocks/iframe.rs @@ -10,7 +10,7 @@ use alloc::collections::BTreeMap; #[allow(unused_imports)] use core::marker::PhantomData; -use jacquard_common::{BosStr, DefaultStr, FromStaticStr}; +use jacquard_common::{BosStr, CowStr, DefaultStr, FromStaticStr}; #[allow(unused_imports)] use jacquard_common::deps::codegen::unicode_segmentation::UnicodeSegmentation; @@ -38,7 +38,7 @@ pub struct AspectRatio { pub extra_data: Option>>, } -#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic, Default)] #[serde( rename_all = "camelCase", bound(deserialize = "S: Deserialize<'de> + BosStr") @@ -48,7 +48,11 @@ pub struct Iframe { pub aspect_ratio: Option>, #[serde(skip_serializing_if = "Option::is_none")] pub height: Option, - pub url: UriValue, + ///DEPRECATED — use pub.leaflet.blocks.html instead. Inline HTML rendered via the iframe's srcdoc attribute. Takes precedence over url. + #[serde(skip_serializing_if = "Option::is_none")] + pub html: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub url: Option>, #[serde(flatten, default, skip_serializing_if = "Option::is_none")] pub extra_data: Option>>, } @@ -290,7 +294,6 @@ fn lexicon_doc_pub_leaflet_blocks_iframe() -> LexiconDoc<'static> { map.insert( SmolStr::new_static("main"), LexUserType::Object(LexObject { - required: Some(vec![SmolStr::new_static("url")]), properties: { #[allow(unused_mut)] let mut map = BTreeMap::new(); @@ -309,6 +312,17 @@ fn lexicon_doc_pub_leaflet_blocks_iframe() -> LexiconDoc<'static> { ..Default::default() }), ); + map.insert( + SmolStr::new_static("html"), + LexObjectProperty::String(LexString { + description: Some( + CowStr::new_static( + "DEPRECATED — use pub.leaflet.blocks.html instead. Inline HTML rendered via the iframe's srcdoc attribute. Takes precedence over url.", + ), + ), + ..Default::default() + }), + ); map.insert( SmolStr::new_static("url"), LexObjectProperty::String(LexString { @@ -326,152 +340,3 @@ fn lexicon_doc_pub_leaflet_blocks_iframe() -> LexiconDoc<'static> { ..Default::default() } } - -pub mod iframe_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 Url; - } - /// Empty state - all required fields are unset - pub struct Empty(()); - impl sealed::Sealed for Empty {} - impl State for Empty { - type Url = Unset; - } - ///State transition - sets the `url` field to Set - pub struct SetUrl(PhantomData St>); - impl sealed::Sealed for SetUrl {} - impl State for SetUrl { - type Url = Set; - } - /// Marker types for field names - #[allow(non_camel_case_types)] - pub mod members { - ///Marker type for the `url` field - pub struct url(()); - } -} - -/// Builder for constructing an instance of this type. -pub struct IframeBuilder { - _state: PhantomData St>, - _fields: ( - Option>, - Option, - Option>, - ), - _type: PhantomData S>, -} - -impl Iframe { - /// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed - pub fn new() -> IframeBuilder { - IframeBuilder::new() - } -} - -impl Iframe { - /// Create a new builder for this type - pub fn builder() -> IframeBuilder { - IframeBuilder::builder() - } -} - -impl IframeBuilder { - /// Create a new builder with all fields unset, using the default string type, if needed - pub fn new() -> Self { - IframeBuilder { - _state: PhantomData, - _fields: (None, None, None), - _type: PhantomData, - } - } -} - -impl IframeBuilder { - /// Create a new builder with all fields unset - pub fn builder() -> Self { - IframeBuilder { - _state: PhantomData, - _fields: (None, None, None), - _type: PhantomData, - } - } -} - -impl IframeBuilder { - /// Set the `aspectRatio` field (optional) - pub fn aspect_ratio(mut self, value: impl Into>>) -> Self { - self._fields.0 = value.into(); - self - } - /// Set the `aspectRatio` field to an Option value (optional) - pub fn maybe_aspect_ratio(mut self, value: Option>) -> Self { - self._fields.0 = value; - self - } -} - -impl IframeBuilder { - /// Set the `height` field (optional) - pub fn height(mut self, value: impl Into>) -> Self { - self._fields.1 = value.into(); - self - } - /// Set the `height` field to an Option value (optional) - pub fn maybe_height(mut self, value: Option) -> Self { - self._fields.1 = value; - self - } -} - -impl IframeBuilder -where - St: iframe_state::State, - St::Url: iframe_state::IsUnset, -{ - /// Set the `url` field (required) - pub fn url( - mut self, - value: impl Into>, - ) -> IframeBuilder, S> { - self._fields.2 = Option::Some(value.into()); - IframeBuilder { - _state: PhantomData, - _fields: self._fields, - _type: PhantomData, - } - } -} - -impl IframeBuilder -where - St: iframe_state::State, - St::Url: iframe_state::IsSet, -{ - /// Build the final struct. - pub fn build(self) -> Iframe { - Iframe { - aspect_ratio: self._fields.0, - height: self._fields.1, - url: 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>) -> Iframe { - Iframe { - aspect_ratio: self._fields.0, - height: self._fields.1, - url: self._fields.2.unwrap(), - extra_data: Some(extra_data), - } - } -} diff --git a/crates/jacquard-api/src/pub_leaflet/blocks/image.rs b/crates/jacquard-api/src/pub_leaflet/blocks/image.rs index 39af31a8b..9bca12d65 100644 --- a/crates/jacquard-api/src/pub_leaflet/blocks/image.rs +++ b/crates/jacquard-api/src/pub_leaflet/blocks/image.rs @@ -52,6 +52,9 @@ pub struct Image { #[serde(skip_serializing_if = "Option::is_none")] pub full_bleed: Option, pub image: BlobRef, + ///Display width of the image in pixels, capped at the page width. + #[serde(skip_serializing_if = "Option::is_none")] + pub width: Option, #[serde(flatten, default, skip_serializing_if = "Option::is_none")] pub extra_data: Option>>, } @@ -347,6 +350,12 @@ fn lexicon_doc_pub_leaflet_blocks_image() -> LexiconDoc<'static> { ..Default::default() }), ); + map.insert( + SmolStr::new_static("width"), + LexObjectProperty::Integer(LexInteger { + ..Default::default() + }), + ); map }, ..Default::default() @@ -410,6 +419,7 @@ pub struct ImageBuilder { Option>, Option, Option>, + Option, ), _type: PhantomData S>, } @@ -433,7 +443,7 @@ impl ImageBuilder { pub fn new() -> Self { ImageBuilder { _state: PhantomData, - _fields: (None, None, None, None), + _fields: (None, None, None, None, None), _type: PhantomData, } } @@ -444,7 +454,7 @@ impl ImageBuilder { pub fn builder() -> Self { ImageBuilder { _state: PhantomData, - _fields: (None, None, None, None), + _fields: (None, None, None, None, None), _type: PhantomData, } } @@ -514,6 +524,19 @@ where } } +impl ImageBuilder { + /// Set the `width` field (optional) + pub fn width(mut self, value: impl Into>) -> Self { + self._fields.4 = value.into(); + self + } + /// Set the `width` field to an Option value (optional) + pub fn maybe_width(mut self, value: Option) -> Self { + self._fields.4 = value; + self + } +} + impl ImageBuilder where St: image_state::State, @@ -527,6 +550,7 @@ where aspect_ratio: self._fields.1.unwrap(), full_bleed: self._fields.2, image: self._fields.3.unwrap(), + width: self._fields.4, extra_data: Default::default(), } } @@ -537,6 +561,7 @@ where aspect_ratio: self._fields.1.unwrap(), full_bleed: self._fields.2, image: self._fields.3.unwrap(), + width: self._fields.4, extra_data: Some(extra_data), } } diff --git a/crates/jacquard-api/src/pub_leaflet/blocks/image_gallery.rs b/crates/jacquard-api/src/pub_leaflet/blocks/image_gallery.rs new file mode 100644 index 000000000..ab591b5be --- /dev/null +++ b/crates/jacquard-api/src/pub_leaflet/blocks/image_gallery.rs @@ -0,0 +1,838 @@ +// @generated by jacquard-lexicon. DO NOT EDIT. +// +// Lexicon: pub.leaflet.blocks.imageGallery +// +// 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::blob::BlobRef; +use jacquard_common::types::value::Data; +use jacquard_derive::IntoStatic; +use jacquard_lexicon::lexicon::LexiconDoc; +use jacquard_lexicon::schema::LexiconSchema; + +use crate::pub_leaflet::blocks::image_gallery; +#[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", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct AspectRatio { + pub height: i64, + pub width: i64, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct Image { + ///Alt text description of the image, for accessibility. + #[serde(skip_serializing_if = "Option::is_none")] + pub alt: Option, + pub aspect_ratio: image_gallery::AspectRatio, + pub image: BlobRef, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct ImageGallery { + #[serde(skip_serializing_if = "Option::is_none")] + pub format: Option>, + ///Gap between images in pixels. + #[serde(skip_serializing_if = "Option::is_none")] + pub gap: Option, + pub images: Vec>, + ///Max width per image in grid view (px); drives how many columns fit. + #[serde(skip_serializing_if = "Option::is_none")] + pub max_width: Option, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub enum ImageGalleryFormat { + Grid, + Carousel, + Strip, + Other(S), +} + +impl ImageGalleryFormat { + pub fn as_str(&self) -> &str { + match self { + Self::Grid => "grid", + Self::Carousel => "carousel", + Self::Strip => "strip", + 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() { + "grid" => Self::Grid, + "carousel" => Self::Carousel, + "strip" => Self::Strip, + _ => Self::Other(s), + } + } +} + +impl core::fmt::Display for ImageGalleryFormat { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!(f, "{}", self.as_str()) + } +} + +impl AsRef for ImageGalleryFormat { + fn as_ref(&self) -> &str { + self.as_str() + } +} + +impl Serialize for ImageGalleryFormat { + 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 ImageGalleryFormat { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = S::deserialize(deserializer)?; + Ok(Self::from_value(s)) + } +} + +impl Default for ImageGalleryFormat { + fn default() -> Self { + Self::Other(Default::default()) + } +} + +impl jacquard_common::IntoStatic for ImageGalleryFormat +where + S: BosStr + jacquard_common::IntoStatic, + S::Output: BosStr, +{ + type Output = ImageGalleryFormat; + fn into_static(self) -> Self::Output { + match self { + ImageGalleryFormat::Grid => ImageGalleryFormat::Grid, + ImageGalleryFormat::Carousel => ImageGalleryFormat::Carousel, + ImageGalleryFormat::Strip => ImageGalleryFormat::Strip, + ImageGalleryFormat::Other(v) => ImageGalleryFormat::Other(v.into_static()), + } + } +} + +impl LexiconSchema for AspectRatio { + fn nsid() -> &'static str { + "pub.leaflet.blocks.imageGallery" + } + fn def_name() -> &'static str { + "aspectRatio" + } + fn lexicon_doc() -> LexiconDoc<'static> { + lexicon_doc_pub_leaflet_blocks_imageGallery() + } + fn validate(&self) -> Result<(), ConstraintError> { + Ok(()) + } +} + +impl LexiconSchema for Image { + fn nsid() -> &'static str { + "pub.leaflet.blocks.imageGallery" + } + fn def_name() -> &'static str { + "image" + } + fn lexicon_doc() -> LexiconDoc<'static> { + lexicon_doc_pub_leaflet_blocks_imageGallery() + } + fn validate(&self) -> Result<(), ConstraintError> { + { + let value = &self.image; + { + let size = value.blob().size; + if size > 1000000usize { + return Err(ConstraintError::BlobTooLarge { + path: ValidationPath::from_field("image"), + max: 1000000usize, + actual: size, + }); + } + } + } + { + let value = &self.image; + { + let mime = value.blob().mime_type.as_str(); + let accepted: &[&str] = &["image/*"]; + let matched = accepted.iter().any(|pattern| { + if *pattern == "*/*" { + true + } else if pattern.ends_with("/*") { + let prefix = &pattern[..pattern.len() - 2]; + mime.starts_with(prefix) && mime.as_bytes().get(prefix.len()) == Some(&b'/') + } else { + mime == *pattern + } + }); + if !matched { + return Err(ConstraintError::BlobMimeTypeNotAccepted { + path: ValidationPath::from_field("image"), + accepted: vec!["image/*".to_string()], + actual: mime.to_string(), + }); + } + } + } + Ok(()) + } +} + +impl LexiconSchema for ImageGallery { + fn nsid() -> &'static str { + "pub.leaflet.blocks.imageGallery" + } + fn def_name() -> &'static str { + "main" + } + fn lexicon_doc() -> LexiconDoc<'static> { + lexicon_doc_pub_leaflet_blocks_imageGallery() + } + fn validate(&self) -> Result<(), ConstraintError> { + Ok(()) + } +} + +pub mod aspect_ratio_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 Height; + type Width; + } + /// Empty state - all required fields are unset + pub struct Empty(()); + impl sealed::Sealed for Empty {} + impl State for Empty { + type Height = Unset; + type Width = Unset; + } + ///State transition - sets the `height` field to Set + pub struct SetHeight(PhantomData St>); + impl sealed::Sealed for SetHeight {} + impl State for SetHeight { + type Height = Set; + type Width = St::Width; + } + ///State transition - sets the `width` field to Set + pub struct SetWidth(PhantomData St>); + impl sealed::Sealed for SetWidth {} + impl State for SetWidth { + type Height = St::Height; + type Width = Set; + } + /// Marker types for field names + #[allow(non_camel_case_types)] + pub mod members { + ///Marker type for the `height` field + pub struct height(()); + ///Marker type for the `width` field + pub struct width(()); + } +} + +/// Builder for constructing an instance of this type. +pub struct AspectRatioBuilder { + _state: PhantomData St>, + _fields: (Option, Option), + _type: PhantomData S>, +} + +impl AspectRatio { + /// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed + pub fn new() -> AspectRatioBuilder { + AspectRatioBuilder::new() + } +} + +impl AspectRatio { + /// Create a new builder for this type + pub fn builder() -> AspectRatioBuilder { + AspectRatioBuilder::builder() + } +} + +impl AspectRatioBuilder { + /// Create a new builder with all fields unset, using the default string type, if needed + pub fn new() -> Self { + AspectRatioBuilder { + _state: PhantomData, + _fields: (None, None), + _type: PhantomData, + } + } +} + +impl AspectRatioBuilder { + /// Create a new builder with all fields unset + pub fn builder() -> Self { + AspectRatioBuilder { + _state: PhantomData, + _fields: (None, None), + _type: PhantomData, + } + } +} + +impl AspectRatioBuilder +where + St: aspect_ratio_state::State, + St::Height: aspect_ratio_state::IsUnset, +{ + /// Set the `height` field (required) + pub fn height( + mut self, + value: impl Into, + ) -> AspectRatioBuilder, S> { + self._fields.0 = Option::Some(value.into()); + AspectRatioBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl AspectRatioBuilder +where + St: aspect_ratio_state::State, + St::Width: aspect_ratio_state::IsUnset, +{ + /// Set the `width` field (required) + pub fn width( + mut self, + value: impl Into, + ) -> AspectRatioBuilder, S> { + self._fields.1 = Option::Some(value.into()); + AspectRatioBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl AspectRatioBuilder +where + St: aspect_ratio_state::State, + St::Height: aspect_ratio_state::IsSet, + St::Width: aspect_ratio_state::IsSet, +{ + /// Build the final struct. + pub fn build(self) -> AspectRatio { + AspectRatio { + height: self._fields.0.unwrap(), + width: self._fields.1.unwrap(), + extra_data: Default::default(), + } + } + /// Build the final struct with custom extra_data. + pub fn build_with_data(self, extra_data: BTreeMap>) -> AspectRatio { + AspectRatio { + height: self._fields.0.unwrap(), + width: self._fields.1.unwrap(), + extra_data: Some(extra_data), + } + } +} + +fn lexicon_doc_pub_leaflet_blocks_imageGallery() -> 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("pub.leaflet.blocks.imageGallery"), + defs: { + let mut map = BTreeMap::new(); + map.insert( + SmolStr::new_static("aspectRatio"), + LexUserType::Object(LexObject { + required: Some(vec![ + SmolStr::new_static("width"), + SmolStr::new_static("height"), + ]), + properties: { + #[allow(unused_mut)] + let mut map = BTreeMap::new(); + map.insert( + SmolStr::new_static("height"), + LexObjectProperty::Integer(LexInteger { + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("width"), + LexObjectProperty::Integer(LexInteger { + ..Default::default() + }), + ); + map + }, + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("image"), + LexUserType::Object(LexObject { + required: Some(vec![ + SmolStr::new_static("image"), + SmolStr::new_static("aspectRatio"), + ]), + properties: { + #[allow(unused_mut)] + let mut map = BTreeMap::new(); + map.insert( + SmolStr::new_static("alt"), + LexObjectProperty::String(LexString { + description: Some(CowStr::new_static( + "Alt text description of the image, for accessibility.", + )), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("aspectRatio"), + LexObjectProperty::Ref(LexRef { + r#ref: CowStr::new_static("#aspectRatio"), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("image"), + LexObjectProperty::Blob(LexBlob { + ..Default::default() + }), + ); + map + }, + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("main"), + LexUserType::Object(LexObject { + required: Some(vec![SmolStr::new_static("images")]), + properties: { + #[allow(unused_mut)] + let mut map = BTreeMap::new(); + map.insert( + SmolStr::new_static("format"), + LexObjectProperty::String(LexString { + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("gap"), + LexObjectProperty::Integer(LexInteger { + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("images"), + LexObjectProperty::Array(LexArray { + items: LexArrayItem::Ref(LexRef { + r#ref: CowStr::new_static("#image"), + ..Default::default() + }), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("maxWidth"), + LexObjectProperty::Integer(LexInteger { + ..Default::default() + }), + ); + map + }, + ..Default::default() + }), + ); + map + }, + ..Default::default() + } +} + +pub mod image_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 AspectRatio; + type Image; + } + /// Empty state - all required fields are unset + pub struct Empty(()); + impl sealed::Sealed for Empty {} + impl State for Empty { + type AspectRatio = Unset; + type Image = Unset; + } + ///State transition - sets the `aspect_ratio` field to Set + pub struct SetAspectRatio(PhantomData St>); + impl sealed::Sealed for SetAspectRatio {} + impl State for SetAspectRatio { + type AspectRatio = Set; + type Image = St::Image; + } + ///State transition - sets the `image` field to Set + pub struct SetImage(PhantomData St>); + impl sealed::Sealed for SetImage {} + impl State for SetImage { + type AspectRatio = St::AspectRatio; + type Image = Set; + } + /// Marker types for field names + #[allow(non_camel_case_types)] + pub mod members { + ///Marker type for the `aspect_ratio` field + pub struct aspect_ratio(()); + ///Marker type for the `image` field + pub struct image(()); + } +} + +/// Builder for constructing an instance of this type. +pub struct ImageBuilder { + _state: PhantomData St>, + _fields: ( + Option, + Option>, + Option>, + ), + _type: PhantomData S>, +} + +impl Image { + /// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed + pub fn new() -> ImageBuilder { + ImageBuilder::new() + } +} + +impl Image { + /// Create a new builder for this type + pub fn builder() -> ImageBuilder { + ImageBuilder::builder() + } +} + +impl ImageBuilder { + /// Create a new builder with all fields unset, using the default string type, if needed + pub fn new() -> Self { + ImageBuilder { + _state: PhantomData, + _fields: (None, None, None), + _type: PhantomData, + } + } +} + +impl ImageBuilder { + /// Create a new builder with all fields unset + pub fn builder() -> Self { + ImageBuilder { + _state: PhantomData, + _fields: (None, None, None), + _type: PhantomData, + } + } +} + +impl ImageBuilder { + /// Set the `alt` field (optional) + pub fn alt(mut self, value: impl Into>) -> Self { + self._fields.0 = value.into(); + self + } + /// Set the `alt` field to an Option value (optional) + pub fn maybe_alt(mut self, value: Option) -> Self { + self._fields.0 = value; + self + } +} + +impl ImageBuilder +where + St: image_state::State, + St::AspectRatio: image_state::IsUnset, +{ + /// Set the `aspectRatio` field (required) + pub fn aspect_ratio( + mut self, + value: impl Into>, + ) -> ImageBuilder, S> { + self._fields.1 = Option::Some(value.into()); + ImageBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl ImageBuilder +where + St: image_state::State, + St::Image: image_state::IsUnset, +{ + /// Set the `image` field (required) + pub fn image( + mut self, + value: impl Into>, + ) -> ImageBuilder, S> { + self._fields.2 = Option::Some(value.into()); + ImageBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl ImageBuilder +where + St: image_state::State, + St::AspectRatio: image_state::IsSet, + St::Image: image_state::IsSet, +{ + /// Build the final struct. + pub fn build(self) -> Image { + Image { + alt: self._fields.0, + aspect_ratio: self._fields.1.unwrap(), + image: 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>) -> Image { + Image { + alt: self._fields.0, + aspect_ratio: self._fields.1.unwrap(), + image: self._fields.2.unwrap(), + extra_data: Some(extra_data), + } + } +} + +pub mod image_gallery_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 Images; + } + /// Empty state - all required fields are unset + pub struct Empty(()); + impl sealed::Sealed for Empty {} + impl State for Empty { + type Images = Unset; + } + ///State transition - sets the `images` field to Set + pub struct SetImages(PhantomData St>); + impl sealed::Sealed for SetImages {} + impl State for SetImages { + type Images = Set; + } + /// Marker types for field names + #[allow(non_camel_case_types)] + pub mod members { + ///Marker type for the `images` field + pub struct images(()); + } +} + +/// Builder for constructing an instance of this type. +pub struct ImageGalleryBuilder { + _state: PhantomData St>, + _fields: ( + Option>, + Option, + Option>>, + Option, + ), + _type: PhantomData S>, +} + +impl ImageGallery { + /// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed + pub fn new() -> ImageGalleryBuilder { + ImageGalleryBuilder::new() + } +} + +impl ImageGallery { + /// Create a new builder for this type + pub fn builder() -> ImageGalleryBuilder { + ImageGalleryBuilder::builder() + } +} + +impl ImageGalleryBuilder { + /// Create a new builder with all fields unset, using the default string type, if needed + pub fn new() -> Self { + ImageGalleryBuilder { + _state: PhantomData, + _fields: (None, None, None, None), + _type: PhantomData, + } + } +} + +impl ImageGalleryBuilder { + /// Create a new builder with all fields unset + pub fn builder() -> Self { + ImageGalleryBuilder { + _state: PhantomData, + _fields: (None, None, None, None), + _type: PhantomData, + } + } +} + +impl ImageGalleryBuilder { + /// Set the `format` field (optional) + pub fn format(mut self, value: impl Into>>) -> Self { + self._fields.0 = value.into(); + self + } + /// Set the `format` field to an Option value (optional) + pub fn maybe_format(mut self, value: Option>) -> Self { + self._fields.0 = value; + self + } +} + +impl ImageGalleryBuilder { + /// Set the `gap` field (optional) + pub fn gap(mut self, value: impl Into>) -> Self { + self._fields.1 = value.into(); + self + } + /// Set the `gap` field to an Option value (optional) + pub fn maybe_gap(mut self, value: Option) -> Self { + self._fields.1 = value; + self + } +} + +impl ImageGalleryBuilder +where + St: image_gallery_state::State, + St::Images: image_gallery_state::IsUnset, +{ + /// Set the `images` field (required) + pub fn images( + mut self, + value: impl Into>>, + ) -> ImageGalleryBuilder, S> { + self._fields.2 = Option::Some(value.into()); + ImageGalleryBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl ImageGalleryBuilder { + /// Set the `maxWidth` field (optional) + pub fn max_width(mut self, value: impl Into>) -> Self { + self._fields.3 = value.into(); + self + } + /// Set the `maxWidth` field to an Option value (optional) + pub fn maybe_max_width(mut self, value: Option) -> Self { + self._fields.3 = value; + self + } +} + +impl ImageGalleryBuilder +where + St: image_gallery_state::State, + St::Images: image_gallery_state::IsSet, +{ + /// Build the final struct. + pub fn build(self) -> ImageGallery { + ImageGallery { + format: self._fields.0, + gap: self._fields.1, + images: self._fields.2.unwrap(), + max_width: self._fields.3, + extra_data: Default::default(), + } + } + /// Build the final struct with custom extra_data. + pub fn build_with_data(self, extra_data: BTreeMap>) -> ImageGallery { + ImageGallery { + format: self._fields.0, + gap: self._fields.1, + images: self._fields.2.unwrap(), + max_width: self._fields.3, + extra_data: Some(extra_data), + } + } +} diff --git a/crates/jacquard-api/src/pub_leaflet/blocks/members_only_delimiter.rs b/crates/jacquard-api/src/pub_leaflet/blocks/members_only_delimiter.rs new file mode 100644 index 000000000..3af912966 --- /dev/null +++ b/crates/jacquard-api/src/pub_leaflet/blocks/members_only_delimiter.rs @@ -0,0 +1,95 @@ +// @generated by jacquard-lexicon. DO NOT EDIT. +// +// Lexicon: pub.leaflet.blocks.membersOnlyDelimiter +// +// 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; +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::value::Data; +use jacquard_derive::IntoStatic; +use jacquard_lexicon::lexicon::LexiconDoc; +use jacquard_lexicon::schema::LexiconSchema; + +#[allow(unused_imports)] +use jacquard_lexicon::validation::{ConstraintError, ValidationPath}; +use serde::{Deserialize, Serialize}; +/// Marks where members-only content begins; blocks after this delimiter are only served to readers with an active paid membership. + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic, Default)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct MembersOnlyDelimiter { + ///Id of the lowest membership tier whose members can read past the delimiter; tiers rank by price, so pricier tiers read through too. Absent means any paid membership. + #[serde(skip_serializing_if = "Option::is_none")] + pub tier: Option, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +impl LexiconSchema for MembersOnlyDelimiter { + fn nsid() -> &'static str { + "pub.leaflet.blocks.membersOnlyDelimiter" + } + fn def_name() -> &'static str { + "main" + } + fn lexicon_doc() -> LexiconDoc<'static> { + lexicon_doc_pub_leaflet_blocks_membersOnlyDelimiter() + } + fn validate(&self) -> Result<(), ConstraintError> { + Ok(()) + } +} + +fn lexicon_doc_pub_leaflet_blocks_membersOnlyDelimiter() -> 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("pub.leaflet.blocks.membersOnlyDelimiter"), + defs: { + let mut map = BTreeMap::new(); + map.insert( + SmolStr::new_static("main"), + LexUserType::Object(LexObject { + description: Some( + CowStr::new_static( + "Marks where members-only content begins; blocks after this delimiter are only served to readers with an active paid membership.", + ), + ), + required: Some(vec![]), + properties: { + #[allow(unused_mut)] + let mut map = BTreeMap::new(); + map.insert( + SmolStr::new_static("tier"), + LexObjectProperty::String(LexString { + description: Some( + CowStr::new_static( + "Id of the lowest membership tier whose members can read past the delimiter; tiers rank by price, so pricier tiers read through too. Absent means any paid membership.", + ), + ), + ..Default::default() + }), + ); + map + }, + ..Default::default() + }), + ); + map + }, + ..Default::default() + } +} diff --git a/crates/jacquard-api/src/pub_leaflet/blocks/posts_list.rs b/crates/jacquard-api/src/pub_leaflet/blocks/posts_list.rs index 519116e85..15ebeea98 100644 --- a/crates/jacquard-api/src/pub_leaflet/blocks/posts_list.rs +++ b/crates/jacquard-api/src/pub_leaflet/blocks/posts_list.rs @@ -44,6 +44,7 @@ pub struct PostsList { pub enum PostsListView { Small, Medium, + Chapter, Other(S), } @@ -52,6 +53,7 @@ impl PostsListView { match self { Self::Small => "small", Self::Medium => "medium", + Self::Chapter => "chapter", Self::Other(s) => s.as_ref(), } } @@ -60,6 +62,7 @@ impl PostsListView { match s.as_ref() { "small" => Self::Small, "medium" => Self::Medium, + "chapter" => Self::Chapter, _ => Self::Other(s), } } @@ -112,6 +115,7 @@ where match self { PostsListView::Small => PostsListView::Small, PostsListView::Medium => PostsListView::Medium, + PostsListView::Chapter => PostsListView::Chapter, PostsListView::Other(v) => PostsListView::Other(v.into_static()), } } diff --git a/crates/jacquard-api/src/pub_leaflet/blocks/standard_site_publication.rs b/crates/jacquard-api/src/pub_leaflet/blocks/standard_site_publication.rs new file mode 100644 index 000000000..4df7ebfdf --- /dev/null +++ b/crates/jacquard-api/src/pub_leaflet/blocks/standard_site_publication.rs @@ -0,0 +1,255 @@ +// @generated by jacquard-lexicon. DO NOT EDIT. +// +// Lexicon: pub.leaflet.blocks.standardSitePublication +// +// 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::string::AtUri; +use jacquard_common::types::value::Data; +use jacquard_derive::IntoStatic; +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", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct StandardSitePublication { + #[serde(skip_serializing_if = "Option::is_none")] + pub cid: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub show_publication_theme: Option, + pub uri: AtUri, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +impl LexiconSchema for StandardSitePublication { + fn nsid() -> &'static str { + "pub.leaflet.blocks.standardSitePublication" + } + fn def_name() -> &'static str { + "main" + } + fn lexicon_doc() -> LexiconDoc<'static> { + lexicon_doc_pub_leaflet_blocks_standardSitePublication() + } + fn validate(&self) -> Result<(), ConstraintError> { + Ok(()) + } +} + +pub mod standard_site_publication_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 Uri; + } + /// Empty state - all required fields are unset + pub struct Empty(()); + impl sealed::Sealed for Empty {} + impl State for Empty { + type Uri = Unset; + } + ///State transition - sets the `uri` field to Set + pub struct SetUri(PhantomData St>); + impl sealed::Sealed for SetUri {} + impl State for SetUri { + type Uri = Set; + } + /// Marker types for field names + #[allow(non_camel_case_types)] + pub mod members { + ///Marker type for the `uri` field + pub struct uri(()); + } +} + +/// Builder for constructing an instance of this type. +pub struct StandardSitePublicationBuilder< + St: standard_site_publication_state::State, + S: BosStr = DefaultStr, +> { + _state: PhantomData St>, + _fields: (Option, Option, Option>), + _type: PhantomData S>, +} + +impl StandardSitePublication { + /// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed + pub fn new() + -> StandardSitePublicationBuilder { + StandardSitePublicationBuilder::new() + } +} + +impl StandardSitePublication { + /// Create a new builder for this type + pub fn builder() -> StandardSitePublicationBuilder { + StandardSitePublicationBuilder::builder() + } +} + +impl StandardSitePublicationBuilder { + /// Create a new builder with all fields unset, using the default string type, if needed + pub fn new() -> Self { + StandardSitePublicationBuilder { + _state: PhantomData, + _fields: (None, None, None), + _type: PhantomData, + } + } +} + +impl StandardSitePublicationBuilder { + /// Create a new builder with all fields unset + pub fn builder() -> Self { + StandardSitePublicationBuilder { + _state: PhantomData, + _fields: (None, None, None), + _type: PhantomData, + } + } +} + +impl StandardSitePublicationBuilder { + /// Set the `cid` field (optional) + pub fn cid(mut self, value: impl Into>) -> Self { + self._fields.0 = value.into(); + self + } + /// Set the `cid` field to an Option value (optional) + pub fn maybe_cid(mut self, value: Option) -> Self { + self._fields.0 = value; + self + } +} + +impl StandardSitePublicationBuilder { + /// Set the `showPublicationTheme` field (optional) + pub fn show_publication_theme(mut self, value: impl Into>) -> Self { + self._fields.1 = value.into(); + self + } + /// Set the `showPublicationTheme` field to an Option value (optional) + pub fn maybe_show_publication_theme(mut self, value: Option) -> Self { + self._fields.1 = value; + self + } +} + +impl StandardSitePublicationBuilder +where + St: standard_site_publication_state::State, + St::Uri: standard_site_publication_state::IsUnset, +{ + /// Set the `uri` field (required) + pub fn uri( + mut self, + value: impl Into>, + ) -> StandardSitePublicationBuilder, S> { + self._fields.2 = Option::Some(value.into()); + StandardSitePublicationBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl StandardSitePublicationBuilder +where + St: standard_site_publication_state::State, + St::Uri: standard_site_publication_state::IsSet, +{ + /// Build the final struct. + pub fn build(self) -> StandardSitePublication { + StandardSitePublication { + cid: self._fields.0, + show_publication_theme: self._fields.1, + uri: 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>, + ) -> StandardSitePublication { + StandardSitePublication { + cid: self._fields.0, + show_publication_theme: self._fields.1, + uri: self._fields.2.unwrap(), + extra_data: Some(extra_data), + } + } +} + +fn lexicon_doc_pub_leaflet_blocks_standardSitePublication() -> 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("pub.leaflet.blocks.standardSitePublication"), + defs: { + let mut map = BTreeMap::new(); + map.insert( + SmolStr::new_static("main"), + LexUserType::Object(LexObject { + required: Some(vec![SmolStr::new_static("uri")]), + properties: { + #[allow(unused_mut)] + let mut map = BTreeMap::new(); + map.insert( + SmolStr::new_static("cid"), + LexObjectProperty::String(LexString { + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("showPublicationTheme"), + LexObjectProperty::Boolean(LexBoolean { + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("uri"), + LexObjectProperty::String(LexString { + format: Some(LexStringFormat::AtUri), + ..Default::default() + }), + ); + map + }, + ..Default::default() + }), + ); + map + }, + ..Default::default() + } +} diff --git a/crates/jacquard-api/src/pub_leaflet/document.rs b/crates/jacquard-api/src/pub_leaflet/document.rs index d8f11d084..f5ef45ce2 100644 --- a/crates/jacquard-api/src/pub_leaflet/document.rs +++ b/crates/jacquard-api/src/pub_leaflet/document.rs @@ -193,6 +193,18 @@ impl LexiconSchema for Document { } } } + if let Some(values) = &self.tags { + for value in values { + #[allow(unused_comparisons)] + if ::len(value.as_ref()) > 50usize { + return Err(ConstraintError::MaxLength { + path: ValidationPath::from_field("tags"), + max: 50usize, + actual: ::len(value.as_ref()), + }); + } + } + } { let value = &self.title; #[allow(unused_comparisons)] diff --git a/crates/jacquard-api/src/pub_leaflet/graph.rs b/crates/jacquard-api/src/pub_leaflet/graph.rs index eb6c0485c..6acb0dbb6 100644 --- a/crates/jacquard-api/src/pub_leaflet/graph.rs +++ b/crates/jacquard-api/src/pub_leaflet/graph.rs @@ -4,4 +4,5 @@ // Any manual changes will be overwritten on the next regeneration. //! Generated bindings for the `pub.leaflet.graph` Lexicon namespace/module. +pub mod recommendations; pub mod subscription; diff --git a/crates/jacquard-api/src/pub_leaflet/graph/recommendations.rs b/crates/jacquard-api/src/pub_leaflet/graph/recommendations.rs new file mode 100644 index 000000000..93fb01fc8 --- /dev/null +++ b/crates/jacquard-api/src/pub_leaflet/graph/recommendations.rs @@ -0,0 +1,335 @@ +// @generated by jacquard-lexicon. DO NOT EDIT. +// +// Lexicon: pub.leaflet.graph.recommendations +// +// 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}; +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}; +/// Record declaring the publications a publication recommends + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + rename = "pub.leaflet.graph.recommendations", + tag = "$type", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct Recommendations { + ///The publication making the recommendations; must live in the same repo as this record + pub publication: AtUri, + ///Publications this publication recommends + pub recommendations: Vec>, + #[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 RecommendationsGetRecordOutput { + #[serde(skip_serializing_if = "Option::is_none")] + pub cid: Option>, + pub uri: AtUri, + pub value: Recommendations, +} + +impl Recommendations { + 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 RecommendationsRecord; +impl XrpcResp for RecommendationsRecord { + const NSID: &'static str = "pub.leaflet.graph.recommendations"; + const ENCODING: &'static str = "application/json"; + type Output = RecommendationsGetRecordOutput; + type Err = RecordError; +} + +impl From> for Recommendations { + fn from(output: RecommendationsGetRecordOutput) -> Self { + output.value + } +} + +impl Collection for Recommendations { + const NSID: &'static str = "pub.leaflet.graph.recommendations"; + type Record = RecommendationsRecord; +} + +impl Collection for RecommendationsRecord { + const NSID: &'static str = "pub.leaflet.graph.recommendations"; + type Record = RecommendationsRecord; +} + +impl LexiconSchema for Recommendations { + fn nsid() -> &'static str { + "pub.leaflet.graph.recommendations" + } + fn def_name() -> &'static str { + "main" + } + fn lexicon_doc() -> LexiconDoc<'static> { + lexicon_doc_pub_leaflet_graph_recommendations() + } + fn validate(&self) -> Result<(), ConstraintError> { + { + let value = &self.recommendations; + #[allow(unused_comparisons)] + if value.len() > 3usize { + return Err(ConstraintError::MaxLength { + path: ValidationPath::from_field("recommendations"), + max: 3usize, + actual: value.len(), + }); + } + } + Ok(()) + } +} + +pub mod recommendations_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 Publication; + type Recommendations; + } + /// Empty state - all required fields are unset + pub struct Empty(()); + impl sealed::Sealed for Empty {} + impl State for Empty { + type Publication = Unset; + type Recommendations = Unset; + } + ///State transition - sets the `publication` field to Set + pub struct SetPublication(PhantomData St>); + impl sealed::Sealed for SetPublication {} + impl State for SetPublication { + type Publication = Set; + type Recommendations = St::Recommendations; + } + ///State transition - sets the `recommendations` field to Set + pub struct SetRecommendations(PhantomData St>); + impl sealed::Sealed for SetRecommendations {} + impl State for SetRecommendations { + type Publication = St::Publication; + type Recommendations = Set; + } + /// Marker types for field names + #[allow(non_camel_case_types)] + pub mod members { + ///Marker type for the `publication` field + pub struct publication(()); + ///Marker type for the `recommendations` field + pub struct recommendations(()); + } +} + +/// Builder for constructing an instance of this type. +pub struct RecommendationsBuilder { + _state: PhantomData St>, + _fields: (Option>, Option>>), + _type: PhantomData S>, +} + +impl Recommendations { + /// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed + pub fn new() -> RecommendationsBuilder { + RecommendationsBuilder::new() + } +} + +impl Recommendations { + /// Create a new builder for this type + pub fn builder() -> RecommendationsBuilder { + RecommendationsBuilder::builder() + } +} + +impl RecommendationsBuilder { + /// Create a new builder with all fields unset, using the default string type, if needed + pub fn new() -> Self { + RecommendationsBuilder { + _state: PhantomData, + _fields: (None, None), + _type: PhantomData, + } + } +} + +impl RecommendationsBuilder { + /// Create a new builder with all fields unset + pub fn builder() -> Self { + RecommendationsBuilder { + _state: PhantomData, + _fields: (None, None), + _type: PhantomData, + } + } +} + +impl RecommendationsBuilder +where + St: recommendations_state::State, + St::Publication: recommendations_state::IsUnset, +{ + /// Set the `publication` field (required) + pub fn publication( + mut self, + value: impl Into>, + ) -> RecommendationsBuilder, S> { + self._fields.0 = Option::Some(value.into()); + RecommendationsBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl RecommendationsBuilder +where + St: recommendations_state::State, + St::Recommendations: recommendations_state::IsUnset, +{ + /// Set the `recommendations` field (required) + pub fn recommendations( + mut self, + value: impl Into>>, + ) -> RecommendationsBuilder, S> { + self._fields.1 = Option::Some(value.into()); + RecommendationsBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl RecommendationsBuilder +where + St: recommendations_state::State, + St::Publication: recommendations_state::IsSet, + St::Recommendations: recommendations_state::IsSet, +{ + /// Build the final struct. + pub fn build(self) -> Recommendations { + Recommendations { + publication: self._fields.0.unwrap(), + recommendations: self._fields.1.unwrap(), + extra_data: Default::default(), + } + } + /// Build the final struct with custom extra_data. + pub fn build_with_data(self, extra_data: BTreeMap>) -> Recommendations { + Recommendations { + publication: self._fields.0.unwrap(), + recommendations: self._fields.1.unwrap(), + extra_data: Some(extra_data), + } + } +} + +fn lexicon_doc_pub_leaflet_graph_recommendations() -> 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("pub.leaflet.graph.recommendations"), + defs: { + let mut map = BTreeMap::new(); + map.insert( + SmolStr::new_static("main"), + LexUserType::Record(LexRecord { + description: Some( + CowStr::new_static( + "Record declaring the publications a publication recommends", + ), + ), + key: Some(CowStr::new_static("any")), + record: LexRecordRecord::Object(LexObject { + required: Some( + vec![ + SmolStr::new_static("publication"), + SmolStr::new_static("recommendations") + ], + ), + properties: { + #[allow(unused_mut)] + let mut map = BTreeMap::new(); + map.insert( + SmolStr::new_static("publication"), + LexObjectProperty::String(LexString { + description: Some( + CowStr::new_static( + "The publication making the recommendations; must live in the same repo as this record", + ), + ), + format: Some(LexStringFormat::AtUri), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("recommendations"), + LexObjectProperty::Array(LexArray { + description: Some( + CowStr::new_static( + "Publications this publication recommends", + ), + ), + items: LexArrayItem::String(LexString { + format: Some(LexStringFormat::AtUri), + ..Default::default() + }), + max_length: Some(3usize), + ..Default::default() + }), + ); + map + }, + ..Default::default() + }), + ..Default::default() + }), + ); + map + }, + ..Default::default() + } +} diff --git a/crates/jacquard-api/src/pub_leaflet/pages/canvas.rs b/crates/jacquard-api/src/pub_leaflet/pages/canvas.rs index 21f7d86fe..028a22e04 100644 --- a/crates/jacquard-api/src/pub_leaflet/pages/canvas.rs +++ b/crates/jacquard-api/src/pub_leaflet/pages/canvas.rs @@ -26,15 +26,19 @@ use crate::pub_leaflet::blocks::button::Button; use crate::pub_leaflet::blocks::code::Code; use crate::pub_leaflet::blocks::header::Header; use crate::pub_leaflet::blocks::horizontal_rule::HorizontalRule; +use crate::pub_leaflet::blocks::html::Html; use crate::pub_leaflet::blocks::iframe::Iframe; use crate::pub_leaflet::blocks::image::Image; +use crate::pub_leaflet::blocks::image_gallery::ImageGallery; use crate::pub_leaflet::blocks::math::Math; +use crate::pub_leaflet::blocks::members_only_delimiter::MembersOnlyDelimiter; use crate::pub_leaflet::blocks::ordered_list::OrderedList; use crate::pub_leaflet::blocks::page::Page; use crate::pub_leaflet::blocks::poll::Poll; use crate::pub_leaflet::blocks::posts_list::PostsList; use crate::pub_leaflet::blocks::signup::Signup; use crate::pub_leaflet::blocks::standard_site_post::StandardSitePost; +use crate::pub_leaflet::blocks::standard_site_publication::StandardSitePublication; use crate::pub_leaflet::blocks::text::Text; use crate::pub_leaflet::blocks::unordered_list::UnorderedList; use crate::pub_leaflet::blocks::website::Website; @@ -68,6 +72,8 @@ pub struct Block { pub enum BlockBlock { #[serde(rename = "pub.leaflet.blocks.iframe")] Iframe(Box>), + #[serde(rename = "pub.leaflet.blocks.html")] + Html(Box>), #[serde(rename = "pub.leaflet.blocks.text")] Text(Box>), #[serde(rename = "pub.leaflet.blocks.blockquote")] @@ -76,6 +82,8 @@ pub enum BlockBlock { Header(Box>), #[serde(rename = "pub.leaflet.blocks.image")] Image(Box>), + #[serde(rename = "pub.leaflet.blocks.imageGallery")] + ImageGallery(Box>), #[serde(rename = "pub.leaflet.blocks.unorderedList")] UnorderedList(Box>), #[serde(rename = "pub.leaflet.blocks.orderedList")] @@ -92,6 +100,8 @@ pub enum BlockBlock { BskyPost(Box>), #[serde(rename = "pub.leaflet.blocks.standardSitePost")] StandardSitePost(Box>), + #[serde(rename = "pub.leaflet.blocks.standardSitePublication")] + StandardSitePublication(Box>), #[serde(rename = "pub.leaflet.blocks.page")] Page(Box>), #[serde(rename = "pub.leaflet.blocks.poll")] @@ -102,6 +112,8 @@ pub enum BlockBlock { PostsList(Box>), #[serde(rename = "pub.leaflet.blocks.signup")] Signup(Box>), + #[serde(rename = "pub.leaflet.blocks.membersOnlyDelimiter")] + MembersOnlyDelimiter(Box>), } #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] @@ -503,10 +515,12 @@ fn lexicon_doc_pub_leaflet_pages_canvas() -> LexiconDoc<'static> { LexObjectProperty::Union(LexRefUnion { refs: vec![ CowStr::new_static("pub.leaflet.blocks.iframe"), + CowStr::new_static("pub.leaflet.blocks.html"), CowStr::new_static("pub.leaflet.blocks.text"), CowStr::new_static("pub.leaflet.blocks.blockquote"), CowStr::new_static("pub.leaflet.blocks.header"), CowStr::new_static("pub.leaflet.blocks.image"), + CowStr::new_static("pub.leaflet.blocks.imageGallery"), CowStr::new_static("pub.leaflet.blocks.unorderedList"), CowStr::new_static("pub.leaflet.blocks.orderedList"), CowStr::new_static("pub.leaflet.blocks.website"), @@ -515,11 +529,15 @@ fn lexicon_doc_pub_leaflet_pages_canvas() -> LexiconDoc<'static> { CowStr::new_static("pub.leaflet.blocks.horizontalRule"), CowStr::new_static("pub.leaflet.blocks.bskyPost"), CowStr::new_static("pub.leaflet.blocks.standardSitePost"), + CowStr::new_static( + "pub.leaflet.blocks.standardSitePublication", + ), CowStr::new_static("pub.leaflet.blocks.page"), CowStr::new_static("pub.leaflet.blocks.poll"), CowStr::new_static("pub.leaflet.blocks.button"), CowStr::new_static("pub.leaflet.blocks.postsList"), CowStr::new_static("pub.leaflet.blocks.signup"), + CowStr::new_static("pub.leaflet.blocks.membersOnlyDelimiter"), ], ..Default::default() }), diff --git a/crates/jacquard-api/src/pub_leaflet/pages/linear_document.rs b/crates/jacquard-api/src/pub_leaflet/pages/linear_document.rs index 34644a403..574994d13 100644 --- a/crates/jacquard-api/src/pub_leaflet/pages/linear_document.rs +++ b/crates/jacquard-api/src/pub_leaflet/pages/linear_document.rs @@ -26,15 +26,19 @@ use crate::pub_leaflet::blocks::button::Button; use crate::pub_leaflet::blocks::code::Code; use crate::pub_leaflet::blocks::header::Header; use crate::pub_leaflet::blocks::horizontal_rule::HorizontalRule; +use crate::pub_leaflet::blocks::html::Html; use crate::pub_leaflet::blocks::iframe::Iframe; use crate::pub_leaflet::blocks::image::Image; +use crate::pub_leaflet::blocks::image_gallery::ImageGallery; use crate::pub_leaflet::blocks::math::Math; +use crate::pub_leaflet::blocks::members_only_delimiter::MembersOnlyDelimiter; use crate::pub_leaflet::blocks::ordered_list::OrderedList; use crate::pub_leaflet::blocks::page::Page; use crate::pub_leaflet::blocks::poll::Poll; use crate::pub_leaflet::blocks::posts_list::PostsList; use crate::pub_leaflet::blocks::signup::Signup; use crate::pub_leaflet::blocks::standard_site_post::StandardSitePost; +use crate::pub_leaflet::blocks::standard_site_publication::StandardSitePublication; use crate::pub_leaflet::blocks::text::Text; use crate::pub_leaflet::blocks::unordered_list::UnorderedList; use crate::pub_leaflet::blocks::website::Website; @@ -147,6 +151,8 @@ where pub enum BlockBlock { #[serde(rename = "pub.leaflet.blocks.iframe")] Iframe(Box>), + #[serde(rename = "pub.leaflet.blocks.html")] + Html(Box>), #[serde(rename = "pub.leaflet.blocks.text")] Text(Box>), #[serde(rename = "pub.leaflet.blocks.blockquote")] @@ -155,6 +161,8 @@ pub enum BlockBlock { Header(Box>), #[serde(rename = "pub.leaflet.blocks.image")] Image(Box>), + #[serde(rename = "pub.leaflet.blocks.imageGallery")] + ImageGallery(Box>), #[serde(rename = "pub.leaflet.blocks.unorderedList")] UnorderedList(Box>), #[serde(rename = "pub.leaflet.blocks.orderedList")] @@ -171,6 +179,8 @@ pub enum BlockBlock { BskyPost(Box>), #[serde(rename = "pub.leaflet.blocks.standardSitePost")] StandardSitePost(Box>), + #[serde(rename = "pub.leaflet.blocks.standardSitePublication")] + StandardSitePublication(Box>), #[serde(rename = "pub.leaflet.blocks.page")] Page(Box>), #[serde(rename = "pub.leaflet.blocks.poll")] @@ -181,6 +191,8 @@ pub enum BlockBlock { PostsList(Box>), #[serde(rename = "pub.leaflet.blocks.signup")] Signup(Box>), + #[serde(rename = "pub.leaflet.blocks.membersOnlyDelimiter")] + MembersOnlyDelimiter(Box>), } #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] @@ -470,10 +482,12 @@ fn lexicon_doc_pub_leaflet_pages_linearDocument() -> LexiconDoc<'static> { LexObjectProperty::Union(LexRefUnion { refs: vec![ CowStr::new_static("pub.leaflet.blocks.iframe"), + CowStr::new_static("pub.leaflet.blocks.html"), CowStr::new_static("pub.leaflet.blocks.text"), CowStr::new_static("pub.leaflet.blocks.blockquote"), CowStr::new_static("pub.leaflet.blocks.header"), CowStr::new_static("pub.leaflet.blocks.image"), + CowStr::new_static("pub.leaflet.blocks.imageGallery"), CowStr::new_static("pub.leaflet.blocks.unorderedList"), CowStr::new_static("pub.leaflet.blocks.orderedList"), CowStr::new_static("pub.leaflet.blocks.website"), @@ -482,11 +496,15 @@ fn lexicon_doc_pub_leaflet_pages_linearDocument() -> LexiconDoc<'static> { CowStr::new_static("pub.leaflet.blocks.horizontalRule"), CowStr::new_static("pub.leaflet.blocks.bskyPost"), CowStr::new_static("pub.leaflet.blocks.standardSitePost"), + CowStr::new_static( + "pub.leaflet.blocks.standardSitePublication", + ), CowStr::new_static("pub.leaflet.blocks.page"), CowStr::new_static("pub.leaflet.blocks.poll"), CowStr::new_static("pub.leaflet.blocks.button"), CowStr::new_static("pub.leaflet.blocks.postsList"), CowStr::new_static("pub.leaflet.blocks.signup"), + CowStr::new_static("pub.leaflet.blocks.membersOnlyDelimiter"), ], ..Default::default() }), diff --git a/crates/jacquard-api/src/pub_leaflet/publication.rs b/crates/jacquard-api/src/pub_leaflet/publication.rs index e323d1194..0198451a1 100644 --- a/crates/jacquard-api/src/pub_leaflet/publication.rs +++ b/crates/jacquard-api/src/pub_leaflet/publication.rs @@ -75,6 +75,8 @@ pub struct PublicationGetRecordOutput { bound(deserialize = "S: Deserialize<'de> + BosStr") )] pub struct Preferences { + #[serde(skip_serializing_if = "Option::is_none")] + pub prev_next_direction: Option>, /// Defaults to `true`. #[serde(skip_serializing_if = "Option::is_none")] #[serde(default = "_default_preferences_show_comments")] @@ -103,6 +105,85 @@ pub struct Preferences { pub extra_data: Option>>, } +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub enum PreferencesPrevNextDirection { + Ltr, + Rtl, + Other(S), +} + +impl PreferencesPrevNextDirection { + pub fn as_str(&self) -> &str { + match self { + Self::Ltr => "ltr", + Self::Rtl => "rtl", + 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() { + "ltr" => Self::Ltr, + "rtl" => Self::Rtl, + _ => Self::Other(s), + } + } +} + +impl core::fmt::Display for PreferencesPrevNextDirection { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!(f, "{}", self.as_str()) + } +} + +impl AsRef for PreferencesPrevNextDirection { + fn as_ref(&self) -> &str { + self.as_str() + } +} + +impl Serialize for PreferencesPrevNextDirection { + 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 PreferencesPrevNextDirection { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = S::deserialize(deserializer)?; + Ok(Self::from_value(s)) + } +} + +impl Default for PreferencesPrevNextDirection { + fn default() -> Self { + Self::Other(Default::default()) + } +} + +impl jacquard_common::IntoStatic for PreferencesPrevNextDirection +where + S: BosStr + jacquard_common::IntoStatic, + S::Output: BosStr, +{ + type Output = PreferencesPrevNextDirection; + fn into_static(self) -> Self::Output { + match self { + PreferencesPrevNextDirection::Ltr => PreferencesPrevNextDirection::Ltr, + PreferencesPrevNextDirection::Rtl => PreferencesPrevNextDirection::Rtl, + PreferencesPrevNextDirection::Other(v) => { + PreferencesPrevNextDirection::Other(v.into_static()) + } + } + } +} + #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] #[serde( rename_all = "camelCase", @@ -629,6 +710,12 @@ fn lexicon_doc_pub_leaflet_publication() -> LexiconDoc<'static> { properties: { #[allow(unused_mut)] let mut map = BTreeMap::new(); + map.insert( + SmolStr::new_static("prevNextDirection"), + LexObjectProperty::String(LexString { + ..Default::default() + }), + ); map.insert( SmolStr::new_static("showComments"), LexObjectProperty::Boolean(LexBoolean { @@ -806,6 +893,7 @@ fn _default_preferences_show_recommends() -> Option { impl Default for Preferences { fn default() -> Self { Self { + prev_next_direction: None, show_comments: Some(true), show_first_last: Some(false), show_in_discover: Some(true), diff --git a/crates/jacquard-api/src/pub_quizzy/team_score.rs b/crates/jacquard-api/src/pub_quizzy/team_score.rs index ff5ac7139..90e118b7a 100644 --- a/crates/jacquard-api/src/pub_quizzy/team_score.rs +++ b/crates/jacquard-api/src/pub_quizzy/team_score.rs @@ -193,6 +193,15 @@ impl LexiconSchema for ScoredAnswer { }); } } + for value in &self.scores { + if *value < 0i64 { + return Err(ConstraintError::Minimum { + path: ValidationPath::from_field("scores"), + min: 0i64, + actual: *value, + }); + } + } Ok(()) } } diff --git a/crates/jacquard-api/src/science_alt/dataset/entry.rs b/crates/jacquard-api/src/science_alt/dataset/entry.rs index 2490957d8..322f5d07f 100644 --- a/crates/jacquard-api/src/science_alt/dataset/entry.rs +++ b/crates/jacquard-api/src/science_alt/dataset/entry.rs @@ -284,6 +284,18 @@ impl LexiconSchema for Entry { }); } } + if let Some(values) = &self.tags { + for value in values { + #[allow(unused_comparisons)] + if ::len(value.as_ref()) > 150usize { + return Err(ConstraintError::MaxLength { + path: ValidationPath::from_field("tags"), + max: 150usize, + actual: ::len(value.as_ref()), + }); + } + } + } Ok(()) } } diff --git a/crates/jacquard-api/src/science_alt/dataset/lens.rs b/crates/jacquard-api/src/science_alt/dataset/lens.rs index 47e917ab8..548f8897a 100644 --- a/crates/jacquard-api/src/science_alt/dataset/lens.rs +++ b/crates/jacquard-api/src/science_alt/dataset/lens.rs @@ -155,6 +155,16 @@ impl LexiconSchema for CodeReference { }); } } + if let Some(ref value) = self.language { + #[allow(unused_comparisons)] + if ::len(value.as_ref()) > 50usize { + return Err(ConstraintError::MaxLength { + path: ValidationPath::from_field("language"), + max: 50usize, + actual: ::len(value.as_ref()), + }); + } + } { let value = &self.path; #[allow(unused_comparisons)] diff --git a/crates/jacquard-api/src/science_alt/dataset/lens_verification.rs b/crates/jacquard-api/src/science_alt/dataset/lens_verification.rs index 3e1961cd4..44aee4cbd 100644 --- a/crates/jacquard-api/src/science_alt/dataset/lens_verification.rs +++ b/crates/jacquard-api/src/science_alt/dataset/lens_verification.rs @@ -201,6 +201,17 @@ impl LexiconSchema for LensVerification { }); } } + { + let value = &self.verification_method; + #[allow(unused_comparisons)] + if ::len(value.as_ref()) > 50usize { + return Err(ConstraintError::MaxLength { + path: ValidationPath::from_field("verification_method"), + max: 50usize, + actual: ::len(value.as_ref()), + }); + } + } Ok(()) } } diff --git a/crates/jacquard-api/src/science_alt/dataset/storage_external.rs b/crates/jacquard-api/src/science_alt/dataset/storage_external.rs index b686acd09..5714cd22b 100644 --- a/crates/jacquard-api/src/science_alt/dataset/storage_external.rs +++ b/crates/jacquard-api/src/science_alt/dataset/storage_external.rs @@ -60,6 +60,16 @@ impl LexiconSchema for StorageExternal { }); } } + for value in &self.urls { + #[allow(unused_comparisons)] + if ::len(value.as_ref()) > 1000usize { + return Err(ConstraintError::MaxLength { + path: ValidationPath::from_field("urls"), + max: 1000usize, + actual: ::len(value.as_ref()), + }); + } + } Ok(()) } } diff --git a/crates/jacquard-api/src/sh_tangled.rs b/crates/jacquard-api/src/sh_tangled.rs index 55ac754d7..3cad2ea3f 100644 --- a/crates/jacquard-api/src/sh_tangled.rs +++ b/crates/jacquard-api/src/sh_tangled.rs @@ -5,6 +5,7 @@ //! Generated bindings for the `sh.tangled` Lexicon namespace/module. pub mod actor; +pub mod ci; pub mod feed; pub mod git; pub mod graph; @@ -16,6 +17,7 @@ pub mod pipeline; pub mod publicKey; pub mod public_key; pub mod repo; +pub mod search; pub mod spindle; pub mod string; pub mod sync; diff --git a/crates/jacquard-api/src/sh_tangled/actor.rs b/crates/jacquard-api/src/sh_tangled/actor.rs index 62443f76a..f1de6ffc1 100644 --- a/crates/jacquard-api/src/sh_tangled/actor.rs +++ b/crates/jacquard-api/src/sh_tangled/actor.rs @@ -4,4 +4,6 @@ // Any manual changes will be overwritten on the next regeneration. //! Generated bindings for the `sh.tangled.actor` Lexicon namespace/module. +pub mod get_profile; +pub mod get_profiles; pub mod profile; diff --git a/crates/jacquard-api/src/sh_tangled/actor/get_profile.rs b/crates/jacquard-api/src/sh_tangled/actor/get_profile.rs new file mode 100644 index 000000000..929f3e35b --- /dev/null +++ b/crates/jacquard-api/src/sh_tangled/actor/get_profile.rs @@ -0,0 +1,177 @@ +// @generated by jacquard-lexicon. DO NOT EDIT. +// +// Lexicon: sh.tangled.actor.getProfile +// +// 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::deps::smol_str::SmolStr; +use jacquard_common::types::string::{AtUri, Cid}; +use jacquard_common::types::value::Data; +use jacquard_common::{BosStr, DefaultStr, FromStaticStr}; +use jacquard_derive::IntoStatic; +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct GetProfile { + pub actor: AtUri, +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct GetProfileOutput { + #[serde(skip_serializing_if = "Option::is_none")] + pub cid: Option>, + pub uri: AtUri, + ///Embedded sh.tangled.actor.profile record. + pub value: Data, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +/** Response marker for the `sh.tangled.actor.getProfile` query. + +Implements `jacquard_common::xrpc::XrpcResp`; successful bodies decode as `Self::Output`, which is `GetProfileOutput` for this endpoint.*/ +pub struct GetProfileResponse; +impl jacquard_common::xrpc::XrpcResp for GetProfileResponse { + const NSID: &'static str = "sh.tangled.actor.getProfile"; + const ENCODING: &'static str = "application/json"; + type Output = GetProfileOutput; + type Err = jacquard_common::xrpc::GenericError; +} + +impl jacquard_common::xrpc::XrpcRequest for GetProfile { + const NSID: &'static str = "sh.tangled.actor.getProfile"; + const METHOD: jacquard_common::xrpc::XrpcMethod = jacquard_common::xrpc::XrpcMethod::Query; + type Response = GetProfileResponse; +} + +/** Endpoint marker for the `sh.tangled.actor.getProfile` query. + +Path: `/xrpc/sh.tangled.actor.getProfile`. The request payload type is `GetProfile`; send that request with `jacquard::Client` or use this marker through lower-level `XrpcEndpoint` APIs.*/ +pub struct GetProfileRequest; +impl jacquard_common::xrpc::XrpcEndpoint for GetProfileRequest { + const PATH: &'static str = "/xrpc/sh.tangled.actor.getProfile"; + const METHOD: jacquard_common::xrpc::XrpcMethod = jacquard_common::xrpc::XrpcMethod::Query; + type Request = GetProfile; + type Response = GetProfileResponse; +} + +pub mod get_profile_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 Actor; + } + /// Empty state - all required fields are unset + pub struct Empty(()); + impl sealed::Sealed for Empty {} + impl State for Empty { + type Actor = Unset; + } + ///State transition - sets the `actor` field to Set + pub struct SetActor(PhantomData St>); + impl sealed::Sealed for SetActor {} + impl State for SetActor { + type Actor = Set; + } + /// Marker types for field names + #[allow(non_camel_case_types)] + pub mod members { + ///Marker type for the `actor` field + pub struct actor(()); + } +} + +/// Builder for constructing an instance of this type. +pub struct GetProfileBuilder { + _state: PhantomData St>, + _fields: (Option>,), + _type: PhantomData S>, +} + +impl GetProfile { + /// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed + pub fn new() -> GetProfileBuilder { + GetProfileBuilder::new() + } +} + +impl GetProfile { + /// Create a new builder for this type + pub fn builder() -> GetProfileBuilder { + GetProfileBuilder::builder() + } +} + +impl GetProfileBuilder { + /// Create a new builder with all fields unset, using the default string type, if needed + pub fn new() -> Self { + GetProfileBuilder { + _state: PhantomData, + _fields: (None,), + _type: PhantomData, + } + } +} + +impl GetProfileBuilder { + /// Create a new builder with all fields unset + pub fn builder() -> Self { + GetProfileBuilder { + _state: PhantomData, + _fields: (None,), + _type: PhantomData, + } + } +} + +impl GetProfileBuilder +where + St: get_profile_state::State, + St::Actor: get_profile_state::IsUnset, +{ + /// Set the `actor` field (required) + pub fn actor( + mut self, + value: impl Into>, + ) -> GetProfileBuilder, S> { + self._fields.0 = Option::Some(value.into()); + GetProfileBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl GetProfileBuilder +where + St: get_profile_state::State, + St::Actor: get_profile_state::IsSet, +{ + /// Build the final struct. + pub fn build(self) -> GetProfile { + GetProfile { + actor: self._fields.0.unwrap(), + } + } +} diff --git a/crates/jacquard-api/src/sh_tangled/actor/get_profiles.rs b/crates/jacquard-api/src/sh_tangled/actor/get_profiles.rs new file mode 100644 index 000000000..7fcdfa28c --- /dev/null +++ b/crates/jacquard-api/src/sh_tangled/actor/get_profiles.rs @@ -0,0 +1,453 @@ +// @generated by jacquard-lexicon. DO NOT EDIT. +// +// Lexicon: sh.tangled.actor.getProfiles +// +// 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, DefaultStr, FromStaticStr}; + +#[allow(unused_imports)] +use jacquard_common::deps::codegen::unicode_segmentation::UnicodeSegmentation; +use jacquard_common::deps::smol_str::SmolStr; +use jacquard_common::types::string::{AtUri, Cid}; +use jacquard_common::types::value::Data; +use jacquard_derive::IntoStatic; +use jacquard_lexicon::lexicon::LexiconDoc; +use jacquard_lexicon::schema::LexiconSchema; + +use crate::sh_tangled::actor::get_profiles; +#[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", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct GetProfiles { + pub actors: Vec>, +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct GetProfilesOutput { + pub items: Vec>, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct RecordView { + #[serde(skip_serializing_if = "Option::is_none")] + pub cid: Option>, + pub uri: AtUri, + ///Embedded sh.tangled.actor.profile record. + pub value: Data, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +/** Response marker for the `sh.tangled.actor.getProfiles` query. + +Implements `jacquard_common::xrpc::XrpcResp`; successful bodies decode as `Self::Output`, which is `GetProfilesOutput` for this endpoint.*/ +pub struct GetProfilesResponse; +impl jacquard_common::xrpc::XrpcResp for GetProfilesResponse { + const NSID: &'static str = "sh.tangled.actor.getProfiles"; + const ENCODING: &'static str = "application/json"; + type Output = GetProfilesOutput; + type Err = jacquard_common::xrpc::GenericError; +} + +impl jacquard_common::xrpc::XrpcRequest for GetProfiles { + const NSID: &'static str = "sh.tangled.actor.getProfiles"; + const METHOD: jacquard_common::xrpc::XrpcMethod = jacquard_common::xrpc::XrpcMethod::Query; + type Response = GetProfilesResponse; +} + +/** Endpoint marker for the `sh.tangled.actor.getProfiles` query. + +Path: `/xrpc/sh.tangled.actor.getProfiles`. The request payload type is `GetProfiles`; send that request with `jacquard::Client` or use this marker through lower-level `XrpcEndpoint` APIs.*/ +pub struct GetProfilesRequest; +impl jacquard_common::xrpc::XrpcEndpoint for GetProfilesRequest { + const PATH: &'static str = "/xrpc/sh.tangled.actor.getProfiles"; + const METHOD: jacquard_common::xrpc::XrpcMethod = jacquard_common::xrpc::XrpcMethod::Query; + type Request = GetProfiles; + type Response = GetProfilesResponse; +} + +impl LexiconSchema for RecordView { + fn nsid() -> &'static str { + "sh.tangled.actor.getProfiles" + } + fn def_name() -> &'static str { + "recordView" + } + fn lexicon_doc() -> LexiconDoc<'static> { + lexicon_doc_sh_tangled_actor_getProfiles() + } + fn validate(&self) -> Result<(), ConstraintError> { + Ok(()) + } +} + +pub mod get_profiles_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 Actors; + } + /// Empty state - all required fields are unset + pub struct Empty(()); + impl sealed::Sealed for Empty {} + impl State for Empty { + type Actors = Unset; + } + ///State transition - sets the `actors` field to Set + pub struct SetActors(PhantomData St>); + impl sealed::Sealed for SetActors {} + impl State for SetActors { + type Actors = Set; + } + /// Marker types for field names + #[allow(non_camel_case_types)] + pub mod members { + ///Marker type for the `actors` field + pub struct actors(()); + } +} + +/// Builder for constructing an instance of this type. +pub struct GetProfilesBuilder { + _state: PhantomData St>, + _fields: (Option>>,), + _type: PhantomData S>, +} + +impl GetProfiles { + /// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed + pub fn new() -> GetProfilesBuilder { + GetProfilesBuilder::new() + } +} + +impl GetProfiles { + /// Create a new builder for this type + pub fn builder() -> GetProfilesBuilder { + GetProfilesBuilder::builder() + } +} + +impl GetProfilesBuilder { + /// Create a new builder with all fields unset, using the default string type, if needed + pub fn new() -> Self { + GetProfilesBuilder { + _state: PhantomData, + _fields: (None,), + _type: PhantomData, + } + } +} + +impl GetProfilesBuilder { + /// Create a new builder with all fields unset + pub fn builder() -> Self { + GetProfilesBuilder { + _state: PhantomData, + _fields: (None,), + _type: PhantomData, + } + } +} + +impl GetProfilesBuilder +where + St: get_profiles_state::State, + St::Actors: get_profiles_state::IsUnset, +{ + /// Set the `actors` field (required) + pub fn actors( + mut self, + value: impl Into>>, + ) -> GetProfilesBuilder, S> { + self._fields.0 = Option::Some(value.into()); + GetProfilesBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl GetProfilesBuilder +where + St: get_profiles_state::State, + St::Actors: get_profiles_state::IsSet, +{ + /// Build the final struct. + pub fn build(self) -> GetProfiles { + GetProfiles { + actors: self._fields.0.unwrap(), + } + } +} + +pub mod record_view_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 Uri; + type Value; + } + /// Empty state - all required fields are unset + pub struct Empty(()); + impl sealed::Sealed for Empty {} + impl State for Empty { + type Uri = Unset; + type Value = Unset; + } + ///State transition - sets the `uri` field to Set + pub struct SetUri(PhantomData St>); + impl sealed::Sealed for SetUri {} + impl State for SetUri { + type Uri = Set; + type Value = St::Value; + } + ///State transition - sets the `value` field to Set + pub struct SetValue(PhantomData St>); + impl sealed::Sealed for SetValue {} + impl State for SetValue { + type Uri = St::Uri; + type Value = Set; + } + /// Marker types for field names + #[allow(non_camel_case_types)] + pub mod members { + ///Marker type for the `uri` field + pub struct uri(()); + ///Marker type for the `value` field + pub struct value(()); + } +} + +/// Builder for constructing an instance of this type. +pub struct RecordViewBuilder { + _state: PhantomData St>, + _fields: (Option>, Option>, Option>), + _type: PhantomData S>, +} + +impl RecordView { + /// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed + pub fn new() -> RecordViewBuilder { + RecordViewBuilder::new() + } +} + +impl RecordView { + /// Create a new builder for this type + pub fn builder() -> RecordViewBuilder { + RecordViewBuilder::builder() + } +} + +impl RecordViewBuilder { + /// Create a new builder with all fields unset, using the default string type, if needed + pub fn new() -> Self { + RecordViewBuilder { + _state: PhantomData, + _fields: (None, None, None), + _type: PhantomData, + } + } +} + +impl RecordViewBuilder { + /// Create a new builder with all fields unset + pub fn builder() -> Self { + RecordViewBuilder { + _state: PhantomData, + _fields: (None, None, None), + _type: PhantomData, + } + } +} + +impl RecordViewBuilder { + /// Set the `cid` field (optional) + pub fn cid(mut self, value: impl Into>>) -> Self { + self._fields.0 = value.into(); + self + } + /// Set the `cid` field to an Option value (optional) + pub fn maybe_cid(mut self, value: Option>) -> Self { + self._fields.0 = value; + self + } +} + +impl RecordViewBuilder +where + St: record_view_state::State, + St::Uri: record_view_state::IsUnset, +{ + /// Set the `uri` field (required) + pub fn uri( + mut self, + value: impl Into>, + ) -> RecordViewBuilder, S> { + self._fields.1 = Option::Some(value.into()); + RecordViewBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl RecordViewBuilder +where + St: record_view_state::State, + St::Value: record_view_state::IsUnset, +{ + /// Set the `value` field (required) + pub fn value( + mut self, + value: impl Into>, + ) -> RecordViewBuilder, S> { + self._fields.2 = Option::Some(value.into()); + RecordViewBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl RecordViewBuilder +where + St: record_view_state::State, + St::Uri: record_view_state::IsSet, + St::Value: record_view_state::IsSet, +{ + /// Build the final struct. + pub fn build(self) -> RecordView { + RecordView { + cid: self._fields.0, + uri: self._fields.1.unwrap(), + value: 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>) -> RecordView { + RecordView { + cid: self._fields.0, + uri: self._fields.1.unwrap(), + value: self._fields.2.unwrap(), + extra_data: Some(extra_data), + } + } +} + +fn lexicon_doc_sh_tangled_actor_getProfiles() -> 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.actor.getProfiles"), + defs: { + let mut map = BTreeMap::new(); + map.insert( + SmolStr::new_static("main"), + LexUserType::XrpcQuery(LexXrpcQuery { + parameters: Some(LexXrpcQueryParameter::Params(LexXrpcParameters { + required: Some(vec![SmolStr::new_static("actors")]), + properties: { + #[allow(unused_mut)] + let mut map = BTreeMap::new(); + map.insert( + SmolStr::new_static("actors"), + LexXrpcParametersProperty::Array(LexPrimitiveArray { + items: LexPrimitiveArrayItem::String(LexString { + format: Some(LexStringFormat::AtUri), + ..Default::default() + }), + max_length: Some(50usize), + ..Default::default() + }), + ); + map + }, + ..Default::default() + })), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("recordView"), + LexUserType::Object(LexObject { + required: Some(vec![ + SmolStr::new_static("uri"), + SmolStr::new_static("value"), + ]), + properties: { + #[allow(unused_mut)] + let mut map = BTreeMap::new(); + map.insert( + SmolStr::new_static("cid"), + LexObjectProperty::String(LexString { + format: Some(LexStringFormat::Cid), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("uri"), + LexObjectProperty::String(LexString { + format: Some(LexStringFormat::AtUri), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("value"), + LexObjectProperty::Unknown(LexUnknown { + ..Default::default() + }), + ); + map + }, + ..Default::default() + }), + ); + map + }, + ..Default::default() + } +} diff --git a/crates/jacquard-api/src/sh_tangled/ci.rs b/crates/jacquard-api/src/sh_tangled/ci.rs new file mode 100644 index 000000000..77ab2b6e6 --- /dev/null +++ b/crates/jacquard-api/src/sh_tangled/ci.rs @@ -0,0 +1,16 @@ +// @generated by jacquard-lexicon. DO NOT EDIT. +// +// This file was automatically generated from Lexicon schemas. +// Any manual changes will be overwritten on the next regeneration. + +//! Generated bindings for the `sh.tangled.ci` Lexicon namespace/module. +pub mod cancel_pipeline; +pub mod describe_workflow_definition; +pub mod get_pipeline; +pub mod pipeline; +pub mod query_pipelines; + +#[cfg(feature = "streaming")] +pub mod subscribe_pipeline_logs; +pub mod trigger; +pub mod trigger_pipeline; diff --git a/crates/jacquard-api/src/sh_tangled/ci/cancel_pipeline.rs b/crates/jacquard-api/src/sh_tangled/ci/cancel_pipeline.rs new file mode 100644 index 000000000..8a1296678 --- /dev/null +++ b/crates/jacquard-api/src/sh_tangled/ci/cancel_pipeline.rs @@ -0,0 +1,229 @@ +// @generated by jacquard-lexicon. DO NOT EDIT. +// +// Lexicon: sh.tangled.ci.cancelPipeline +// +// 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::deps::smol_str::SmolStr; +use jacquard_common::types::string::{Did, Tid}; +use jacquard_common::types::value::Data; +use jacquard_common::{BosStr, CowStr, DefaultStr, FromStaticStr}; +use jacquard_derive::IntoStatic; +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct CancelPipeline { + ///pipeline TID + pub pipeline: Tid, + ///git repository DID + pub repo: Did, + ///Workflow names to filter. When not provided, entire pipeline will be canceled. + #[serde(skip_serializing_if = "Option::is_none")] + pub workflows: Option>, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +/** Response marker for the `sh.tangled.ci.cancelPipeline` procedure. + +Implements `jacquard_common::xrpc::XrpcResp`; successful bodies decode as `Self::Output`, which is `()` for this endpoint.*/ +pub struct CancelPipelineResponse; +impl jacquard_common::xrpc::XrpcResp for CancelPipelineResponse { + const NSID: &'static str = "sh.tangled.ci.cancelPipeline"; + const ENCODING: &'static str = "application/json"; + type Output = (); + type Err = jacquard_common::xrpc::GenericError; +} + +impl jacquard_common::xrpc::XrpcRequest for CancelPipeline { + const NSID: &'static str = "sh.tangled.ci.cancelPipeline"; + const METHOD: jacquard_common::xrpc::XrpcMethod = + jacquard_common::xrpc::XrpcMethod::Procedure("application/json"); + type Response = CancelPipelineResponse; +} + +/** Endpoint marker for the `sh.tangled.ci.cancelPipeline` procedure. + +Path: `/xrpc/sh.tangled.ci.cancelPipeline`. The request payload type is `CancelPipeline`; send that request with `jacquard::Client` or use this marker through lower-level `XrpcEndpoint` APIs.*/ +pub struct CancelPipelineRequest; +impl jacquard_common::xrpc::XrpcEndpoint for CancelPipelineRequest { + const PATH: &'static str = "/xrpc/sh.tangled.ci.cancelPipeline"; + const METHOD: jacquard_common::xrpc::XrpcMethod = + jacquard_common::xrpc::XrpcMethod::Procedure("application/json"); + type Request = CancelPipeline; + type Response = CancelPipelineResponse; +} + +pub mod cancel_pipeline_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 Pipeline; + type Repo; + } + /// Empty state - all required fields are unset + pub struct Empty(()); + impl sealed::Sealed for Empty {} + impl State for Empty { + type Pipeline = Unset; + type Repo = Unset; + } + ///State transition - sets the `pipeline` field to Set + pub struct SetPipeline(PhantomData St>); + impl sealed::Sealed for SetPipeline {} + impl State for SetPipeline { + type Pipeline = Set; + type Repo = St::Repo; + } + ///State transition - sets the `repo` field to Set + pub struct SetRepo(PhantomData St>); + impl sealed::Sealed for SetRepo {} + impl State for SetRepo { + type Pipeline = St::Pipeline; + type Repo = Set; + } + /// Marker types for field names + #[allow(non_camel_case_types)] + pub mod members { + ///Marker type for the `pipeline` field + pub struct pipeline(()); + ///Marker type for the `repo` field + pub struct repo(()); + } +} + +/// Builder for constructing an instance of this type. +pub struct CancelPipelineBuilder { + _state: PhantomData St>, + _fields: (Option, Option>, Option>), + _type: PhantomData S>, +} + +impl CancelPipeline { + /// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed + pub fn new() -> CancelPipelineBuilder { + CancelPipelineBuilder::new() + } +} + +impl CancelPipeline { + /// Create a new builder for this type + pub fn builder() -> CancelPipelineBuilder { + CancelPipelineBuilder::builder() + } +} + +impl CancelPipelineBuilder { + /// Create a new builder with all fields unset, using the default string type, if needed + pub fn new() -> Self { + CancelPipelineBuilder { + _state: PhantomData, + _fields: (None, None, None), + _type: PhantomData, + } + } +} + +impl CancelPipelineBuilder { + /// Create a new builder with all fields unset + pub fn builder() -> Self { + CancelPipelineBuilder { + _state: PhantomData, + _fields: (None, None, None), + _type: PhantomData, + } + } +} + +impl CancelPipelineBuilder +where + St: cancel_pipeline_state::State, + St::Pipeline: cancel_pipeline_state::IsUnset, +{ + /// Set the `pipeline` field (required) + pub fn pipeline( + mut self, + value: impl Into, + ) -> CancelPipelineBuilder, S> { + self._fields.0 = Option::Some(value.into()); + CancelPipelineBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl CancelPipelineBuilder +where + St: cancel_pipeline_state::State, + St::Repo: cancel_pipeline_state::IsUnset, +{ + /// Set the `repo` field (required) + pub fn repo( + mut self, + value: impl Into>, + ) -> CancelPipelineBuilder, S> { + self._fields.1 = Option::Some(value.into()); + CancelPipelineBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl CancelPipelineBuilder { + /// Set the `workflows` field (optional) + pub fn workflows(mut self, value: impl Into>>) -> Self { + self._fields.2 = value.into(); + self + } + /// Set the `workflows` field to an Option value (optional) + pub fn maybe_workflows(mut self, value: Option>) -> Self { + self._fields.2 = value; + self + } +} + +impl CancelPipelineBuilder +where + St: cancel_pipeline_state::State, + St::Pipeline: cancel_pipeline_state::IsSet, + St::Repo: cancel_pipeline_state::IsSet, +{ + /// Build the final struct. + pub fn build(self) -> CancelPipeline { + CancelPipeline { + pipeline: self._fields.0.unwrap(), + repo: self._fields.1.unwrap(), + workflows: self._fields.2, + extra_data: Default::default(), + } + } + /// Build the final struct with custom extra_data. + pub fn build_with_data(self, extra_data: BTreeMap>) -> CancelPipeline { + CancelPipeline { + pipeline: self._fields.0.unwrap(), + repo: self._fields.1.unwrap(), + workflows: self._fields.2, + extra_data: Some(extra_data), + } + } +} diff --git a/crates/jacquard-api/src/sh_tangled/ci/describe_workflow_definition.rs b/crates/jacquard-api/src/sh_tangled/ci/describe_workflow_definition.rs new file mode 100644 index 000000000..ad28cca69 --- /dev/null +++ b/crates/jacquard-api/src/sh_tangled/ci/describe_workflow_definition.rs @@ -0,0 +1,275 @@ +// @generated by jacquard-lexicon. DO NOT EDIT. +// +// Lexicon: sh.tangled.ci.describeWorkflowDefinition +// +// 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::deps::smol_str::SmolStr; +use jacquard_common::types::string::Did; +use jacquard_common::types::value::Data; +use jacquard_common::{BosStr, CowStr, DefaultStr, FromStaticStr}; +use jacquard_derive::{IntoStatic, open_union}; +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct DescribeWorkflowDefinition { + pub repo: Did, + pub sha: S, + #[serde(skip_serializing_if = "Option::is_none")] + pub source_repo: Option>, +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct DescribeWorkflowDefinitionOutput { + ///Whether the workflow definition is derived from this repository at all. When false, no commit-to-commit comparison is meaningful (e.g. definitions managed externally), and callers should not surface change warnings. + pub derived: bool, + ///Fingerprint of the workflow definition as resolved by the spindle. Absent when derived is false. + #[serde(skip_serializing_if = "Option::is_none")] + pub hash: Option, + ///Names or paths of the effective workflow files that produced the hash. + #[serde(skip_serializing_if = "Option::is_none")] + pub workflows: Option>, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +#[derive( + Serialize, Deserialize, Debug, Clone, PartialEq, Eq, thiserror::Error, miette::Diagnostic, +)] +#[serde(tag = "error", content = "message")] +pub enum DescribeWorkflowDefinitionError { + /// Invalid request parameters + #[serde(rename = "InvalidRequest")] + InvalidRequest(Option), + /// Catch-all for unknown error codes. + #[serde(untagged)] + Other { + error: SmolStr, + message: Option, + }, +} + +impl core::fmt::Display for DescribeWorkflowDefinitionError { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + match self { + Self::InvalidRequest(msg) => { + write!(f, "InvalidRequest")?; + if let Some(msg) = msg { + write!(f, ": {}", msg)?; + } + Ok(()) + } + Self::Other { error, message } => { + write!(f, "{}", error)?; + if let Some(msg) = message { + write!(f, ": {}", msg)?; + } + Ok(()) + } + } + } +} + +/** Response marker for the `sh.tangled.ci.describeWorkflowDefinition` query. + +Implements `jacquard_common::xrpc::XrpcResp`; successful bodies decode as `Self::Output`, which is `DescribeWorkflowDefinitionOutput` for this endpoint.*/ +pub struct DescribeWorkflowDefinitionResponse; +impl jacquard_common::xrpc::XrpcResp for DescribeWorkflowDefinitionResponse { + const NSID: &'static str = "sh.tangled.ci.describeWorkflowDefinition"; + const ENCODING: &'static str = "application/json"; + type Output = DescribeWorkflowDefinitionOutput; + type Err = DescribeWorkflowDefinitionError; +} + +impl jacquard_common::xrpc::XrpcRequest for DescribeWorkflowDefinition { + const NSID: &'static str = "sh.tangled.ci.describeWorkflowDefinition"; + const METHOD: jacquard_common::xrpc::XrpcMethod = jacquard_common::xrpc::XrpcMethod::Query; + type Response = DescribeWorkflowDefinitionResponse; +} + +/** Endpoint marker for the `sh.tangled.ci.describeWorkflowDefinition` query. + +Path: `/xrpc/sh.tangled.ci.describeWorkflowDefinition`. The request payload type is `DescribeWorkflowDefinition`; send that request with `jacquard::Client` or use this marker through lower-level `XrpcEndpoint` APIs.*/ +pub struct DescribeWorkflowDefinitionRequest; +impl jacquard_common::xrpc::XrpcEndpoint for DescribeWorkflowDefinitionRequest { + const PATH: &'static str = "/xrpc/sh.tangled.ci.describeWorkflowDefinition"; + const METHOD: jacquard_common::xrpc::XrpcMethod = jacquard_common::xrpc::XrpcMethod::Query; + type Request = DescribeWorkflowDefinition; + type Response = DescribeWorkflowDefinitionResponse; +} + +pub mod describe_workflow_definition_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 Repo; + type Sha; + } + /// Empty state - all required fields are unset + pub struct Empty(()); + impl sealed::Sealed for Empty {} + impl State for Empty { + type Repo = Unset; + type Sha = Unset; + } + ///State transition - sets the `repo` field to Set + pub struct SetRepo(PhantomData St>); + impl sealed::Sealed for SetRepo {} + impl State for SetRepo { + type Repo = Set; + type Sha = St::Sha; + } + ///State transition - sets the `sha` field to Set + pub struct SetSha(PhantomData St>); + impl sealed::Sealed for SetSha {} + impl State for SetSha { + type Repo = St::Repo; + type Sha = Set; + } + /// Marker types for field names + #[allow(non_camel_case_types)] + pub mod members { + ///Marker type for the `repo` field + pub struct repo(()); + ///Marker type for the `sha` field + pub struct sha(()); + } +} + +/// Builder for constructing an instance of this type. +pub struct DescribeWorkflowDefinitionBuilder< + St: describe_workflow_definition_state::State, + S: BosStr = DefaultStr, +> { + _state: PhantomData St>, + _fields: (Option>, Option, Option>), + _type: PhantomData S>, +} + +impl DescribeWorkflowDefinition { + /// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed + pub fn new() + -> DescribeWorkflowDefinitionBuilder + { + DescribeWorkflowDefinitionBuilder::new() + } +} + +impl DescribeWorkflowDefinition { + /// Create a new builder for this type + pub fn builder() + -> DescribeWorkflowDefinitionBuilder { + DescribeWorkflowDefinitionBuilder::builder() + } +} + +impl DescribeWorkflowDefinitionBuilder { + /// Create a new builder with all fields unset, using the default string type, if needed + pub fn new() -> Self { + DescribeWorkflowDefinitionBuilder { + _state: PhantomData, + _fields: (None, None, None), + _type: PhantomData, + } + } +} + +impl DescribeWorkflowDefinitionBuilder { + /// Create a new builder with all fields unset + pub fn builder() -> Self { + DescribeWorkflowDefinitionBuilder { + _state: PhantomData, + _fields: (None, None, None), + _type: PhantomData, + } + } +} + +impl DescribeWorkflowDefinitionBuilder +where + St: describe_workflow_definition_state::State, + St::Repo: describe_workflow_definition_state::IsUnset, +{ + /// Set the `repo` field (required) + pub fn repo( + mut self, + value: impl Into>, + ) -> DescribeWorkflowDefinitionBuilder, S> { + self._fields.0 = Option::Some(value.into()); + DescribeWorkflowDefinitionBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl DescribeWorkflowDefinitionBuilder +where + St: describe_workflow_definition_state::State, + St::Sha: describe_workflow_definition_state::IsUnset, +{ + /// Set the `sha` field (required) + pub fn sha( + mut self, + value: impl Into, + ) -> DescribeWorkflowDefinitionBuilder, S> { + self._fields.1 = Option::Some(value.into()); + DescribeWorkflowDefinitionBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl + DescribeWorkflowDefinitionBuilder +{ + /// Set the `sourceRepo` field (optional) + pub fn source_repo(mut self, value: impl Into>>) -> Self { + self._fields.2 = value.into(); + self + } + /// Set the `sourceRepo` field to an Option value (optional) + pub fn maybe_source_repo(mut self, value: Option>) -> Self { + self._fields.2 = value; + self + } +} + +impl DescribeWorkflowDefinitionBuilder +where + St: describe_workflow_definition_state::State, + St::Repo: describe_workflow_definition_state::IsSet, + St::Sha: describe_workflow_definition_state::IsSet, +{ + /// Build the final struct. + pub fn build(self) -> DescribeWorkflowDefinition { + DescribeWorkflowDefinition { + repo: self._fields.0.unwrap(), + sha: self._fields.1.unwrap(), + source_repo: self._fields.2, + } + } +} diff --git a/crates/jacquard-api/src/sh_tangled/ci/get_pipeline.rs b/crates/jacquard-api/src/sh_tangled/ci/get_pipeline.rs new file mode 100644 index 000000000..435ff2cfb --- /dev/null +++ b/crates/jacquard-api/src/sh_tangled/ci/get_pipeline.rs @@ -0,0 +1,208 @@ +// @generated by jacquard-lexicon. DO NOT EDIT. +// +// Lexicon: sh.tangled.ci.getPipeline +// +// 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; + +use crate::sh_tangled::ci::pipeline::Pipeline; +#[allow(unused_imports)] +use core::marker::PhantomData; +use jacquard_common::deps::smol_str::SmolStr; +use jacquard_common::types::string::Tid; +use jacquard_common::types::value::Data; +use jacquard_common::{BosStr, CowStr, DefaultStr, FromStaticStr}; +use jacquard_derive::{IntoStatic, open_union}; +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde(rename_all = "camelCase")] +pub struct GetPipeline { + pub pipeline: Tid, +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct GetPipelineOutput { + #[serde(flatten)] + pub value: Pipeline, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +#[derive( + Serialize, Deserialize, Debug, Clone, PartialEq, Eq, thiserror::Error, miette::Diagnostic, +)] +#[serde(tag = "error", content = "message")] +pub enum GetPipelineError { + /// Pipeline not found + #[serde(rename = "PipelineNotFound")] + PipelineNotFound(Option), + /// Invalid request parameters + #[serde(rename = "InvalidRequest")] + InvalidRequest(Option), + /// Catch-all for unknown error codes. + #[serde(untagged)] + Other { + error: SmolStr, + message: Option, + }, +} + +impl core::fmt::Display for GetPipelineError { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + match self { + Self::PipelineNotFound(msg) => { + write!(f, "PipelineNotFound")?; + if let Some(msg) = msg { + write!(f, ": {}", msg)?; + } + Ok(()) + } + Self::InvalidRequest(msg) => { + write!(f, "InvalidRequest")?; + if let Some(msg) = msg { + write!(f, ": {}", msg)?; + } + Ok(()) + } + Self::Other { error, message } => { + write!(f, "{}", error)?; + if let Some(msg) = message { + write!(f, ": {}", msg)?; + } + Ok(()) + } + } + } +} + +/** Response marker for the `sh.tangled.ci.getPipeline` query. + +Implements `jacquard_common::xrpc::XrpcResp`; successful bodies decode as `Self::Output`, which is `GetPipelineOutput` for this endpoint.*/ +pub struct GetPipelineResponse; +impl jacquard_common::xrpc::XrpcResp for GetPipelineResponse { + const NSID: &'static str = "sh.tangled.ci.getPipeline"; + const ENCODING: &'static str = "application/json"; + type Output = GetPipelineOutput; + type Err = GetPipelineError; +} + +impl jacquard_common::xrpc::XrpcRequest for GetPipeline { + const NSID: &'static str = "sh.tangled.ci.getPipeline"; + const METHOD: jacquard_common::xrpc::XrpcMethod = jacquard_common::xrpc::XrpcMethod::Query; + type Response = GetPipelineResponse; +} + +/** Endpoint marker for the `sh.tangled.ci.getPipeline` query. + +Path: `/xrpc/sh.tangled.ci.getPipeline`. The request payload type is `GetPipeline`; send that request with `jacquard::Client` or use this marker through lower-level `XrpcEndpoint` APIs.*/ +pub struct GetPipelineRequest; +impl jacquard_common::xrpc::XrpcEndpoint for GetPipelineRequest { + const PATH: &'static str = "/xrpc/sh.tangled.ci.getPipeline"; + const METHOD: jacquard_common::xrpc::XrpcMethod = jacquard_common::xrpc::XrpcMethod::Query; + type Request = GetPipeline; + type Response = GetPipelineResponse; +} + +pub mod get_pipeline_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 Pipeline; + } + /// Empty state - all required fields are unset + pub struct Empty(()); + impl sealed::Sealed for Empty {} + impl State for Empty { + type Pipeline = Unset; + } + ///State transition - sets the `pipeline` field to Set + pub struct SetPipeline(PhantomData St>); + impl sealed::Sealed for SetPipeline {} + impl State for SetPipeline { + type Pipeline = Set; + } + /// Marker types for field names + #[allow(non_camel_case_types)] + pub mod members { + ///Marker type for the `pipeline` field + pub struct pipeline(()); + } +} + +/// Builder for constructing an instance of this type. +pub struct GetPipelineBuilder { + _state: PhantomData St>, + _fields: (Option,), +} + +impl GetPipeline { + /// Create a new builder for this type. + pub fn new() -> GetPipelineBuilder { + GetPipelineBuilder::new() + } +} + +impl GetPipelineBuilder { + /// Create a new builder with all fields unset, using the default string type, if needed + pub fn new() -> Self { + GetPipelineBuilder { + _state: PhantomData, + _fields: (None,), + } + } +} + +impl GetPipelineBuilder { + /// Create a new builder with all fields unset + pub fn builder() -> Self { + GetPipelineBuilder { + _state: PhantomData, + _fields: (None,), + } + } +} + +impl GetPipelineBuilder +where + St: get_pipeline_state::State, + St::Pipeline: get_pipeline_state::IsUnset, +{ + /// Set the `pipeline` field (required) + pub fn pipeline( + mut self, + value: impl Into, + ) -> GetPipelineBuilder> { + self._fields.0 = Option::Some(value.into()); + GetPipelineBuilder { + _state: PhantomData, + _fields: self._fields, + } + } +} + +impl GetPipelineBuilder +where + St: get_pipeline_state::State, + St::Pipeline: get_pipeline_state::IsSet, +{ + /// Build the final struct. + pub fn build(self) -> GetPipeline { + GetPipeline { + pipeline: self._fields.0.unwrap(), + } + } +} diff --git a/crates/jacquard-api/src/sh_tangled/ci/pipeline.rs b/crates/jacquard-api/src/sh_tangled/ci/pipeline.rs new file mode 100644 index 000000000..7886baf1b --- /dev/null +++ b/crates/jacquard-api/src/sh_tangled/ci/pipeline.rs @@ -0,0 +1,619 @@ +// @generated by jacquard-lexicon. DO NOT EDIT. +// +// Lexicon: sh.tangled.ci.pipeline +// +// 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::string::{Datetime, Did}; +use jacquard_common::types::value::Data; +use jacquard_derive::{IntoStatic, open_union}; +use jacquard_lexicon::lexicon::LexiconDoc; +use jacquard_lexicon::schema::LexiconSchema; + +use crate::sh_tangled::ci::pipeline; +use crate::sh_tangled::ci::trigger::Manual; +use crate::sh_tangled::ci::trigger::PullRequest; +use crate::sh_tangled::ci::trigger::Push; +#[allow(unused_imports)] +use jacquard_lexicon::validation::{ConstraintError, ValidationPath}; +use serde::{Deserialize, Serialize}; +/// A CI pipeline. Record-like, but owned by the spindle rather than a PDS. + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct Pipeline { + ///Commit Id this pipeline is running on + pub commit: S, + #[serde(skip_serializing_if = "Option::is_none")] + pub created_at: Option, + ///Spindle-local pipeline id + pub id: S, + ///Repository DID + #[serde(skip_serializing_if = "Option::is_none")] + pub repo: Option>, + ///Repository DID that the commit was checked out from, if different from repo (e.g. a fork for a fork-based pull request) + #[serde(skip_serializing_if = "Option::is_none")] + pub source_repo: Option>, + ///Trigger event metadata + pub trigger: PipelineTrigger, + ///Triggered workflows + pub workflows: Vec>, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +#[open_union] +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde(tag = "$type", bound(deserialize = "S: Deserialize<'de> + BosStr"))] +pub enum PipelineTrigger { + #[serde(rename = "sh.tangled.ci.trigger#push")] + TriggerPush(Box>), + #[serde(rename = "sh.tangled.ci.trigger#pullRequest")] + TriggerPullRequest(Box>), + #[serde(rename = "sh.tangled.ci.trigger#manual")] + TriggerManual(Box>), +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic, Default)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct Workflow { + #[serde(skip_serializing_if = "Option::is_none")] + pub error: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub finished_at: Option, + ///Spindle-local workflow id. Unique per pipeline, usually same as name. + pub id: S, + ///Name of the workflow + pub name: S, + #[serde(skip_serializing_if = "Option::is_none")] + pub started_at: Option, + ///Workflow status + pub status: S, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +impl LexiconSchema for Pipeline { + fn nsid() -> &'static str { + "sh.tangled.ci.pipeline" + } + fn def_name() -> &'static str { + "main" + } + fn lexicon_doc() -> LexiconDoc<'static> { + lexicon_doc_sh_tangled_ci_pipeline() + } + fn validate(&self) -> Result<(), ConstraintError> { + { + let value = &self.workflows; + #[allow(unused_comparisons)] + if value.len() > 50usize { + return Err(ConstraintError::MaxLength { + path: ValidationPath::from_field("workflows"), + max: 50usize, + actual: value.len(), + }); + } + } + { + let value = &self.workflows; + #[allow(unused_comparisons)] + if value.len() < 1usize { + return Err(ConstraintError::MinLength { + path: ValidationPath::from_field("workflows"), + min: 1usize, + actual: value.len(), + }); + } + } + Ok(()) + } +} + +impl LexiconSchema for Workflow { + fn nsid() -> &'static str { + "sh.tangled.ci.pipeline" + } + fn def_name() -> &'static str { + "workflow" + } + fn lexicon_doc() -> LexiconDoc<'static> { + lexicon_doc_sh_tangled_ci_pipeline() + } + fn validate(&self) -> Result<(), ConstraintError> { + { + let value = &self.name; + { + let count = UnicodeSegmentation::graphemes(value.as_ref(), true).count(); + if count > 40usize { + return Err(ConstraintError::MaxGraphemes { + path: ValidationPath::from_field("name"), + max: 40usize, + actual: count, + }); + } + } + } + { + let value = &self.name; + { + let count = UnicodeSegmentation::graphemes(value.as_ref(), true).count(); + if count < 1usize { + return Err(ConstraintError::MinGraphemes { + path: ValidationPath::from_field("name"), + min: 1usize, + actual: count, + }); + } + } + } + Ok(()) + } +} + +pub mod pipeline_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 Commit; + type Id; + type Trigger; + type Workflows; + } + /// Empty state - all required fields are unset + pub struct Empty(()); + impl sealed::Sealed for Empty {} + impl State for Empty { + type Commit = Unset; + type Id = Unset; + type Trigger = Unset; + type Workflows = Unset; + } + ///State transition - sets the `commit` field to Set + pub struct SetCommit(PhantomData St>); + impl sealed::Sealed for SetCommit {} + impl State for SetCommit { + type Commit = Set; + type Id = St::Id; + type Trigger = St::Trigger; + type Workflows = St::Workflows; + } + ///State transition - sets the `id` field to Set + pub struct SetId(PhantomData St>); + impl sealed::Sealed for SetId {} + impl State for SetId { + type Commit = St::Commit; + type Id = Set; + type Trigger = St::Trigger; + type Workflows = St::Workflows; + } + ///State transition - sets the `trigger` field to Set + pub struct SetTrigger(PhantomData St>); + impl sealed::Sealed for SetTrigger {} + impl State for SetTrigger { + type Commit = St::Commit; + type Id = St::Id; + type Trigger = Set; + type Workflows = St::Workflows; + } + ///State transition - sets the `workflows` field to Set + pub struct SetWorkflows(PhantomData St>); + impl sealed::Sealed for SetWorkflows {} + impl State for SetWorkflows { + type Commit = St::Commit; + type Id = St::Id; + type Trigger = St::Trigger; + type Workflows = Set; + } + /// Marker types for field names + #[allow(non_camel_case_types)] + pub mod members { + ///Marker type for the `commit` field + pub struct commit(()); + ///Marker type for the `id` field + pub struct id(()); + ///Marker type for the `trigger` field + pub struct trigger(()); + ///Marker type for the `workflows` field + pub struct workflows(()); + } +} + +/// Builder for constructing an instance of this type. +pub struct PipelineBuilder { + _state: PhantomData St>, + _fields: ( + Option, + Option, + Option, + Option>, + Option>, + Option>, + Option>>, + ), + _type: PhantomData S>, +} + +impl Pipeline { + /// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed + pub fn new() -> PipelineBuilder { + PipelineBuilder::new() + } +} + +impl Pipeline { + /// Create a new builder for this type + pub fn builder() -> PipelineBuilder { + PipelineBuilder::builder() + } +} + +impl PipelineBuilder { + /// Create a new builder with all fields unset, using the default string type, if needed + pub fn new() -> Self { + PipelineBuilder { + _state: PhantomData, + _fields: (None, None, None, None, None, None, None), + _type: PhantomData, + } + } +} + +impl PipelineBuilder { + /// Create a new builder with all fields unset + pub fn builder() -> Self { + PipelineBuilder { + _state: PhantomData, + _fields: (None, None, None, None, None, None, None), + _type: PhantomData, + } + } +} + +impl PipelineBuilder +where + St: pipeline_state::State, + St::Commit: pipeline_state::IsUnset, +{ + /// Set the `commit` field (required) + pub fn commit( + mut self, + value: impl Into, + ) -> PipelineBuilder, S> { + self._fields.0 = Option::Some(value.into()); + PipelineBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl PipelineBuilder { + /// Set the `createdAt` field (optional) + pub fn created_at(mut self, value: impl Into>) -> Self { + self._fields.1 = value.into(); + self + } + /// Set the `createdAt` field to an Option value (optional) + pub fn maybe_created_at(mut self, value: Option) -> Self { + self._fields.1 = value; + self + } +} + +impl PipelineBuilder +where + St: pipeline_state::State, + St::Id: pipeline_state::IsUnset, +{ + /// Set the `id` field (required) + pub fn id(mut self, value: impl Into) -> PipelineBuilder, S> { + self._fields.2 = Option::Some(value.into()); + PipelineBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl PipelineBuilder { + /// Set the `repo` field (optional) + pub fn repo(mut self, value: impl Into>>) -> Self { + self._fields.3 = value.into(); + self + } + /// Set the `repo` field to an Option value (optional) + pub fn maybe_repo(mut self, value: Option>) -> Self { + self._fields.3 = value; + self + } +} + +impl PipelineBuilder { + /// Set the `sourceRepo` field (optional) + pub fn source_repo(mut self, value: impl Into>>) -> Self { + self._fields.4 = value.into(); + self + } + /// Set the `sourceRepo` field to an Option value (optional) + pub fn maybe_source_repo(mut self, value: Option>) -> Self { + self._fields.4 = value; + self + } +} + +impl PipelineBuilder +where + St: pipeline_state::State, + St::Trigger: pipeline_state::IsUnset, +{ + /// Set the `trigger` field (required) + pub fn trigger( + mut self, + value: impl Into>, + ) -> PipelineBuilder, S> { + self._fields.5 = Option::Some(value.into()); + PipelineBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl PipelineBuilder +where + St: pipeline_state::State, + St::Workflows: pipeline_state::IsUnset, +{ + /// Set the `workflows` field (required) + pub fn workflows( + mut self, + value: impl Into>>, + ) -> PipelineBuilder, S> { + self._fields.6 = Option::Some(value.into()); + PipelineBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl PipelineBuilder +where + St: pipeline_state::State, + St::Commit: pipeline_state::IsSet, + St::Id: pipeline_state::IsSet, + St::Trigger: pipeline_state::IsSet, + St::Workflows: pipeline_state::IsSet, +{ + /// Build the final struct. + pub fn build(self) -> Pipeline { + Pipeline { + commit: self._fields.0.unwrap(), + created_at: self._fields.1, + id: self._fields.2.unwrap(), + repo: self._fields.3, + source_repo: self._fields.4, + trigger: self._fields.5.unwrap(), + workflows: 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>) -> Pipeline { + Pipeline { + commit: self._fields.0.unwrap(), + created_at: self._fields.1, + id: self._fields.2.unwrap(), + repo: self._fields.3, + source_repo: self._fields.4, + trigger: self._fields.5.unwrap(), + workflows: self._fields.6.unwrap(), + extra_data: Some(extra_data), + } + } +} + +fn lexicon_doc_sh_tangled_ci_pipeline() -> 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.ci.pipeline"), + defs: { + let mut map = BTreeMap::new(); + map.insert( + SmolStr::new_static("main"), + LexUserType::Object(LexObject { + description: Some( + CowStr::new_static( + "A CI pipeline. Record-like, but owned by the spindle rather than a PDS.", + ), + ), + required: Some( + vec![ + SmolStr::new_static("id"), SmolStr::new_static("trigger"), + SmolStr::new_static("commit"), + SmolStr::new_static("workflows") + ], + ), + properties: { + #[allow(unused_mut)] + let mut map = BTreeMap::new(); + map.insert( + SmolStr::new_static("commit"), + LexObjectProperty::String(LexString { + description: Some( + CowStr::new_static("Commit Id this pipeline is running on"), + ), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("createdAt"), + LexObjectProperty::String(LexString { + format: Some(LexStringFormat::Datetime), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("id"), + LexObjectProperty::String(LexString { + description: Some( + CowStr::new_static("Spindle-local pipeline id"), + ), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("repo"), + LexObjectProperty::String(LexString { + description: Some(CowStr::new_static("Repository DID")), + format: Some(LexStringFormat::Did), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("sourceRepo"), + LexObjectProperty::String(LexString { + description: Some( + CowStr::new_static( + "Repository DID that the commit was checked out from, if different from repo (e.g. a fork for a fork-based pull request)", + ), + ), + format: Some(LexStringFormat::Did), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("trigger"), + LexObjectProperty::Union(LexRefUnion { + description: Some( + CowStr::new_static("Trigger event metadata"), + ), + refs: vec![ + CowStr::new_static("sh.tangled.ci.trigger#push"), + CowStr::new_static("sh.tangled.ci.trigger#pullRequest"), + CowStr::new_static("sh.tangled.ci.trigger#manual") + ], + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("workflows"), + LexObjectProperty::Array(LexArray { + description: Some( + CowStr::new_static("Triggered workflows"), + ), + items: LexArrayItem::Ref(LexRef { + r#ref: CowStr::new_static("#workflow"), + ..Default::default() + }), + min_length: Some(1usize), + max_length: Some(50usize), + ..Default::default() + }), + ); + map + }, + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("workflow"), + LexUserType::Object(LexObject { + required: Some( + vec![ + SmolStr::new_static("id"), SmolStr::new_static("name"), + SmolStr::new_static("status") + ], + ), + properties: { + #[allow(unused_mut)] + let mut map = BTreeMap::new(); + map.insert( + SmolStr::new_static("error"), + LexObjectProperty::String(LexString { ..Default::default() }), + ); + map.insert( + SmolStr::new_static("finishedAt"), + LexObjectProperty::String(LexString { + format: Some(LexStringFormat::Datetime), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("id"), + LexObjectProperty::String(LexString { + description: Some( + CowStr::new_static( + "Spindle-local workflow id. Unique per pipeline, usually same as name.", + ), + ), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("name"), + LexObjectProperty::String(LexString { + description: Some( + CowStr::new_static("Name of the workflow"), + ), + min_graphemes: Some(1usize), + max_graphemes: Some(40usize), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("startedAt"), + LexObjectProperty::String(LexString { + format: Some(LexStringFormat::Datetime), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("status"), + LexObjectProperty::String(LexString { + description: Some(CowStr::new_static("Workflow status")), + ..Default::default() + }), + ); + map + }, + ..Default::default() + }), + ); + map + }, + ..Default::default() + } +} diff --git a/crates/jacquard-api/src/sh_tangled/ci/query_pipelines.rs b/crates/jacquard-api/src/sh_tangled/ci/query_pipelines.rs new file mode 100644 index 000000000..b75be6f85 --- /dev/null +++ b/crates/jacquard-api/src/sh_tangled/ci/query_pipelines.rs @@ -0,0 +1,291 @@ +// @generated by jacquard-lexicon. DO NOT EDIT. +// +// Lexicon: sh.tangled.ci.queryPipelines +// +// 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; + +use crate::sh_tangled::ci::pipeline::Pipeline; +#[allow(unused_imports)] +use core::marker::PhantomData; +use jacquard_common::deps::smol_str::SmolStr; +use jacquard_common::types::string::Did; +use jacquard_common::types::value::Data; +use jacquard_common::{BosStr, CowStr, DefaultStr, FromStaticStr}; +use jacquard_derive::{IntoStatic, open_union}; +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct QueryPipelines { + #[serde(skip_serializing_if = "Option::is_none")] + pub commits: Option>, + #[serde(skip_serializing_if = "Option::is_none")] + pub cursor: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub kinds: Option>, + /// Defaults to `50`. Min: 1. Max: 250. + #[serde(default = "_default_limit")] + #[serde(skip_serializing_if = "Option::is_none")] + pub limit: Option, + pub repo: Did, +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct QueryPipelinesOutput { + #[serde(skip_serializing_if = "Option::is_none")] + pub cursor: Option, + pub pipelines: Vec>, + ///Maximum number of pipelines + pub total: i64, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +#[derive( + Serialize, Deserialize, Debug, Clone, PartialEq, Eq, thiserror::Error, miette::Diagnostic, +)] +#[serde(tag = "error", content = "message")] +pub enum QueryPipelinesError { + /// Invalid request parameters + #[serde(rename = "InvalidRequest")] + InvalidRequest(Option), + /// Catch-all for unknown error codes. + #[serde(untagged)] + Other { + error: SmolStr, + message: Option, + }, +} + +impl core::fmt::Display for QueryPipelinesError { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + match self { + Self::InvalidRequest(msg) => { + write!(f, "InvalidRequest")?; + if let Some(msg) = msg { + write!(f, ": {}", msg)?; + } + Ok(()) + } + Self::Other { error, message } => { + write!(f, "{}", error)?; + if let Some(msg) = message { + write!(f, ": {}", msg)?; + } + Ok(()) + } + } + } +} + +/** Response marker for the `sh.tangled.ci.queryPipelines` query. + +Implements `jacquard_common::xrpc::XrpcResp`; successful bodies decode as `Self::Output`, which is `QueryPipelinesOutput` for this endpoint.*/ +pub struct QueryPipelinesResponse; +impl jacquard_common::xrpc::XrpcResp for QueryPipelinesResponse { + const NSID: &'static str = "sh.tangled.ci.queryPipelines"; + const ENCODING: &'static str = "application/json"; + type Output = QueryPipelinesOutput; + type Err = QueryPipelinesError; +} + +impl jacquard_common::xrpc::XrpcRequest for QueryPipelines { + const NSID: &'static str = "sh.tangled.ci.queryPipelines"; + const METHOD: jacquard_common::xrpc::XrpcMethod = jacquard_common::xrpc::XrpcMethod::Query; + type Response = QueryPipelinesResponse; +} + +/** Endpoint marker for the `sh.tangled.ci.queryPipelines` query. + +Path: `/xrpc/sh.tangled.ci.queryPipelines`. The request payload type is `QueryPipelines`; send that request with `jacquard::Client` or use this marker through lower-level `XrpcEndpoint` APIs.*/ +pub struct QueryPipelinesRequest; +impl jacquard_common::xrpc::XrpcEndpoint for QueryPipelinesRequest { + const PATH: &'static str = "/xrpc/sh.tangled.ci.queryPipelines"; + const METHOD: jacquard_common::xrpc::XrpcMethod = jacquard_common::xrpc::XrpcMethod::Query; + type Request = QueryPipelines; + type Response = QueryPipelinesResponse; +} + +fn _default_limit() -> Option { + Some(50i64) +} + +pub mod query_pipelines_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 Repo; + } + /// Empty state - all required fields are unset + pub struct Empty(()); + impl sealed::Sealed for Empty {} + impl State for Empty { + type Repo = Unset; + } + ///State transition - sets the `repo` field to Set + pub struct SetRepo(PhantomData St>); + impl sealed::Sealed for SetRepo {} + impl State for SetRepo { + type Repo = Set; + } + /// Marker types for field names + #[allow(non_camel_case_types)] + pub mod members { + ///Marker type for the `repo` field + pub struct repo(()); + } +} + +/// Builder for constructing an instance of this type. +pub struct QueryPipelinesBuilder { + _state: PhantomData St>, + _fields: ( + Option>, + Option, + Option>, + Option, + Option>, + ), + _type: PhantomData S>, +} + +impl QueryPipelines { + /// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed + pub fn new() -> QueryPipelinesBuilder { + QueryPipelinesBuilder::new() + } +} + +impl QueryPipelines { + /// Create a new builder for this type + pub fn builder() -> QueryPipelinesBuilder { + QueryPipelinesBuilder::builder() + } +} + +impl QueryPipelinesBuilder { + /// Create a new builder with all fields unset, using the default string type, if needed + pub fn new() -> Self { + QueryPipelinesBuilder { + _state: PhantomData, + _fields: (None, None, None, None, None), + _type: PhantomData, + } + } +} + +impl QueryPipelinesBuilder { + /// Create a new builder with all fields unset + pub fn builder() -> Self { + QueryPipelinesBuilder { + _state: PhantomData, + _fields: (None, None, None, None, None), + _type: PhantomData, + } + } +} + +impl QueryPipelinesBuilder { + /// Set the `commits` field (optional) + pub fn commits(mut self, value: impl Into>>) -> Self { + self._fields.0 = value.into(); + self + } + /// Set the `commits` field to an Option value (optional) + pub fn maybe_commits(mut self, value: Option>) -> Self { + self._fields.0 = value; + self + } +} + +impl QueryPipelinesBuilder { + /// Set the `cursor` field (optional) + pub fn cursor(mut self, value: impl Into>) -> Self { + self._fields.1 = value.into(); + self + } + /// Set the `cursor` field to an Option value (optional) + pub fn maybe_cursor(mut self, value: Option) -> Self { + self._fields.1 = value; + self + } +} + +impl QueryPipelinesBuilder { + /// Set the `kinds` field (optional) + pub fn kinds(mut self, value: impl Into>>) -> Self { + self._fields.2 = value.into(); + self + } + /// Set the `kinds` field to an Option value (optional) + pub fn maybe_kinds(mut self, value: Option>) -> Self { + self._fields.2 = value; + self + } +} + +impl QueryPipelinesBuilder { + /// Set the `limit` field (optional) + pub fn limit(mut self, value: impl Into>) -> Self { + self._fields.3 = value.into(); + self + } + /// Set the `limit` field to an Option value (optional) + pub fn maybe_limit(mut self, value: Option) -> Self { + self._fields.3 = value; + self + } +} + +impl QueryPipelinesBuilder +where + St: query_pipelines_state::State, + St::Repo: query_pipelines_state::IsUnset, +{ + /// Set the `repo` field (required) + pub fn repo( + mut self, + value: impl Into>, + ) -> QueryPipelinesBuilder, S> { + self._fields.4 = Option::Some(value.into()); + QueryPipelinesBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl QueryPipelinesBuilder +where + St: query_pipelines_state::State, + St::Repo: query_pipelines_state::IsSet, +{ + /// Build the final struct. + pub fn build(self) -> QueryPipelines { + QueryPipelines { + commits: self._fields.0, + cursor: self._fields.1, + kinds: self._fields.2, + limit: self._fields.3, + repo: self._fields.4.unwrap(), + } + } +} diff --git a/crates/jacquard-api/src/sh_tangled/ci/subscribe_pipeline_logs.rs b/crates/jacquard-api/src/sh_tangled/ci/subscribe_pipeline_logs.rs new file mode 100644 index 000000000..c1f2bbb18 --- /dev/null +++ b/crates/jacquard-api/src/sh_tangled/ci/subscribe_pipeline_logs.rs @@ -0,0 +1,1038 @@ +// @generated by jacquard-lexicon. DO NOT EDIT. +// +// Lexicon: sh.tangled.ci.subscribePipelineLogs +// +// 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::string::{Datetime, Tid}; +use jacquard_derive::{IntoStatic, open_union}; +use jacquard_lexicon::lexicon::LexiconDoc; +use jacquard_lexicon::schema::LexiconSchema; + +use crate::sh_tangled::ci::subscribe_pipeline_logs; +#[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", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct Control { + ///Step command + #[serde(skip_serializing_if = "Option::is_none")] + pub command: Option, + pub content: S, + ///Step kind + #[serde(skip_serializing_if = "Option::is_none")] + pub kind: Option, + ///Step status + #[serde(skip_serializing_if = "Option::is_none")] + pub status: Option, + ///Step ID + pub step: i64, + pub time: Datetime, + ///workflow name + pub workflow: S, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct Data { + pub content: S, + ///Step ID + pub step: i64, + pub stream: S, + pub time: Datetime, + ///workflow name + pub workflow: S, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct SubscribePipelineLogs { + pub pipeline: Tid, + #[serde(skip_serializing_if = "Option::is_none")] + pub workflows: Option>, +} + +#[open_union] +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde(tag = "$type", bound(deserialize = "S: Deserialize<'de> + BosStr"))] +pub enum SubscribePipelineLogsMessage { + #[serde(rename = "#control")] + Control(Box>), + #[serde(rename = "#data")] + Data(Box>), +} + +impl SubscribePipelineLogsMessage { + /// Decode a framed DAG-CBOR message (header + body). + pub fn decode_framed<'de>( + bytes: &'de [u8], + ) -> Result, jacquard_common::error::DecodeError> + where + S: serde::Deserialize<'de>, + { + let (header, body) = jacquard_common::xrpc::subscription::parse_event_header(bytes)?; + match header.t.as_str() { + "#control" => { + let variant = jacquard_common::deps::codegen::serde_ipld_dagcbor::from_slice(body)?; + Ok(Self::Control(Box::new(variant))) + } + "#data" => { + let variant = jacquard_common::deps::codegen::serde_ipld_dagcbor::from_slice(body)?; + Ok(Self::Data(Box::new(variant))) + } + unknown => Err(jacquard_common::error::DecodeError::UnknownEventType( + unknown.into(), + )), + } + } +} + +#[derive( + Serialize, Deserialize, Debug, Clone, PartialEq, Eq, thiserror::Error, miette::Diagnostic, +)] +#[serde(tag = "error", content = "message")] +pub enum SubscribePipelineLogsError { + /// Workflow not found + #[serde(rename = "WorkflowNotFound")] + WorkflowNotFound(Option), + /// Invalid request parameters + #[serde(rename = "InvalidRequest")] + InvalidRequest(Option), + /// Catch-all for unknown error codes. + #[serde(untagged)] + Other { + error: SmolStr, + message: Option, + }, +} + +impl core::fmt::Display for SubscribePipelineLogsError { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + match self { + Self::WorkflowNotFound(msg) => { + write!(f, "WorkflowNotFound")?; + if let Some(msg) = msg { + write!(f, ": {}", msg)?; + } + Ok(()) + } + Self::InvalidRequest(msg) => { + write!(f, "InvalidRequest")?; + if let Some(msg) = msg { + write!(f, ": {}", msg)?; + } + Ok(()) + } + Self::Other { error, message } => { + write!(f, "{}", error)?; + if let Some(msg) = message { + write!(f, ": {}", msg)?; + } + Ok(()) + } + } + } +} + +impl LexiconSchema for Control { + fn nsid() -> &'static str { + "sh.tangled.ci.subscribePipelineLogs" + } + fn def_name() -> &'static str { + "control" + } + fn lexicon_doc() -> LexiconDoc<'static> { + lexicon_doc_sh_tangled_ci_subscribePipelineLogs() + } + fn validate(&self) -> Result<(), ConstraintError> { + Ok(()) + } +} + +impl LexiconSchema for Data { + fn nsid() -> &'static str { + "sh.tangled.ci.subscribePipelineLogs" + } + fn def_name() -> &'static str { + "data" + } + fn lexicon_doc() -> LexiconDoc<'static> { + lexicon_doc_sh_tangled_ci_subscribePipelineLogs() + } + fn validate(&self) -> Result<(), ConstraintError> { + Ok(()) + } +} + +///Stream response type for +///sh.tangled.ci.subscribePipelineLogs +pub struct SubscribePipelineLogsStream; +impl jacquard_common::xrpc::SubscriptionResp for SubscribePipelineLogsStream { + const NSID: &'static str = "sh.tangled.ci.subscribePipelineLogs"; + const ENCODING: jacquard_common::xrpc::MessageEncoding = + jacquard_common::xrpc::MessageEncoding::Json; + type Message = SubscribePipelineLogsMessage; + type Error = SubscribePipelineLogsError; +} + +impl jacquard_common::xrpc::XrpcSubscription for SubscribePipelineLogs { + const NSID: &'static str = "sh.tangled.ci.subscribePipelineLogs"; + const ENCODING: jacquard_common::xrpc::MessageEncoding = + jacquard_common::xrpc::MessageEncoding::Json; + type Stream = SubscribePipelineLogsStream; +} + +pub struct SubscribePipelineLogsEndpoint; +impl jacquard_common::xrpc::SubscriptionEndpoint for SubscribePipelineLogsEndpoint { + const PATH: &'static str = "/xrpc/sh.tangled.ci.subscribePipelineLogs"; + const ENCODING: jacquard_common::xrpc::MessageEncoding = + jacquard_common::xrpc::MessageEncoding::Json; + type Params = SubscribePipelineLogs; + type Stream = SubscribePipelineLogsStream; +} + +pub mod control_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 Content; + type Step; + type Time; + type Workflow; + } + /// Empty state - all required fields are unset + pub struct Empty(()); + impl sealed::Sealed for Empty {} + impl State for Empty { + type Content = Unset; + type Step = Unset; + type Time = Unset; + type Workflow = Unset; + } + ///State transition - sets the `content` field to Set + pub struct SetContent(PhantomData St>); + impl sealed::Sealed for SetContent {} + impl State for SetContent { + type Content = Set; + type Step = St::Step; + type Time = St::Time; + type Workflow = St::Workflow; + } + ///State transition - sets the `step` field to Set + pub struct SetStep(PhantomData St>); + impl sealed::Sealed for SetStep {} + impl State for SetStep { + type Content = St::Content; + type Step = Set; + type Time = St::Time; + type Workflow = St::Workflow; + } + ///State transition - sets the `time` field to Set + pub struct SetTime(PhantomData St>); + impl sealed::Sealed for SetTime {} + impl State for SetTime { + type Content = St::Content; + type Step = St::Step; + type Time = Set; + type Workflow = St::Workflow; + } + ///State transition - sets the `workflow` field to Set + pub struct SetWorkflow(PhantomData St>); + impl sealed::Sealed for SetWorkflow {} + impl State for SetWorkflow { + type Content = St::Content; + type Step = St::Step; + type Time = St::Time; + type Workflow = Set; + } + /// Marker types for field names + #[allow(non_camel_case_types)] + pub mod members { + ///Marker type for the `content` field + pub struct content(()); + ///Marker type for the `step` field + pub struct step(()); + ///Marker type for the `time` field + pub struct time(()); + ///Marker type for the `workflow` field + pub struct workflow(()); + } +} + +/// Builder for constructing an instance of this type. +pub struct ControlBuilder { + _state: PhantomData St>, + _fields: ( + Option, + Option, + Option, + Option, + Option, + Option, + Option, + ), + _type: PhantomData S>, +} + +impl Control { + /// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed + pub fn new() -> ControlBuilder { + ControlBuilder::new() + } +} + +impl Control { + /// Create a new builder for this type + pub fn builder() -> ControlBuilder { + ControlBuilder::builder() + } +} + +impl ControlBuilder { + /// Create a new builder with all fields unset, using the default string type, if needed + pub fn new() -> Self { + ControlBuilder { + _state: PhantomData, + _fields: (None, None, None, None, None, None, None), + _type: PhantomData, + } + } +} + +impl ControlBuilder { + /// Create a new builder with all fields unset + pub fn builder() -> Self { + ControlBuilder { + _state: PhantomData, + _fields: (None, None, None, None, None, None, None), + _type: PhantomData, + } + } +} + +impl ControlBuilder { + /// Set the `command` field (optional) + pub fn command(mut self, value: impl Into>) -> Self { + self._fields.0 = value.into(); + self + } + /// Set the `command` field to an Option value (optional) + pub fn maybe_command(mut self, value: Option) -> Self { + self._fields.0 = value; + self + } +} + +impl ControlBuilder +where + St: control_state::State, + St::Content: control_state::IsUnset, +{ + /// Set the `content` field (required) + pub fn content( + mut self, + value: impl Into, + ) -> ControlBuilder, S> { + self._fields.1 = Option::Some(value.into()); + ControlBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl ControlBuilder { + /// Set the `kind` field (optional) + pub fn kind(mut self, value: impl Into>) -> Self { + self._fields.2 = value.into(); + self + } + /// Set the `kind` field to an Option value (optional) + pub fn maybe_kind(mut self, value: Option) -> Self { + self._fields.2 = value; + self + } +} + +impl ControlBuilder { + /// Set the `status` field (optional) + pub fn status(mut self, value: impl Into>) -> Self { + self._fields.3 = value.into(); + self + } + /// Set the `status` field to an Option value (optional) + pub fn maybe_status(mut self, value: Option) -> Self { + self._fields.3 = value; + self + } +} + +impl ControlBuilder +where + St: control_state::State, + St::Step: control_state::IsUnset, +{ + /// Set the `step` field (required) + pub fn step(mut self, value: impl Into) -> ControlBuilder, S> { + self._fields.4 = Option::Some(value.into()); + ControlBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl ControlBuilder +where + St: control_state::State, + St::Time: control_state::IsUnset, +{ + /// Set the `time` field (required) + pub fn time( + mut self, + value: impl Into, + ) -> ControlBuilder, S> { + self._fields.5 = Option::Some(value.into()); + ControlBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl ControlBuilder +where + St: control_state::State, + St::Workflow: control_state::IsUnset, +{ + /// Set the `workflow` field (required) + pub fn workflow( + mut self, + value: impl Into, + ) -> ControlBuilder, S> { + self._fields.6 = Option::Some(value.into()); + ControlBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl ControlBuilder +where + St: control_state::State, + St::Content: control_state::IsSet, + St::Step: control_state::IsSet, + St::Time: control_state::IsSet, + St::Workflow: control_state::IsSet, +{ + /// Build the final struct. + pub fn build(self) -> Control { + Control { + command: self._fields.0, + content: self._fields.1.unwrap(), + kind: self._fields.2, + status: self._fields.3, + step: self._fields.4.unwrap(), + time: self._fields.5.unwrap(), + workflow: 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>, + ) -> Control { + Control { + command: self._fields.0, + content: self._fields.1.unwrap(), + kind: self._fields.2, + status: self._fields.3, + step: self._fields.4.unwrap(), + time: self._fields.5.unwrap(), + workflow: self._fields.6.unwrap(), + extra_data: Some(extra_data), + } + } +} + +fn lexicon_doc_sh_tangled_ci_subscribePipelineLogs() -> 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.ci.subscribePipelineLogs"), + defs: { + let mut map = BTreeMap::new(); + map.insert( + SmolStr::new_static("control"), + LexUserType::Object(LexObject { + required: Some(vec![ + SmolStr::new_static("time"), + SmolStr::new_static("workflow"), + SmolStr::new_static("step"), + SmolStr::new_static("content"), + ]), + properties: { + #[allow(unused_mut)] + let mut map = BTreeMap::new(); + map.insert( + SmolStr::new_static("command"), + LexObjectProperty::String(LexString { + description: Some(CowStr::new_static("Step command")), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("content"), + LexObjectProperty::String(LexString { + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("kind"), + LexObjectProperty::String(LexString { + description: Some(CowStr::new_static("Step kind")), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("status"), + LexObjectProperty::String(LexString { + description: Some(CowStr::new_static("Step status")), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("step"), + LexObjectProperty::Integer(LexInteger { + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("time"), + LexObjectProperty::String(LexString { + format: Some(LexStringFormat::Datetime), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("workflow"), + LexObjectProperty::String(LexString { + description: Some(CowStr::new_static("workflow name")), + ..Default::default() + }), + ); + map + }, + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("data"), + LexUserType::Object(LexObject { + required: Some(vec![ + SmolStr::new_static("time"), + SmolStr::new_static("workflow"), + SmolStr::new_static("step"), + SmolStr::new_static("content"), + SmolStr::new_static("stream"), + ]), + properties: { + #[allow(unused_mut)] + let mut map = BTreeMap::new(); + map.insert( + SmolStr::new_static("content"), + LexObjectProperty::String(LexString { + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("step"), + LexObjectProperty::Integer(LexInteger { + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("stream"), + LexObjectProperty::String(LexString { + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("time"), + LexObjectProperty::String(LexString { + format: Some(LexStringFormat::Datetime), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("workflow"), + LexObjectProperty::String(LexString { + description: Some(CowStr::new_static("workflow name")), + ..Default::default() + }), + ); + map + }, + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("main"), + LexUserType::XrpcSubscription(LexXrpcSubscription { + parameters: Some(LexXrpcSubscriptionParameter::Params(LexXrpcParameters { + required: Some(vec![SmolStr::new_static("pipeline")]), + properties: { + #[allow(unused_mut)] + let mut map = BTreeMap::new(); + map.insert( + SmolStr::new_static("pipeline"), + LexXrpcParametersProperty::String(LexString { + description: Some(CowStr::new_static("Pipeline ID")), + format: Some(LexStringFormat::Tid), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("workflows"), + LexXrpcParametersProperty::Array(LexPrimitiveArray { + items: LexPrimitiveArrayItem::String(LexString { + description: Some(CowStr::new_static("Workflow name")), + ..Default::default() + }), + ..Default::default() + }), + ); + map + }, + ..Default::default() + })), + ..Default::default() + }), + ); + map + }, + ..Default::default() + } +} + +pub mod data_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 Content; + type Step; + type Stream; + type Time; + type Workflow; + } + /// Empty state - all required fields are unset + pub struct Empty(()); + impl sealed::Sealed for Empty {} + impl State for Empty { + type Content = Unset; + type Step = Unset; + type Stream = Unset; + type Time = Unset; + type Workflow = Unset; + } + ///State transition - sets the `content` field to Set + pub struct SetContent(PhantomData St>); + impl sealed::Sealed for SetContent {} + impl State for SetContent { + type Content = Set; + type Step = St::Step; + type Stream = St::Stream; + type Time = St::Time; + type Workflow = St::Workflow; + } + ///State transition - sets the `step` field to Set + pub struct SetStep(PhantomData St>); + impl sealed::Sealed for SetStep {} + impl State for SetStep { + type Content = St::Content; + type Step = Set; + type Stream = St::Stream; + type Time = St::Time; + type Workflow = St::Workflow; + } + ///State transition - sets the `stream` field to Set + pub struct SetStream(PhantomData St>); + impl sealed::Sealed for SetStream {} + impl State for SetStream { + type Content = St::Content; + type Step = St::Step; + type Stream = Set; + type Time = St::Time; + type Workflow = St::Workflow; + } + ///State transition - sets the `time` field to Set + pub struct SetTime(PhantomData St>); + impl sealed::Sealed for SetTime {} + impl State for SetTime { + type Content = St::Content; + type Step = St::Step; + type Stream = St::Stream; + type Time = Set; + type Workflow = St::Workflow; + } + ///State transition - sets the `workflow` field to Set + pub struct SetWorkflow(PhantomData St>); + impl sealed::Sealed for SetWorkflow {} + impl State for SetWorkflow { + type Content = St::Content; + type Step = St::Step; + type Stream = St::Stream; + type Time = St::Time; + type Workflow = Set; + } + /// Marker types for field names + #[allow(non_camel_case_types)] + pub mod members { + ///Marker type for the `content` field + pub struct content(()); + ///Marker type for the `step` field + pub struct step(()); + ///Marker type for the `stream` field + pub struct stream(()); + ///Marker type for the `time` field + pub struct time(()); + ///Marker type for the `workflow` field + pub struct workflow(()); + } +} + +/// Builder for constructing an instance of this type. +pub struct DataBuilder { + _state: PhantomData St>, + _fields: ( + Option, + Option, + Option, + Option, + Option, + ), + _type: PhantomData S>, +} + +impl Data { + /// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed + pub fn new() -> DataBuilder { + DataBuilder::new() + } +} + +impl Data { + /// Create a new builder for this type + pub fn builder() -> DataBuilder { + DataBuilder::builder() + } +} + +impl DataBuilder { + /// Create a new builder with all fields unset, using the default string type, if needed + pub fn new() -> Self { + DataBuilder { + _state: PhantomData, + _fields: (None, None, None, None, None), + _type: PhantomData, + } + } +} + +impl DataBuilder { + /// Create a new builder with all fields unset + pub fn builder() -> Self { + DataBuilder { + _state: PhantomData, + _fields: (None, None, None, None, None), + _type: PhantomData, + } + } +} + +impl DataBuilder +where + St: data_state::State, + St::Content: data_state::IsUnset, +{ + /// Set the `content` field (required) + pub fn content(mut self, value: impl Into) -> DataBuilder, S> { + self._fields.0 = Option::Some(value.into()); + DataBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl DataBuilder +where + St: data_state::State, + St::Step: data_state::IsUnset, +{ + /// Set the `step` field (required) + pub fn step(mut self, value: impl Into) -> DataBuilder, S> { + self._fields.1 = Option::Some(value.into()); + DataBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl DataBuilder +where + St: data_state::State, + St::Stream: data_state::IsUnset, +{ + /// Set the `stream` field (required) + pub fn stream(mut self, value: impl Into) -> DataBuilder, S> { + self._fields.2 = Option::Some(value.into()); + DataBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl DataBuilder +where + St: data_state::State, + St::Time: data_state::IsUnset, +{ + /// Set the `time` field (required) + pub fn time(mut self, value: impl Into) -> DataBuilder, S> { + self._fields.3 = Option::Some(value.into()); + DataBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl DataBuilder +where + St: data_state::State, + St::Workflow: data_state::IsUnset, +{ + /// Set the `workflow` field (required) + pub fn workflow(mut self, value: impl Into) -> DataBuilder, S> { + self._fields.4 = Option::Some(value.into()); + DataBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl DataBuilder +where + St: data_state::State, + St::Content: data_state::IsSet, + St::Step: data_state::IsSet, + St::Stream: data_state::IsSet, + St::Time: data_state::IsSet, + St::Workflow: data_state::IsSet, +{ + /// Build the final struct. + pub fn build(self) -> Data { + Data { + content: self._fields.0.unwrap(), + step: self._fields.1.unwrap(), + stream: self._fields.2.unwrap(), + time: self._fields.3.unwrap(), + workflow: self._fields.4.unwrap(), + extra_data: Default::default(), + } + } + /// Build the final struct with custom extra_data. + pub fn build_with_data( + self, + extra_data: BTreeMap>, + ) -> Data { + Data { + content: self._fields.0.unwrap(), + step: self._fields.1.unwrap(), + stream: self._fields.2.unwrap(), + time: self._fields.3.unwrap(), + workflow: self._fields.4.unwrap(), + extra_data: Some(extra_data), + } + } +} + +pub mod subscribe_pipeline_logs_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 Pipeline; + } + /// Empty state - all required fields are unset + pub struct Empty(()); + impl sealed::Sealed for Empty {} + impl State for Empty { + type Pipeline = Unset; + } + ///State transition - sets the `pipeline` field to Set + pub struct SetPipeline(PhantomData St>); + impl sealed::Sealed for SetPipeline {} + impl State for SetPipeline { + type Pipeline = Set; + } + /// Marker types for field names + #[allow(non_camel_case_types)] + pub mod members { + ///Marker type for the `pipeline` field + pub struct pipeline(()); + } +} + +/// Builder for constructing an instance of this type. +pub struct SubscribePipelineLogsBuilder< + St: subscribe_pipeline_logs_state::State, + S: BosStr = DefaultStr, +> { + _state: PhantomData St>, + _fields: (Option, Option>), + _type: PhantomData S>, +} + +impl SubscribePipelineLogs { + /// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed + pub fn new() -> SubscribePipelineLogsBuilder { + SubscribePipelineLogsBuilder::new() + } +} + +impl SubscribePipelineLogs { + /// Create a new builder for this type + pub fn builder() -> SubscribePipelineLogsBuilder { + SubscribePipelineLogsBuilder::builder() + } +} + +impl SubscribePipelineLogsBuilder { + /// Create a new builder with all fields unset, using the default string type, if needed + pub fn new() -> Self { + SubscribePipelineLogsBuilder { + _state: PhantomData, + _fields: (None, None), + _type: PhantomData, + } + } +} + +impl SubscribePipelineLogsBuilder { + /// Create a new builder with all fields unset + pub fn builder() -> Self { + SubscribePipelineLogsBuilder { + _state: PhantomData, + _fields: (None, None), + _type: PhantomData, + } + } +} + +impl SubscribePipelineLogsBuilder +where + St: subscribe_pipeline_logs_state::State, + St::Pipeline: subscribe_pipeline_logs_state::IsUnset, +{ + /// Set the `pipeline` field (required) + pub fn pipeline( + mut self, + value: impl Into, + ) -> SubscribePipelineLogsBuilder, S> { + self._fields.0 = Option::Some(value.into()); + SubscribePipelineLogsBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl SubscribePipelineLogsBuilder { + /// Set the `workflows` field (optional) + pub fn workflows(mut self, value: impl Into>>) -> Self { + self._fields.1 = value.into(); + self + } + /// Set the `workflows` field to an Option value (optional) + pub fn maybe_workflows(mut self, value: Option>) -> Self { + self._fields.1 = value; + self + } +} + +impl SubscribePipelineLogsBuilder +where + St: subscribe_pipeline_logs_state::State, + St::Pipeline: subscribe_pipeline_logs_state::IsSet, +{ + /// Build the final struct. + pub fn build(self) -> SubscribePipelineLogs { + SubscribePipelineLogs { + pipeline: self._fields.0.unwrap(), + workflows: self._fields.1, + } + } +} diff --git a/crates/jacquard-api/src/sh_tangled/ci/trigger.rs b/crates/jacquard-api/src/sh_tangled/ci/trigger.rs new file mode 100644 index 000000000..b922f1dd3 --- /dev/null +++ b/crates/jacquard-api/src/sh_tangled/ci/trigger.rs @@ -0,0 +1,452 @@ +// @generated by jacquard-lexicon. DO NOT EDIT. +// +// Lexicon: sh.tangled.ci.trigger +// +// 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; +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::string::{AtUri, Did}; +use jacquard_common::types::value::Data; +use jacquard_derive::IntoStatic; +use jacquard_lexicon::lexicon::LexiconDoc; +use jacquard_lexicon::schema::LexiconSchema; + +use crate::sh_tangled::ci::trigger; +#[allow(unused_imports)] +use jacquard_lexicon::validation::{ConstraintError, ValidationPath}; +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic, Default)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct Manual { + #[serde(skip_serializing_if = "Option::is_none")] + pub inputs: Option>>, + ///optional ref the SHA was resolved from, for display and TANGLED_REF + #[serde(skip_serializing_if = "Option::is_none")] + pub r#ref: Option, + ///commit SHA the manual run targets + pub sha: S, + ///Repository DID to check out code and workflow definitions from, if different from the target repo. + #[serde(skip_serializing_if = "Option::is_none")] + pub source_repo: Option>, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic, Default)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct Pair { + pub key: S, + pub value: S, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +/// TODO: reference PR record with strongRef instead of embedding raw values + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic, Default)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct PullRequest { + ///the pull request lifecycle action that produced this trigger + #[serde(skip_serializing_if = "Option::is_none")] + pub action: Option, + ///AT-URI of the sh.tangled.repo.pull record this run belongs to + #[serde(skip_serializing_if = "Option::is_none")] + pub pull: Option>, + #[serde(skip_serializing_if = "Option::is_none")] + pub source_branch: Option, + ///Repository DID to check out code and workflow definitions from, if different from the target repo. + #[serde(skip_serializing_if = "Option::is_none")] + pub source_repo: Option>, + pub source_sha: S, + pub target_branch: S, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic, Default)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct Push { + pub new_sha: S, + pub old_sha: S, + pub r#ref: S, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +impl LexiconSchema for Manual { + fn nsid() -> &'static str { + "sh.tangled.ci.trigger" + } + fn def_name() -> &'static str { + "manual" + } + fn lexicon_doc() -> LexiconDoc<'static> { + lexicon_doc_sh_tangled_ci_trigger() + } + fn validate(&self) -> Result<(), ConstraintError> { + { + let value = &self.sha; + #[allow(unused_comparisons)] + if ::len(value.as_ref()) > 40usize { + return Err(ConstraintError::MaxLength { + path: ValidationPath::from_field("sha"), + max: 40usize, + actual: ::len(value.as_ref()), + }); + } + } + { + let value = &self.sha; + #[allow(unused_comparisons)] + if ::len(value.as_ref()) < 40usize { + return Err(ConstraintError::MinLength { + path: ValidationPath::from_field("sha"), + min: 40usize, + actual: ::len(value.as_ref()), + }); + } + } + Ok(()) + } +} + +impl LexiconSchema for Pair { + fn nsid() -> &'static str { + "sh.tangled.ci.trigger" + } + fn def_name() -> &'static str { + "pair" + } + fn lexicon_doc() -> LexiconDoc<'static> { + lexicon_doc_sh_tangled_ci_trigger() + } + fn validate(&self) -> Result<(), ConstraintError> { + Ok(()) + } +} + +impl LexiconSchema for PullRequest { + fn nsid() -> &'static str { + "sh.tangled.ci.trigger" + } + fn def_name() -> &'static str { + "pullRequest" + } + fn lexicon_doc() -> LexiconDoc<'static> { + lexicon_doc_sh_tangled_ci_trigger() + } + fn validate(&self) -> Result<(), ConstraintError> { + { + let value = &self.source_sha; + #[allow(unused_comparisons)] + if ::len(value.as_ref()) > 40usize { + return Err(ConstraintError::MaxLength { + path: ValidationPath::from_field("source_sha"), + max: 40usize, + actual: ::len(value.as_ref()), + }); + } + } + { + let value = &self.source_sha; + #[allow(unused_comparisons)] + if ::len(value.as_ref()) < 40usize { + return Err(ConstraintError::MinLength { + path: ValidationPath::from_field("source_sha"), + min: 40usize, + actual: ::len(value.as_ref()), + }); + } + } + Ok(()) + } +} + +impl LexiconSchema for Push { + fn nsid() -> &'static str { + "sh.tangled.ci.trigger" + } + fn def_name() -> &'static str { + "push" + } + fn lexicon_doc() -> LexiconDoc<'static> { + lexicon_doc_sh_tangled_ci_trigger() + } + fn validate(&self) -> Result<(), ConstraintError> { + { + let value = &self.new_sha; + #[allow(unused_comparisons)] + if ::len(value.as_ref()) > 40usize { + return Err(ConstraintError::MaxLength { + path: ValidationPath::from_field("new_sha"), + max: 40usize, + actual: ::len(value.as_ref()), + }); + } + } + { + let value = &self.new_sha; + #[allow(unused_comparisons)] + if ::len(value.as_ref()) < 40usize { + return Err(ConstraintError::MinLength { + path: ValidationPath::from_field("new_sha"), + min: 40usize, + actual: ::len(value.as_ref()), + }); + } + } + { + let value = &self.old_sha; + #[allow(unused_comparisons)] + if ::len(value.as_ref()) > 40usize { + return Err(ConstraintError::MaxLength { + path: ValidationPath::from_field("old_sha"), + max: 40usize, + actual: ::len(value.as_ref()), + }); + } + } + { + let value = &self.old_sha; + #[allow(unused_comparisons)] + if ::len(value.as_ref()) < 40usize { + return Err(ConstraintError::MinLength { + path: ValidationPath::from_field("old_sha"), + min: 40usize, + actual: ::len(value.as_ref()), + }); + } + } + Ok(()) + } +} + +fn lexicon_doc_sh_tangled_ci_trigger() -> 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.ci.trigger"), + defs: { + let mut map = BTreeMap::new(); + map.insert( + SmolStr::new_static("manual"), + LexUserType::Object(LexObject { + required: Some(vec![SmolStr::new_static("sha")]), + properties: { + #[allow(unused_mut)] + let mut map = BTreeMap::new(); + map.insert( + SmolStr::new_static("inputs"), + LexObjectProperty::Array(LexArray { + items: LexArrayItem::Ref(LexRef { + r#ref: CowStr::new_static("#pair"), + ..Default::default() + }), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("ref"), + LexObjectProperty::String(LexString { + description: Some( + CowStr::new_static( + "optional ref the SHA was resolved from, for display and TANGLED_REF", + ), + ), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("sha"), + LexObjectProperty::String(LexString { + description: Some( + CowStr::new_static("commit SHA the manual run targets"), + ), + min_length: Some(40usize), + max_length: Some(40usize), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("sourceRepo"), + LexObjectProperty::String(LexString { + description: Some( + CowStr::new_static( + "Repository DID to check out code and workflow definitions from, if different from the target repo.", + ), + ), + format: Some(LexStringFormat::Did), + ..Default::default() + }), + ); + map + }, + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("pair"), + LexUserType::Object(LexObject { + required: Some(vec![ + SmolStr::new_static("key"), + SmolStr::new_static("value"), + ]), + properties: { + #[allow(unused_mut)] + let mut map = BTreeMap::new(); + map.insert( + SmolStr::new_static("key"), + LexObjectProperty::String(LexString { + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("value"), + LexObjectProperty::String(LexString { + ..Default::default() + }), + ); + map + }, + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("pullRequest"), + LexUserType::Object(LexObject { + description: Some( + CowStr::new_static( + "TODO: reference PR record with strongRef instead of embedding raw values", + ), + ), + required: Some( + vec![ + SmolStr::new_static("targetBranch"), + SmolStr::new_static("sourceSha") + ], + ), + properties: { + #[allow(unused_mut)] + let mut map = BTreeMap::new(); + map.insert( + SmolStr::new_static("action"), + LexObjectProperty::String(LexString { + description: Some( + CowStr::new_static( + "the pull request lifecycle action that produced this trigger", + ), + ), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("pull"), + LexObjectProperty::String(LexString { + description: Some( + CowStr::new_static( + "AT-URI of the sh.tangled.repo.pull record this run belongs to", + ), + ), + format: Some(LexStringFormat::AtUri), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("sourceBranch"), + LexObjectProperty::String(LexString { ..Default::default() }), + ); + map.insert( + SmolStr::new_static("sourceRepo"), + LexObjectProperty::String(LexString { + description: Some( + CowStr::new_static( + "Repository DID to check out code and workflow definitions from, if different from the target repo.", + ), + ), + format: Some(LexStringFormat::Did), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("sourceSha"), + LexObjectProperty::String(LexString { + min_length: Some(40usize), + max_length: Some(40usize), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("targetBranch"), + LexObjectProperty::String(LexString { ..Default::default() }), + ); + map + }, + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("push"), + LexUserType::Object(LexObject { + required: Some(vec![ + SmolStr::new_static("ref"), + SmolStr::new_static("newSha"), + SmolStr::new_static("oldSha"), + ]), + properties: { + #[allow(unused_mut)] + let mut map = BTreeMap::new(); + map.insert( + SmolStr::new_static("newSha"), + LexObjectProperty::String(LexString { + min_length: Some(40usize), + max_length: Some(40usize), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("oldSha"), + LexObjectProperty::String(LexString { + min_length: Some(40usize), + max_length: Some(40usize), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("ref"), + LexObjectProperty::String(LexString { + ..Default::default() + }), + ); + map + }, + ..Default::default() + }), + ); + map + }, + ..Default::default() + } +} diff --git a/crates/jacquard-api/src/sh_tangled/ci/trigger_pipeline.rs b/crates/jacquard-api/src/sh_tangled/ci/trigger_pipeline.rs new file mode 100644 index 000000000..6e1e526bc --- /dev/null +++ b/crates/jacquard-api/src/sh_tangled/ci/trigger_pipeline.rs @@ -0,0 +1,294 @@ +// @generated by jacquard-lexicon. DO NOT EDIT. +// +// Lexicon: sh.tangled.ci.triggerPipeline +// +// 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; + +use crate::sh_tangled::ci::trigger::Manual; +use crate::sh_tangled::ci::trigger::PullRequest; +#[allow(unused_imports)] +use core::marker::PhantomData; +use jacquard_common::deps::smol_str::SmolStr; +use jacquard_common::types::string::{AtUri, Did}; +use jacquard_common::types::value::Data; +use jacquard_common::{BosStr, CowStr, DefaultStr, FromStaticStr}; +use jacquard_derive::{IntoStatic, open_union}; +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct TriggerPipeline { + ///Target repository DID. Auth is checked against this repo. + pub repo: Did, + ///Trigger metadata for this dispatch. + pub trigger: TriggerPipelineTrigger, + ///Workflow names to run. When not provided, every dispatchable workflow is run. + #[serde(skip_serializing_if = "Option::is_none")] + pub workflows: Option>, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +#[open_union] +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde(tag = "$type", bound(deserialize = "S: Deserialize<'de> + BosStr"))] +pub enum TriggerPipelineTrigger { + #[serde(rename = "sh.tangled.ci.trigger#manual")] + TriggerManual(Box>), + #[serde(rename = "sh.tangled.ci.trigger#pullRequest")] + TriggerPullRequest(Box>), +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct TriggerPipelineOutput { + ///AT-URI of the created pipeline + pub pipeline: AtUri, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +#[derive( + Serialize, Deserialize, Debug, Clone, PartialEq, Eq, thiserror::Error, miette::Diagnostic, +)] +#[serde(tag = "error", content = "message")] +pub enum TriggerPipelineError { + /// Invalid request parameters + #[serde(rename = "InvalidRequest")] + InvalidRequest(Option), + /// Catch-all for unknown error codes. + #[serde(untagged)] + Other { + error: SmolStr, + message: Option, + }, +} + +impl core::fmt::Display for TriggerPipelineError { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + match self { + Self::InvalidRequest(msg) => { + write!(f, "InvalidRequest")?; + if let Some(msg) = msg { + write!(f, ": {}", msg)?; + } + Ok(()) + } + Self::Other { error, message } => { + write!(f, "{}", error)?; + if let Some(msg) = message { + write!(f, ": {}", msg)?; + } + Ok(()) + } + } + } +} + +/** Response marker for the `sh.tangled.ci.triggerPipeline` procedure. + +Implements `jacquard_common::xrpc::XrpcResp`; successful bodies decode as `Self::Output`, which is `TriggerPipelineOutput` for this endpoint.*/ +pub struct TriggerPipelineResponse; +impl jacquard_common::xrpc::XrpcResp for TriggerPipelineResponse { + const NSID: &'static str = "sh.tangled.ci.triggerPipeline"; + const ENCODING: &'static str = "application/json"; + type Output = TriggerPipelineOutput; + type Err = TriggerPipelineError; +} + +impl jacquard_common::xrpc::XrpcRequest for TriggerPipeline { + const NSID: &'static str = "sh.tangled.ci.triggerPipeline"; + const METHOD: jacquard_common::xrpc::XrpcMethod = + jacquard_common::xrpc::XrpcMethod::Procedure("application/json"); + type Response = TriggerPipelineResponse; +} + +/** Endpoint marker for the `sh.tangled.ci.triggerPipeline` procedure. + +Path: `/xrpc/sh.tangled.ci.triggerPipeline`. The request payload type is `TriggerPipeline`; send that request with `jacquard::Client` or use this marker through lower-level `XrpcEndpoint` APIs.*/ +pub struct TriggerPipelineRequest; +impl jacquard_common::xrpc::XrpcEndpoint for TriggerPipelineRequest { + const PATH: &'static str = "/xrpc/sh.tangled.ci.triggerPipeline"; + const METHOD: jacquard_common::xrpc::XrpcMethod = + jacquard_common::xrpc::XrpcMethod::Procedure("application/json"); + type Request = TriggerPipeline; + type Response = TriggerPipelineResponse; +} + +pub mod trigger_pipeline_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 Repo; + type Trigger; + } + /// Empty state - all required fields are unset + pub struct Empty(()); + impl sealed::Sealed for Empty {} + impl State for Empty { + type Repo = Unset; + type Trigger = Unset; + } + ///State transition - sets the `repo` field to Set + pub struct SetRepo(PhantomData St>); + impl sealed::Sealed for SetRepo {} + impl State for SetRepo { + type Repo = Set; + type Trigger = St::Trigger; + } + ///State transition - sets the `trigger` field to Set + pub struct SetTrigger(PhantomData St>); + impl sealed::Sealed for SetTrigger {} + impl State for SetTrigger { + type Repo = St::Repo; + type Trigger = Set; + } + /// Marker types for field names + #[allow(non_camel_case_types)] + pub mod members { + ///Marker type for the `repo` field + pub struct repo(()); + ///Marker type for the `trigger` field + pub struct trigger(()); + } +} + +/// Builder for constructing an instance of this type. +pub struct TriggerPipelineBuilder { + _state: PhantomData St>, + _fields: ( + Option>, + Option>, + Option>, + ), + _type: PhantomData S>, +} + +impl TriggerPipeline { + /// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed + pub fn new() -> TriggerPipelineBuilder { + TriggerPipelineBuilder::new() + } +} + +impl TriggerPipeline { + /// Create a new builder for this type + pub fn builder() -> TriggerPipelineBuilder { + TriggerPipelineBuilder::builder() + } +} + +impl TriggerPipelineBuilder { + /// Create a new builder with all fields unset, using the default string type, if needed + pub fn new() -> Self { + TriggerPipelineBuilder { + _state: PhantomData, + _fields: (None, None, None), + _type: PhantomData, + } + } +} + +impl TriggerPipelineBuilder { + /// Create a new builder with all fields unset + pub fn builder() -> Self { + TriggerPipelineBuilder { + _state: PhantomData, + _fields: (None, None, None), + _type: PhantomData, + } + } +} + +impl TriggerPipelineBuilder +where + St: trigger_pipeline_state::State, + St::Repo: trigger_pipeline_state::IsUnset, +{ + /// Set the `repo` field (required) + pub fn repo( + mut self, + value: impl Into>, + ) -> TriggerPipelineBuilder, S> { + self._fields.0 = Option::Some(value.into()); + TriggerPipelineBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl TriggerPipelineBuilder +where + St: trigger_pipeline_state::State, + St::Trigger: trigger_pipeline_state::IsUnset, +{ + /// Set the `trigger` field (required) + pub fn trigger( + mut self, + value: impl Into>, + ) -> TriggerPipelineBuilder, S> { + self._fields.1 = Option::Some(value.into()); + TriggerPipelineBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl TriggerPipelineBuilder { + /// Set the `workflows` field (optional) + pub fn workflows(mut self, value: impl Into>>) -> Self { + self._fields.2 = value.into(); + self + } + /// Set the `workflows` field to an Option value (optional) + pub fn maybe_workflows(mut self, value: Option>) -> Self { + self._fields.2 = value; + self + } +} + +impl TriggerPipelineBuilder +where + St: trigger_pipeline_state::State, + St::Repo: trigger_pipeline_state::IsSet, + St::Trigger: trigger_pipeline_state::IsSet, +{ + /// Build the final struct. + pub fn build(self) -> TriggerPipeline { + TriggerPipeline { + repo: self._fields.0.unwrap(), + trigger: self._fields.1.unwrap(), + workflows: self._fields.2, + extra_data: Default::default(), + } + } + /// Build the final struct with custom extra_data. + pub fn build_with_data(self, extra_data: BTreeMap>) -> TriggerPipeline { + TriggerPipeline { + repo: self._fields.0.unwrap(), + trigger: self._fields.1.unwrap(), + workflows: self._fields.2, + extra_data: Some(extra_data), + } + } +} diff --git a/crates/jacquard-api/src/sh_tangled/feed.rs b/crates/jacquard-api/src/sh_tangled/feed.rs index 8a5cf3a22..e904ee843 100644 --- a/crates/jacquard-api/src/sh_tangled/feed.rs +++ b/crates/jacquard-api/src/sh_tangled/feed.rs @@ -5,6 +5,12 @@ //! Generated bindings for the `sh.tangled.feed` Lexicon namespace/module. pub mod comment; +pub mod count_comments; +pub mod count_comments_by; +pub mod count_reactions; +pub mod count_reactions_by; +pub mod count_stars; +pub mod count_stars_by; pub mod list_comments; pub mod list_comments_by; pub mod list_reactions; diff --git a/crates/jacquard-api/src/sh_tangled/feed/count_comments.rs b/crates/jacquard-api/src/sh_tangled/feed/count_comments.rs new file mode 100644 index 000000000..8e92e3e4f --- /dev/null +++ b/crates/jacquard-api/src/sh_tangled/feed/count_comments.rs @@ -0,0 +1,176 @@ +// @generated by jacquard-lexicon. DO NOT EDIT. +// +// Lexicon: sh.tangled.feed.countComments +// +// 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::deps::smol_str::SmolStr; +use jacquard_common::types::string::AtUri; +use jacquard_common::types::value::Data; +use jacquard_common::{BosStr, DefaultStr, FromStaticStr}; +use jacquard_derive::IntoStatic; +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct CountComments { + pub subject: AtUri, +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct CountCommentsOutput { + ///Total number of matching records. + pub count: i64, + ///Number of distinct authors among the matching records. + pub distinct_authors: i64, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +/** Response marker for the `sh.tangled.feed.countComments` query. + +Implements `jacquard_common::xrpc::XrpcResp`; successful bodies decode as `Self::Output`, which is `CountCommentsOutput` for this endpoint.*/ +pub struct CountCommentsResponse; +impl jacquard_common::xrpc::XrpcResp for CountCommentsResponse { + const NSID: &'static str = "sh.tangled.feed.countComments"; + const ENCODING: &'static str = "application/json"; + type Output = CountCommentsOutput; + type Err = jacquard_common::xrpc::GenericError; +} + +impl jacquard_common::xrpc::XrpcRequest for CountComments { + const NSID: &'static str = "sh.tangled.feed.countComments"; + const METHOD: jacquard_common::xrpc::XrpcMethod = jacquard_common::xrpc::XrpcMethod::Query; + type Response = CountCommentsResponse; +} + +/** Endpoint marker for the `sh.tangled.feed.countComments` query. + +Path: `/xrpc/sh.tangled.feed.countComments`. The request payload type is `CountComments`; send that request with `jacquard::Client` or use this marker through lower-level `XrpcEndpoint` APIs.*/ +pub struct CountCommentsRequest; +impl jacquard_common::xrpc::XrpcEndpoint for CountCommentsRequest { + const PATH: &'static str = "/xrpc/sh.tangled.feed.countComments"; + const METHOD: jacquard_common::xrpc::XrpcMethod = jacquard_common::xrpc::XrpcMethod::Query; + type Request = CountComments; + type Response = CountCommentsResponse; +} + +pub mod count_comments_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 Subject; + } + /// Empty state - all required fields are unset + pub struct Empty(()); + impl sealed::Sealed for Empty {} + impl State for Empty { + type Subject = Unset; + } + ///State transition - sets the `subject` field to Set + pub struct SetSubject(PhantomData St>); + impl sealed::Sealed for SetSubject {} + impl State for SetSubject { + type Subject = Set; + } + /// Marker types for field names + #[allow(non_camel_case_types)] + pub mod members { + ///Marker type for the `subject` field + pub struct subject(()); + } +} + +/// Builder for constructing an instance of this type. +pub struct CountCommentsBuilder { + _state: PhantomData St>, + _fields: (Option>,), + _type: PhantomData S>, +} + +impl CountComments { + /// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed + pub fn new() -> CountCommentsBuilder { + CountCommentsBuilder::new() + } +} + +impl CountComments { + /// Create a new builder for this type + pub fn builder() -> CountCommentsBuilder { + CountCommentsBuilder::builder() + } +} + +impl CountCommentsBuilder { + /// Create a new builder with all fields unset, using the default string type, if needed + pub fn new() -> Self { + CountCommentsBuilder { + _state: PhantomData, + _fields: (None,), + _type: PhantomData, + } + } +} + +impl CountCommentsBuilder { + /// Create a new builder with all fields unset + pub fn builder() -> Self { + CountCommentsBuilder { + _state: PhantomData, + _fields: (None,), + _type: PhantomData, + } + } +} + +impl CountCommentsBuilder +where + St: count_comments_state::State, + St::Subject: count_comments_state::IsUnset, +{ + /// Set the `subject` field (required) + pub fn subject( + mut self, + value: impl Into>, + ) -> CountCommentsBuilder, S> { + self._fields.0 = Option::Some(value.into()); + CountCommentsBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl CountCommentsBuilder +where + St: count_comments_state::State, + St::Subject: count_comments_state::IsSet, +{ + /// Build the final struct. + pub fn build(self) -> CountComments { + CountComments { + subject: self._fields.0.unwrap(), + } + } +} diff --git a/crates/jacquard-api/src/sh_tangled/feed/count_comments_by.rs b/crates/jacquard-api/src/sh_tangled/feed/count_comments_by.rs new file mode 100644 index 000000000..68033e076 --- /dev/null +++ b/crates/jacquard-api/src/sh_tangled/feed/count_comments_by.rs @@ -0,0 +1,176 @@ +// @generated by jacquard-lexicon. DO NOT EDIT. +// +// Lexicon: sh.tangled.feed.countCommentsBy +// +// 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::deps::smol_str::SmolStr; +use jacquard_common::types::string::Did; +use jacquard_common::types::value::Data; +use jacquard_common::{BosStr, DefaultStr, FromStaticStr}; +use jacquard_derive::IntoStatic; +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct CountCommentsBy { + pub subject: Did, +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct CountCommentsByOutput { + ///Total number of matching records. + pub count: i64, + ///Number of distinct authors among the matching records. + pub distinct_authors: i64, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +/** Response marker for the `sh.tangled.feed.countCommentsBy` query. + +Implements `jacquard_common::xrpc::XrpcResp`; successful bodies decode as `Self::Output`, which is `CountCommentsByOutput` for this endpoint.*/ +pub struct CountCommentsByResponse; +impl jacquard_common::xrpc::XrpcResp for CountCommentsByResponse { + const NSID: &'static str = "sh.tangled.feed.countCommentsBy"; + const ENCODING: &'static str = "application/json"; + type Output = CountCommentsByOutput; + type Err = jacquard_common::xrpc::GenericError; +} + +impl jacquard_common::xrpc::XrpcRequest for CountCommentsBy { + const NSID: &'static str = "sh.tangled.feed.countCommentsBy"; + const METHOD: jacquard_common::xrpc::XrpcMethod = jacquard_common::xrpc::XrpcMethod::Query; + type Response = CountCommentsByResponse; +} + +/** Endpoint marker for the `sh.tangled.feed.countCommentsBy` query. + +Path: `/xrpc/sh.tangled.feed.countCommentsBy`. The request payload type is `CountCommentsBy`; send that request with `jacquard::Client` or use this marker through lower-level `XrpcEndpoint` APIs.*/ +pub struct CountCommentsByRequest; +impl jacquard_common::xrpc::XrpcEndpoint for CountCommentsByRequest { + const PATH: &'static str = "/xrpc/sh.tangled.feed.countCommentsBy"; + const METHOD: jacquard_common::xrpc::XrpcMethod = jacquard_common::xrpc::XrpcMethod::Query; + type Request = CountCommentsBy; + type Response = CountCommentsByResponse; +} + +pub mod count_comments_by_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 Subject; + } + /// Empty state - all required fields are unset + pub struct Empty(()); + impl sealed::Sealed for Empty {} + impl State for Empty { + type Subject = Unset; + } + ///State transition - sets the `subject` field to Set + pub struct SetSubject(PhantomData St>); + impl sealed::Sealed for SetSubject {} + impl State for SetSubject { + type Subject = Set; + } + /// Marker types for field names + #[allow(non_camel_case_types)] + pub mod members { + ///Marker type for the `subject` field + pub struct subject(()); + } +} + +/// Builder for constructing an instance of this type. +pub struct CountCommentsByBuilder { + _state: PhantomData St>, + _fields: (Option>,), + _type: PhantomData S>, +} + +impl CountCommentsBy { + /// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed + pub fn new() -> CountCommentsByBuilder { + CountCommentsByBuilder::new() + } +} + +impl CountCommentsBy { + /// Create a new builder for this type + pub fn builder() -> CountCommentsByBuilder { + CountCommentsByBuilder::builder() + } +} + +impl CountCommentsByBuilder { + /// Create a new builder with all fields unset, using the default string type, if needed + pub fn new() -> Self { + CountCommentsByBuilder { + _state: PhantomData, + _fields: (None,), + _type: PhantomData, + } + } +} + +impl CountCommentsByBuilder { + /// Create a new builder with all fields unset + pub fn builder() -> Self { + CountCommentsByBuilder { + _state: PhantomData, + _fields: (None,), + _type: PhantomData, + } + } +} + +impl CountCommentsByBuilder +where + St: count_comments_by_state::State, + St::Subject: count_comments_by_state::IsUnset, +{ + /// Set the `subject` field (required) + pub fn subject( + mut self, + value: impl Into>, + ) -> CountCommentsByBuilder, S> { + self._fields.0 = Option::Some(value.into()); + CountCommentsByBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl CountCommentsByBuilder +where + St: count_comments_by_state::State, + St::Subject: count_comments_by_state::IsSet, +{ + /// Build the final struct. + pub fn build(self) -> CountCommentsBy { + CountCommentsBy { + subject: self._fields.0.unwrap(), + } + } +} diff --git a/crates/jacquard-api/src/sh_tangled/feed/count_reactions.rs b/crates/jacquard-api/src/sh_tangled/feed/count_reactions.rs new file mode 100644 index 000000000..dcfa3e2f4 --- /dev/null +++ b/crates/jacquard-api/src/sh_tangled/feed/count_reactions.rs @@ -0,0 +1,176 @@ +// @generated by jacquard-lexicon. DO NOT EDIT. +// +// Lexicon: sh.tangled.feed.countReactions +// +// 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::deps::smol_str::SmolStr; +use jacquard_common::types::string::AtUri; +use jacquard_common::types::value::Data; +use jacquard_common::{BosStr, DefaultStr, FromStaticStr}; +use jacquard_derive::IntoStatic; +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct CountReactions { + pub subject: AtUri, +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct CountReactionsOutput { + ///Total number of matching records. + pub count: i64, + ///Number of distinct authors among the matching records. + pub distinct_authors: i64, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +/** Response marker for the `sh.tangled.feed.countReactions` query. + +Implements `jacquard_common::xrpc::XrpcResp`; successful bodies decode as `Self::Output`, which is `CountReactionsOutput` for this endpoint.*/ +pub struct CountReactionsResponse; +impl jacquard_common::xrpc::XrpcResp for CountReactionsResponse { + const NSID: &'static str = "sh.tangled.feed.countReactions"; + const ENCODING: &'static str = "application/json"; + type Output = CountReactionsOutput; + type Err = jacquard_common::xrpc::GenericError; +} + +impl jacquard_common::xrpc::XrpcRequest for CountReactions { + const NSID: &'static str = "sh.tangled.feed.countReactions"; + const METHOD: jacquard_common::xrpc::XrpcMethod = jacquard_common::xrpc::XrpcMethod::Query; + type Response = CountReactionsResponse; +} + +/** Endpoint marker for the `sh.tangled.feed.countReactions` query. + +Path: `/xrpc/sh.tangled.feed.countReactions`. The request payload type is `CountReactions`; send that request with `jacquard::Client` or use this marker through lower-level `XrpcEndpoint` APIs.*/ +pub struct CountReactionsRequest; +impl jacquard_common::xrpc::XrpcEndpoint for CountReactionsRequest { + const PATH: &'static str = "/xrpc/sh.tangled.feed.countReactions"; + const METHOD: jacquard_common::xrpc::XrpcMethod = jacquard_common::xrpc::XrpcMethod::Query; + type Request = CountReactions; + type Response = CountReactionsResponse; +} + +pub mod count_reactions_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 Subject; + } + /// Empty state - all required fields are unset + pub struct Empty(()); + impl sealed::Sealed for Empty {} + impl State for Empty { + type Subject = Unset; + } + ///State transition - sets the `subject` field to Set + pub struct SetSubject(PhantomData St>); + impl sealed::Sealed for SetSubject {} + impl State for SetSubject { + type Subject = Set; + } + /// Marker types for field names + #[allow(non_camel_case_types)] + pub mod members { + ///Marker type for the `subject` field + pub struct subject(()); + } +} + +/// Builder for constructing an instance of this type. +pub struct CountReactionsBuilder { + _state: PhantomData St>, + _fields: (Option>,), + _type: PhantomData S>, +} + +impl CountReactions { + /// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed + pub fn new() -> CountReactionsBuilder { + CountReactionsBuilder::new() + } +} + +impl CountReactions { + /// Create a new builder for this type + pub fn builder() -> CountReactionsBuilder { + CountReactionsBuilder::builder() + } +} + +impl CountReactionsBuilder { + /// Create a new builder with all fields unset, using the default string type, if needed + pub fn new() -> Self { + CountReactionsBuilder { + _state: PhantomData, + _fields: (None,), + _type: PhantomData, + } + } +} + +impl CountReactionsBuilder { + /// Create a new builder with all fields unset + pub fn builder() -> Self { + CountReactionsBuilder { + _state: PhantomData, + _fields: (None,), + _type: PhantomData, + } + } +} + +impl CountReactionsBuilder +where + St: count_reactions_state::State, + St::Subject: count_reactions_state::IsUnset, +{ + /// Set the `subject` field (required) + pub fn subject( + mut self, + value: impl Into>, + ) -> CountReactionsBuilder, S> { + self._fields.0 = Option::Some(value.into()); + CountReactionsBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl CountReactionsBuilder +where + St: count_reactions_state::State, + St::Subject: count_reactions_state::IsSet, +{ + /// Build the final struct. + pub fn build(self) -> CountReactions { + CountReactions { + subject: self._fields.0.unwrap(), + } + } +} diff --git a/crates/jacquard-api/src/sh_tangled/feed/count_reactions_by.rs b/crates/jacquard-api/src/sh_tangled/feed/count_reactions_by.rs new file mode 100644 index 000000000..6f8a50ea4 --- /dev/null +++ b/crates/jacquard-api/src/sh_tangled/feed/count_reactions_by.rs @@ -0,0 +1,176 @@ +// @generated by jacquard-lexicon. DO NOT EDIT. +// +// Lexicon: sh.tangled.feed.countReactionsBy +// +// 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::deps::smol_str::SmolStr; +use jacquard_common::types::string::Did; +use jacquard_common::types::value::Data; +use jacquard_common::{BosStr, DefaultStr, FromStaticStr}; +use jacquard_derive::IntoStatic; +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct CountReactionsBy { + pub subject: Did, +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct CountReactionsByOutput { + ///Total number of matching records. + pub count: i64, + ///Number of distinct authors among the matching records. + pub distinct_authors: i64, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +/** Response marker for the `sh.tangled.feed.countReactionsBy` query. + +Implements `jacquard_common::xrpc::XrpcResp`; successful bodies decode as `Self::Output`, which is `CountReactionsByOutput` for this endpoint.*/ +pub struct CountReactionsByResponse; +impl jacquard_common::xrpc::XrpcResp for CountReactionsByResponse { + const NSID: &'static str = "sh.tangled.feed.countReactionsBy"; + const ENCODING: &'static str = "application/json"; + type Output = CountReactionsByOutput; + type Err = jacquard_common::xrpc::GenericError; +} + +impl jacquard_common::xrpc::XrpcRequest for CountReactionsBy { + const NSID: &'static str = "sh.tangled.feed.countReactionsBy"; + const METHOD: jacquard_common::xrpc::XrpcMethod = jacquard_common::xrpc::XrpcMethod::Query; + type Response = CountReactionsByResponse; +} + +/** Endpoint marker for the `sh.tangled.feed.countReactionsBy` query. + +Path: `/xrpc/sh.tangled.feed.countReactionsBy`. The request payload type is `CountReactionsBy`; send that request with `jacquard::Client` or use this marker through lower-level `XrpcEndpoint` APIs.*/ +pub struct CountReactionsByRequest; +impl jacquard_common::xrpc::XrpcEndpoint for CountReactionsByRequest { + const PATH: &'static str = "/xrpc/sh.tangled.feed.countReactionsBy"; + const METHOD: jacquard_common::xrpc::XrpcMethod = jacquard_common::xrpc::XrpcMethod::Query; + type Request = CountReactionsBy; + type Response = CountReactionsByResponse; +} + +pub mod count_reactions_by_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 Subject; + } + /// Empty state - all required fields are unset + pub struct Empty(()); + impl sealed::Sealed for Empty {} + impl State for Empty { + type Subject = Unset; + } + ///State transition - sets the `subject` field to Set + pub struct SetSubject(PhantomData St>); + impl sealed::Sealed for SetSubject {} + impl State for SetSubject { + type Subject = Set; + } + /// Marker types for field names + #[allow(non_camel_case_types)] + pub mod members { + ///Marker type for the `subject` field + pub struct subject(()); + } +} + +/// Builder for constructing an instance of this type. +pub struct CountReactionsByBuilder { + _state: PhantomData St>, + _fields: (Option>,), + _type: PhantomData S>, +} + +impl CountReactionsBy { + /// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed + pub fn new() -> CountReactionsByBuilder { + CountReactionsByBuilder::new() + } +} + +impl CountReactionsBy { + /// Create a new builder for this type + pub fn builder() -> CountReactionsByBuilder { + CountReactionsByBuilder::builder() + } +} + +impl CountReactionsByBuilder { + /// Create a new builder with all fields unset, using the default string type, if needed + pub fn new() -> Self { + CountReactionsByBuilder { + _state: PhantomData, + _fields: (None,), + _type: PhantomData, + } + } +} + +impl CountReactionsByBuilder { + /// Create a new builder with all fields unset + pub fn builder() -> Self { + CountReactionsByBuilder { + _state: PhantomData, + _fields: (None,), + _type: PhantomData, + } + } +} + +impl CountReactionsByBuilder +where + St: count_reactions_by_state::State, + St::Subject: count_reactions_by_state::IsUnset, +{ + /// Set the `subject` field (required) + pub fn subject( + mut self, + value: impl Into>, + ) -> CountReactionsByBuilder, S> { + self._fields.0 = Option::Some(value.into()); + CountReactionsByBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl CountReactionsByBuilder +where + St: count_reactions_by_state::State, + St::Subject: count_reactions_by_state::IsSet, +{ + /// Build the final struct. + pub fn build(self) -> CountReactionsBy { + CountReactionsBy { + subject: self._fields.0.unwrap(), + } + } +} diff --git a/crates/jacquard-api/src/sh_tangled/feed/count_stars.rs b/crates/jacquard-api/src/sh_tangled/feed/count_stars.rs new file mode 100644 index 000000000..773a02a59 --- /dev/null +++ b/crates/jacquard-api/src/sh_tangled/feed/count_stars.rs @@ -0,0 +1,175 @@ +// @generated by jacquard-lexicon. DO NOT EDIT. +// +// Lexicon: sh.tangled.feed.countStars +// +// 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::deps::smol_str::SmolStr; +use jacquard_common::types::value::Data; +use jacquard_common::{BosStr, CowStr, DefaultStr, FromStaticStr}; +use jacquard_derive::IntoStatic; +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct CountStars { + pub subject: S, +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct CountStarsOutput { + ///Total number of matching records. + pub count: i64, + ///Number of distinct authors among the matching records. + pub distinct_authors: i64, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +/** Response marker for the `sh.tangled.feed.countStars` query. + +Implements `jacquard_common::xrpc::XrpcResp`; successful bodies decode as `Self::Output`, which is `CountStarsOutput` for this endpoint.*/ +pub struct CountStarsResponse; +impl jacquard_common::xrpc::XrpcResp for CountStarsResponse { + const NSID: &'static str = "sh.tangled.feed.countStars"; + const ENCODING: &'static str = "application/json"; + type Output = CountStarsOutput; + type Err = jacquard_common::xrpc::GenericError; +} + +impl jacquard_common::xrpc::XrpcRequest for CountStars { + const NSID: &'static str = "sh.tangled.feed.countStars"; + const METHOD: jacquard_common::xrpc::XrpcMethod = jacquard_common::xrpc::XrpcMethod::Query; + type Response = CountStarsResponse; +} + +/** Endpoint marker for the `sh.tangled.feed.countStars` query. + +Path: `/xrpc/sh.tangled.feed.countStars`. The request payload type is `CountStars`; send that request with `jacquard::Client` or use this marker through lower-level `XrpcEndpoint` APIs.*/ +pub struct CountStarsRequest; +impl jacquard_common::xrpc::XrpcEndpoint for CountStarsRequest { + const PATH: &'static str = "/xrpc/sh.tangled.feed.countStars"; + const METHOD: jacquard_common::xrpc::XrpcMethod = jacquard_common::xrpc::XrpcMethod::Query; + type Request = CountStars; + type Response = CountStarsResponse; +} + +pub mod count_stars_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 Subject; + } + /// Empty state - all required fields are unset + pub struct Empty(()); + impl sealed::Sealed for Empty {} + impl State for Empty { + type Subject = Unset; + } + ///State transition - sets the `subject` field to Set + pub struct SetSubject(PhantomData St>); + impl sealed::Sealed for SetSubject {} + impl State for SetSubject { + type Subject = Set; + } + /// Marker types for field names + #[allow(non_camel_case_types)] + pub mod members { + ///Marker type for the `subject` field + pub struct subject(()); + } +} + +/// Builder for constructing an instance of this type. +pub struct CountStarsBuilder { + _state: PhantomData St>, + _fields: (Option,), + _type: PhantomData S>, +} + +impl CountStars { + /// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed + pub fn new() -> CountStarsBuilder { + CountStarsBuilder::new() + } +} + +impl CountStars { + /// Create a new builder for this type + pub fn builder() -> CountStarsBuilder { + CountStarsBuilder::builder() + } +} + +impl CountStarsBuilder { + /// Create a new builder with all fields unset, using the default string type, if needed + pub fn new() -> Self { + CountStarsBuilder { + _state: PhantomData, + _fields: (None,), + _type: PhantomData, + } + } +} + +impl CountStarsBuilder { + /// Create a new builder with all fields unset + pub fn builder() -> Self { + CountStarsBuilder { + _state: PhantomData, + _fields: (None,), + _type: PhantomData, + } + } +} + +impl CountStarsBuilder +where + St: count_stars_state::State, + St::Subject: count_stars_state::IsUnset, +{ + /// Set the `subject` field (required) + pub fn subject( + mut self, + value: impl Into, + ) -> CountStarsBuilder, S> { + self._fields.0 = Option::Some(value.into()); + CountStarsBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl CountStarsBuilder +where + St: count_stars_state::State, + St::Subject: count_stars_state::IsSet, +{ + /// Build the final struct. + pub fn build(self) -> CountStars { + CountStars { + subject: self._fields.0.unwrap(), + } + } +} diff --git a/crates/jacquard-api/src/sh_tangled/feed/count_stars_by.rs b/crates/jacquard-api/src/sh_tangled/feed/count_stars_by.rs new file mode 100644 index 000000000..fe3695d8b --- /dev/null +++ b/crates/jacquard-api/src/sh_tangled/feed/count_stars_by.rs @@ -0,0 +1,176 @@ +// @generated by jacquard-lexicon. DO NOT EDIT. +// +// Lexicon: sh.tangled.feed.countStarsBy +// +// 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::deps::smol_str::SmolStr; +use jacquard_common::types::string::Did; +use jacquard_common::types::value::Data; +use jacquard_common::{BosStr, DefaultStr, FromStaticStr}; +use jacquard_derive::IntoStatic; +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct CountStarsBy { + pub subject: Did, +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct CountStarsByOutput { + ///Total number of matching records. + pub count: i64, + ///Number of distinct authors among the matching records. + pub distinct_authors: i64, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +/** Response marker for the `sh.tangled.feed.countStarsBy` query. + +Implements `jacquard_common::xrpc::XrpcResp`; successful bodies decode as `Self::Output`, which is `CountStarsByOutput` for this endpoint.*/ +pub struct CountStarsByResponse; +impl jacquard_common::xrpc::XrpcResp for CountStarsByResponse { + const NSID: &'static str = "sh.tangled.feed.countStarsBy"; + const ENCODING: &'static str = "application/json"; + type Output = CountStarsByOutput; + type Err = jacquard_common::xrpc::GenericError; +} + +impl jacquard_common::xrpc::XrpcRequest for CountStarsBy { + const NSID: &'static str = "sh.tangled.feed.countStarsBy"; + const METHOD: jacquard_common::xrpc::XrpcMethod = jacquard_common::xrpc::XrpcMethod::Query; + type Response = CountStarsByResponse; +} + +/** Endpoint marker for the `sh.tangled.feed.countStarsBy` query. + +Path: `/xrpc/sh.tangled.feed.countStarsBy`. The request payload type is `CountStarsBy`; send that request with `jacquard::Client` or use this marker through lower-level `XrpcEndpoint` APIs.*/ +pub struct CountStarsByRequest; +impl jacquard_common::xrpc::XrpcEndpoint for CountStarsByRequest { + const PATH: &'static str = "/xrpc/sh.tangled.feed.countStarsBy"; + const METHOD: jacquard_common::xrpc::XrpcMethod = jacquard_common::xrpc::XrpcMethod::Query; + type Request = CountStarsBy; + type Response = CountStarsByResponse; +} + +pub mod count_stars_by_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 Subject; + } + /// Empty state - all required fields are unset + pub struct Empty(()); + impl sealed::Sealed for Empty {} + impl State for Empty { + type Subject = Unset; + } + ///State transition - sets the `subject` field to Set + pub struct SetSubject(PhantomData St>); + impl sealed::Sealed for SetSubject {} + impl State for SetSubject { + type Subject = Set; + } + /// Marker types for field names + #[allow(non_camel_case_types)] + pub mod members { + ///Marker type for the `subject` field + pub struct subject(()); + } +} + +/// Builder for constructing an instance of this type. +pub struct CountStarsByBuilder { + _state: PhantomData St>, + _fields: (Option>,), + _type: PhantomData S>, +} + +impl CountStarsBy { + /// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed + pub fn new() -> CountStarsByBuilder { + CountStarsByBuilder::new() + } +} + +impl CountStarsBy { + /// Create a new builder for this type + pub fn builder() -> CountStarsByBuilder { + CountStarsByBuilder::builder() + } +} + +impl CountStarsByBuilder { + /// Create a new builder with all fields unset, using the default string type, if needed + pub fn new() -> Self { + CountStarsByBuilder { + _state: PhantomData, + _fields: (None,), + _type: PhantomData, + } + } +} + +impl CountStarsByBuilder { + /// Create a new builder with all fields unset + pub fn builder() -> Self { + CountStarsByBuilder { + _state: PhantomData, + _fields: (None,), + _type: PhantomData, + } + } +} + +impl CountStarsByBuilder +where + St: count_stars_by_state::State, + St::Subject: count_stars_by_state::IsUnset, +{ + /// Set the `subject` field (required) + pub fn subject( + mut self, + value: impl Into>, + ) -> CountStarsByBuilder, S> { + self._fields.0 = Option::Some(value.into()); + CountStarsByBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl CountStarsByBuilder +where + St: count_stars_by_state::State, + St::Subject: count_stars_by_state::IsSet, +{ + /// Build the final struct. + pub fn build(self) -> CountStarsBy { + CountStarsBy { + subject: self._fields.0.unwrap(), + } + } +} diff --git a/crates/jacquard-api/src/sh_tangled/feed/list_comments.rs b/crates/jacquard-api/src/sh_tangled/feed/list_comments.rs index 0b2144fbd..d71afa5b2 100644 --- a/crates/jacquard-api/src/sh_tangled/feed/list_comments.rs +++ b/crates/jacquard-api/src/sh_tangled/feed/list_comments.rs @@ -359,7 +359,7 @@ fn lexicon_doc_sh_tangled_feed_listComments() -> LexiconDoc<'static> { SmolStr::new_static("subject"), LexXrpcParametersProperty::String(LexString { description: Some(CowStr::new_static( - "Record AT-URI the comments are attached to.", + "Record AT-URI the comments attach to.", )), format: Some(LexStringFormat::AtUri), ..Default::default() diff --git a/crates/jacquard-api/src/sh_tangled/git.rs b/crates/jacquard-api/src/sh_tangled/git.rs index e9d60353e..836e40024 100644 --- a/crates/jacquard-api/src/sh_tangled/git.rs +++ b/crates/jacquard-api/src/sh_tangled/git.rs @@ -4,6 +4,8 @@ // Any manual changes will be overwritten on the next regeneration. //! Generated bindings for the `sh.tangled.git` Lexicon namespace/module. +pub mod count_ref_updates; +pub mod count_ref_updates_by; pub mod list_ref_updates; pub mod list_ref_updates_by; pub mod list_refs; diff --git a/crates/jacquard-api/src/sh_tangled/git/count_ref_updates.rs b/crates/jacquard-api/src/sh_tangled/git/count_ref_updates.rs new file mode 100644 index 000000000..9ca1619d5 --- /dev/null +++ b/crates/jacquard-api/src/sh_tangled/git/count_ref_updates.rs @@ -0,0 +1,176 @@ +// @generated by jacquard-lexicon. DO NOT EDIT. +// +// Lexicon: sh.tangled.git.countRefUpdates +// +// 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::deps::smol_str::SmolStr; +use jacquard_common::types::string::Did; +use jacquard_common::types::value::Data; +use jacquard_common::{BosStr, DefaultStr, FromStaticStr}; +use jacquard_derive::IntoStatic; +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct CountRefUpdates { + pub subject: Did, +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct CountRefUpdatesOutput { + ///Total number of matching records. + pub count: i64, + ///Number of distinct authors among the matching records. + pub distinct_authors: i64, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +/** Response marker for the `sh.tangled.git.countRefUpdates` query. + +Implements `jacquard_common::xrpc::XrpcResp`; successful bodies decode as `Self::Output`, which is `CountRefUpdatesOutput` for this endpoint.*/ +pub struct CountRefUpdatesResponse; +impl jacquard_common::xrpc::XrpcResp for CountRefUpdatesResponse { + const NSID: &'static str = "sh.tangled.git.countRefUpdates"; + const ENCODING: &'static str = "application/json"; + type Output = CountRefUpdatesOutput; + type Err = jacquard_common::xrpc::GenericError; +} + +impl jacquard_common::xrpc::XrpcRequest for CountRefUpdates { + const NSID: &'static str = "sh.tangled.git.countRefUpdates"; + const METHOD: jacquard_common::xrpc::XrpcMethod = jacquard_common::xrpc::XrpcMethod::Query; + type Response = CountRefUpdatesResponse; +} + +/** Endpoint marker for the `sh.tangled.git.countRefUpdates` query. + +Path: `/xrpc/sh.tangled.git.countRefUpdates`. The request payload type is `CountRefUpdates`; send that request with `jacquard::Client` or use this marker through lower-level `XrpcEndpoint` APIs.*/ +pub struct CountRefUpdatesRequest; +impl jacquard_common::xrpc::XrpcEndpoint for CountRefUpdatesRequest { + const PATH: &'static str = "/xrpc/sh.tangled.git.countRefUpdates"; + const METHOD: jacquard_common::xrpc::XrpcMethod = jacquard_common::xrpc::XrpcMethod::Query; + type Request = CountRefUpdates; + type Response = CountRefUpdatesResponse; +} + +pub mod count_ref_updates_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 Subject; + } + /// Empty state - all required fields are unset + pub struct Empty(()); + impl sealed::Sealed for Empty {} + impl State for Empty { + type Subject = Unset; + } + ///State transition - sets the `subject` field to Set + pub struct SetSubject(PhantomData St>); + impl sealed::Sealed for SetSubject {} + impl State for SetSubject { + type Subject = Set; + } + /// Marker types for field names + #[allow(non_camel_case_types)] + pub mod members { + ///Marker type for the `subject` field + pub struct subject(()); + } +} + +/// Builder for constructing an instance of this type. +pub struct CountRefUpdatesBuilder { + _state: PhantomData St>, + _fields: (Option>,), + _type: PhantomData S>, +} + +impl CountRefUpdates { + /// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed + pub fn new() -> CountRefUpdatesBuilder { + CountRefUpdatesBuilder::new() + } +} + +impl CountRefUpdates { + /// Create a new builder for this type + pub fn builder() -> CountRefUpdatesBuilder { + CountRefUpdatesBuilder::builder() + } +} + +impl CountRefUpdatesBuilder { + /// Create a new builder with all fields unset, using the default string type, if needed + pub fn new() -> Self { + CountRefUpdatesBuilder { + _state: PhantomData, + _fields: (None,), + _type: PhantomData, + } + } +} + +impl CountRefUpdatesBuilder { + /// Create a new builder with all fields unset + pub fn builder() -> Self { + CountRefUpdatesBuilder { + _state: PhantomData, + _fields: (None,), + _type: PhantomData, + } + } +} + +impl CountRefUpdatesBuilder +where + St: count_ref_updates_state::State, + St::Subject: count_ref_updates_state::IsUnset, +{ + /// Set the `subject` field (required) + pub fn subject( + mut self, + value: impl Into>, + ) -> CountRefUpdatesBuilder, S> { + self._fields.0 = Option::Some(value.into()); + CountRefUpdatesBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl CountRefUpdatesBuilder +where + St: count_ref_updates_state::State, + St::Subject: count_ref_updates_state::IsSet, +{ + /// Build the final struct. + pub fn build(self) -> CountRefUpdates { + CountRefUpdates { + subject: self._fields.0.unwrap(), + } + } +} diff --git a/crates/jacquard-api/src/sh_tangled/git/count_ref_updates_by.rs b/crates/jacquard-api/src/sh_tangled/git/count_ref_updates_by.rs new file mode 100644 index 000000000..9e7706ea2 --- /dev/null +++ b/crates/jacquard-api/src/sh_tangled/git/count_ref_updates_by.rs @@ -0,0 +1,176 @@ +// @generated by jacquard-lexicon. DO NOT EDIT. +// +// Lexicon: sh.tangled.git.countRefUpdatesBy +// +// 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::deps::smol_str::SmolStr; +use jacquard_common::types::string::Did; +use jacquard_common::types::value::Data; +use jacquard_common::{BosStr, DefaultStr, FromStaticStr}; +use jacquard_derive::IntoStatic; +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct CountRefUpdatesBy { + pub subject: Did, +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct CountRefUpdatesByOutput { + ///Total number of matching records. + pub count: i64, + ///Number of distinct authors among the matching records. + pub distinct_authors: i64, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +/** Response marker for the `sh.tangled.git.countRefUpdatesBy` query. + +Implements `jacquard_common::xrpc::XrpcResp`; successful bodies decode as `Self::Output`, which is `CountRefUpdatesByOutput` for this endpoint.*/ +pub struct CountRefUpdatesByResponse; +impl jacquard_common::xrpc::XrpcResp for CountRefUpdatesByResponse { + const NSID: &'static str = "sh.tangled.git.countRefUpdatesBy"; + const ENCODING: &'static str = "application/json"; + type Output = CountRefUpdatesByOutput; + type Err = jacquard_common::xrpc::GenericError; +} + +impl jacquard_common::xrpc::XrpcRequest for CountRefUpdatesBy { + const NSID: &'static str = "sh.tangled.git.countRefUpdatesBy"; + const METHOD: jacquard_common::xrpc::XrpcMethod = jacquard_common::xrpc::XrpcMethod::Query; + type Response = CountRefUpdatesByResponse; +} + +/** Endpoint marker for the `sh.tangled.git.countRefUpdatesBy` query. + +Path: `/xrpc/sh.tangled.git.countRefUpdatesBy`. The request payload type is `CountRefUpdatesBy`; send that request with `jacquard::Client` or use this marker through lower-level `XrpcEndpoint` APIs.*/ +pub struct CountRefUpdatesByRequest; +impl jacquard_common::xrpc::XrpcEndpoint for CountRefUpdatesByRequest { + const PATH: &'static str = "/xrpc/sh.tangled.git.countRefUpdatesBy"; + const METHOD: jacquard_common::xrpc::XrpcMethod = jacquard_common::xrpc::XrpcMethod::Query; + type Request = CountRefUpdatesBy; + type Response = CountRefUpdatesByResponse; +} + +pub mod count_ref_updates_by_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 Subject; + } + /// Empty state - all required fields are unset + pub struct Empty(()); + impl sealed::Sealed for Empty {} + impl State for Empty { + type Subject = Unset; + } + ///State transition - sets the `subject` field to Set + pub struct SetSubject(PhantomData St>); + impl sealed::Sealed for SetSubject {} + impl State for SetSubject { + type Subject = Set; + } + /// Marker types for field names + #[allow(non_camel_case_types)] + pub mod members { + ///Marker type for the `subject` field + pub struct subject(()); + } +} + +/// Builder for constructing an instance of this type. +pub struct CountRefUpdatesByBuilder { + _state: PhantomData St>, + _fields: (Option>,), + _type: PhantomData S>, +} + +impl CountRefUpdatesBy { + /// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed + pub fn new() -> CountRefUpdatesByBuilder { + CountRefUpdatesByBuilder::new() + } +} + +impl CountRefUpdatesBy { + /// Create a new builder for this type + pub fn builder() -> CountRefUpdatesByBuilder { + CountRefUpdatesByBuilder::builder() + } +} + +impl CountRefUpdatesByBuilder { + /// Create a new builder with all fields unset, using the default string type, if needed + pub fn new() -> Self { + CountRefUpdatesByBuilder { + _state: PhantomData, + _fields: (None,), + _type: PhantomData, + } + } +} + +impl CountRefUpdatesByBuilder { + /// Create a new builder with all fields unset + pub fn builder() -> Self { + CountRefUpdatesByBuilder { + _state: PhantomData, + _fields: (None,), + _type: PhantomData, + } + } +} + +impl CountRefUpdatesByBuilder +where + St: count_ref_updates_by_state::State, + St::Subject: count_ref_updates_by_state::IsUnset, +{ + /// Set the `subject` field (required) + pub fn subject( + mut self, + value: impl Into>, + ) -> CountRefUpdatesByBuilder, S> { + self._fields.0 = Option::Some(value.into()); + CountRefUpdatesByBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl CountRefUpdatesByBuilder +where + St: count_ref_updates_by_state::State, + St::Subject: count_ref_updates_by_state::IsSet, +{ + /// Build the final struct. + pub fn build(self) -> CountRefUpdatesBy { + CountRefUpdatesBy { + subject: self._fields.0.unwrap(), + } + } +} diff --git a/crates/jacquard-api/src/sh_tangled/git/ref_update.rs b/crates/jacquard-api/src/sh_tangled/git/ref_update.rs index bc8cb2fda..9bb8ab557 100644 --- a/crates/jacquard-api/src/sh_tangled/git/ref_update.rs +++ b/crates/jacquard-api/src/sh_tangled/git/ref_update.rs @@ -77,7 +77,7 @@ pub struct LangBreakdown { pub extra_data: Option>>, } -/// An update to a git repository, emitted by knots. +/// An event record representing git-push operation to git repository, emitted by knots. #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] #[serde( @@ -87,6 +87,9 @@ pub struct LangBreakdown { bound(deserialize = "S: Deserialize<'de> + BosStr") )] pub struct RefUpdate { + ///files changed between commits + #[serde(skip_serializing_if = "Option::is_none")] + pub changed_files: Option>, ///did of the user that pushed this ref pub committer_did: Did, pub meta: ref_update::Meta, @@ -97,6 +100,9 @@ pub struct RefUpdate { ///did of the owner of the repo #[serde(skip_serializing_if = "Option::is_none")] pub owner_did: Option>, + ///push options passed on git-push + #[serde(skip_serializing_if = "Option::is_none")] + pub push_options: Option>, ///Ref being updated pub r#ref: S, ///DID of the repo itself @@ -280,6 +286,28 @@ impl LexiconSchema for RefUpdate { }); } } + if let Some(ref value) = self.push_options { + #[allow(unused_comparisons)] + if value.len() > 50usize { + return Err(ConstraintError::MaxLength { + path: ValidationPath::from_field("push_options"), + max: 50usize, + actual: value.len(), + }); + } + } + if let Some(values) = &self.push_options { + for value in values { + #[allow(unused_comparisons)] + if ::len(value.as_ref()) > 1024usize { + return Err(ConstraintError::MaxLength { + path: ValidationPath::from_field("push_options"), + max: 1024usize, + actual: ::len(value.as_ref()), + }); + } + } + } { let value = &self.r#ref; #[allow(unused_comparisons)] @@ -433,28 +461,42 @@ fn lexicon_doc_sh_tangled_git_refUpdate() -> LexiconDoc<'static> { map.insert( SmolStr::new_static("main"), LexUserType::Record(LexRecord { - description: Some(CowStr::new_static( - "An update to a git repository, emitted by knots.", - )), + description: Some( + CowStr::new_static( + "An event record representing git-push operation to git repository, emitted by knots.", + ), + ), key: Some(CowStr::new_static("tid")), record: LexRecordRecord::Object(LexObject { - required: Some(vec![ - SmolStr::new_static("ref"), - SmolStr::new_static("committerDid"), - SmolStr::new_static("repo"), - SmolStr::new_static("oldSha"), - SmolStr::new_static("newSha"), - SmolStr::new_static("meta"), - ]), + required: Some( + vec![ + SmolStr::new_static("ref"), + SmolStr::new_static("committerDid"), + SmolStr::new_static("repo"), SmolStr::new_static("oldSha"), + SmolStr::new_static("newSha"), SmolStr::new_static("meta") + ], + ), properties: { #[allow(unused_mut)] let mut map = BTreeMap::new(); + map.insert( + SmolStr::new_static("changedFiles"), + LexObjectProperty::Array(LexArray { + description: Some( + CowStr::new_static("files changed between commits"), + ), + items: LexArrayItem::String(LexString { + ..Default::default() + }), + ..Default::default() + }), + ); map.insert( SmolStr::new_static("committerDid"), LexObjectProperty::String(LexString { - description: Some(CowStr::new_static( - "did of the user that pushed this ref", - )), + description: Some( + CowStr::new_static("did of the user that pushed this ref"), + ), format: Some(LexStringFormat::Did), ..Default::default() }), @@ -469,7 +511,9 @@ fn lexicon_doc_sh_tangled_git_refUpdate() -> LexiconDoc<'static> { map.insert( SmolStr::new_static("newSha"), LexObjectProperty::String(LexString { - description: Some(CowStr::new_static("new SHA of this ref")), + description: Some( + CowStr::new_static("new SHA of this ref"), + ), min_length: Some(40usize), max_length: Some(40usize), ..Default::default() @@ -478,7 +522,9 @@ fn lexicon_doc_sh_tangled_git_refUpdate() -> LexiconDoc<'static> { map.insert( SmolStr::new_static("oldSha"), LexObjectProperty::String(LexString { - description: Some(CowStr::new_static("old SHA of this ref")), + description: Some( + CowStr::new_static("old SHA of this ref"), + ), min_length: Some(40usize), max_length: Some(40usize), ..Default::default() @@ -487,13 +533,27 @@ fn lexicon_doc_sh_tangled_git_refUpdate() -> LexiconDoc<'static> { map.insert( SmolStr::new_static("ownerDid"), LexObjectProperty::String(LexString { - description: Some(CowStr::new_static( - "did of the owner of the repo", - )), + description: Some( + CowStr::new_static("did of the owner of the repo"), + ), format: Some(LexStringFormat::Did), ..Default::default() }), ); + map.insert( + SmolStr::new_static("pushOptions"), + LexObjectProperty::Array(LexArray { + description: Some( + CowStr::new_static("push options passed on git-push"), + ), + items: LexArrayItem::String(LexString { + max_length: Some(1024usize), + ..Default::default() + }), + max_length: Some(50usize), + ..Default::default() + }), + ); map.insert( SmolStr::new_static("ref"), LexObjectProperty::String(LexString { @@ -506,7 +566,9 @@ fn lexicon_doc_sh_tangled_git_refUpdate() -> LexiconDoc<'static> { map.insert( SmolStr::new_static("repo"), LexObjectProperty::String(LexString { - description: Some(CowStr::new_static("DID of the repo itself")), + description: Some( + CowStr::new_static("DID of the repo itself"), + ), format: Some(LexStringFormat::Did), ..Default::default() }), @@ -991,11 +1053,13 @@ pub mod ref_update_state { pub struct RefUpdateBuilder { _state: PhantomData St>, _fields: ( + Option>, Option>, Option>, Option, Option, Option>, + Option>, Option, Option>, ), @@ -1021,7 +1085,7 @@ impl RefUpdateBuilder { pub fn new() -> Self { RefUpdateBuilder { _state: PhantomData, - _fields: (None, None, None, None, None, None, None), + _fields: (None, None, None, None, None, None, None, None, None), _type: PhantomData, } } @@ -1032,12 +1096,25 @@ impl RefUpdateBuilder { pub fn builder() -> Self { RefUpdateBuilder { _state: PhantomData, - _fields: (None, None, None, None, None, None, None), + _fields: (None, None, None, None, None, None, None, None, None), _type: PhantomData, } } } +impl RefUpdateBuilder { + /// Set the `changedFiles` field (optional) + pub fn changed_files(mut self, value: impl Into>>) -> Self { + self._fields.0 = value.into(); + self + } + /// Set the `changedFiles` field to an Option value (optional) + pub fn maybe_changed_files(mut self, value: Option>) -> Self { + self._fields.0 = value; + self + } +} + impl RefUpdateBuilder where St: ref_update_state::State, @@ -1048,7 +1125,7 @@ where mut self, value: impl Into>, ) -> RefUpdateBuilder, S> { - self._fields.0 = Option::Some(value.into()); + self._fields.1 = Option::Some(value.into()); RefUpdateBuilder { _state: PhantomData, _fields: self._fields, @@ -1067,7 +1144,7 @@ where mut self, value: impl Into>, ) -> RefUpdateBuilder, S> { - self._fields.1 = Option::Some(value.into()); + self._fields.2 = Option::Some(value.into()); RefUpdateBuilder { _state: PhantomData, _fields: self._fields, @@ -1086,7 +1163,7 @@ where mut self, value: impl Into, ) -> RefUpdateBuilder, S> { - self._fields.2 = Option::Some(value.into()); + self._fields.3 = Option::Some(value.into()); RefUpdateBuilder { _state: PhantomData, _fields: self._fields, @@ -1105,7 +1182,7 @@ where mut self, value: impl Into, ) -> RefUpdateBuilder, S> { - self._fields.3 = Option::Some(value.into()); + self._fields.4 = Option::Some(value.into()); RefUpdateBuilder { _state: PhantomData, _fields: self._fields, @@ -1117,12 +1194,25 @@ where impl RefUpdateBuilder { /// Set the `ownerDid` field (optional) pub fn owner_did(mut self, value: impl Into>>) -> Self { - self._fields.4 = value.into(); + self._fields.5 = value.into(); self } /// Set the `ownerDid` field to an Option value (optional) pub fn maybe_owner_did(mut self, value: Option>) -> Self { - self._fields.4 = value; + self._fields.5 = value; + self + } +} + +impl RefUpdateBuilder { + /// Set the `pushOptions` field (optional) + pub fn push_options(mut self, value: impl Into>>) -> Self { + self._fields.6 = value.into(); + self + } + /// Set the `pushOptions` field to an Option value (optional) + pub fn maybe_push_options(mut self, value: Option>) -> Self { + self._fields.6 = value; self } } @@ -1137,7 +1227,7 @@ where mut self, value: impl Into, ) -> RefUpdateBuilder, S> { - self._fields.5 = Option::Some(value.into()); + self._fields.7 = Option::Some(value.into()); RefUpdateBuilder { _state: PhantomData, _fields: self._fields, @@ -1156,7 +1246,7 @@ where mut self, value: impl Into>, ) -> RefUpdateBuilder, S> { - self._fields.6 = Option::Some(value.into()); + self._fields.8 = Option::Some(value.into()); RefUpdateBuilder { _state: PhantomData, _fields: self._fields, @@ -1178,26 +1268,30 @@ where /// Build the final struct. pub fn build(self) -> RefUpdate { RefUpdate { - committer_did: self._fields.0.unwrap(), - meta: self._fields.1.unwrap(), - new_sha: self._fields.2.unwrap(), - old_sha: self._fields.3.unwrap(), - owner_did: self._fields.4, - r#ref: self._fields.5.unwrap(), - repo: self._fields.6.unwrap(), + changed_files: self._fields.0, + committer_did: self._fields.1.unwrap(), + meta: self._fields.2.unwrap(), + new_sha: self._fields.3.unwrap(), + old_sha: self._fields.4.unwrap(), + owner_did: self._fields.5, + push_options: self._fields.6, + r#ref: self._fields.7.unwrap(), + repo: self._fields.8.unwrap(), extra_data: Default::default(), } } /// Build the final struct with custom extra_data. pub fn build_with_data(self, extra_data: BTreeMap>) -> RefUpdate { RefUpdate { - committer_did: self._fields.0.unwrap(), - meta: self._fields.1.unwrap(), - new_sha: self._fields.2.unwrap(), - old_sha: self._fields.3.unwrap(), - owner_did: self._fields.4, - r#ref: self._fields.5.unwrap(), - repo: self._fields.6.unwrap(), + changed_files: self._fields.0, + committer_did: self._fields.1.unwrap(), + meta: self._fields.2.unwrap(), + new_sha: self._fields.3.unwrap(), + old_sha: self._fields.4.unwrap(), + owner_did: self._fields.5, + push_options: self._fields.6, + r#ref: self._fields.7.unwrap(), + repo: self._fields.8.unwrap(), extra_data: Some(extra_data), } } diff --git a/crates/jacquard-api/src/sh_tangled/graph.rs b/crates/jacquard-api/src/sh_tangled/graph.rs index 527c07ace..7cb9ce86d 100644 --- a/crates/jacquard-api/src/sh_tangled/graph.rs +++ b/crates/jacquard-api/src/sh_tangled/graph.rs @@ -4,6 +4,10 @@ // Any manual changes will be overwritten on the next regeneration. //! Generated bindings for the `sh.tangled.graph` Lexicon namespace/module. +pub mod count_follows; +pub mod count_follows_by; +pub mod count_vouches; +pub mod count_vouches_by; pub mod follow; pub mod list_follows; pub mod list_follows_by; diff --git a/crates/jacquard-api/src/sh_tangled/graph/count_follows.rs b/crates/jacquard-api/src/sh_tangled/graph/count_follows.rs new file mode 100644 index 000000000..ff7ad1027 --- /dev/null +++ b/crates/jacquard-api/src/sh_tangled/graph/count_follows.rs @@ -0,0 +1,176 @@ +// @generated by jacquard-lexicon. DO NOT EDIT. +// +// Lexicon: sh.tangled.graph.countFollows +// +// 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::deps::smol_str::SmolStr; +use jacquard_common::types::string::Did; +use jacquard_common::types::value::Data; +use jacquard_common::{BosStr, DefaultStr, FromStaticStr}; +use jacquard_derive::IntoStatic; +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct CountFollows { + pub subject: Did, +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct CountFollowsOutput { + ///Total number of matching records. + pub count: i64, + ///Number of distinct authors among the matching records. + pub distinct_authors: i64, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +/** Response marker for the `sh.tangled.graph.countFollows` query. + +Implements `jacquard_common::xrpc::XrpcResp`; successful bodies decode as `Self::Output`, which is `CountFollowsOutput` for this endpoint.*/ +pub struct CountFollowsResponse; +impl jacquard_common::xrpc::XrpcResp for CountFollowsResponse { + const NSID: &'static str = "sh.tangled.graph.countFollows"; + const ENCODING: &'static str = "application/json"; + type Output = CountFollowsOutput; + type Err = jacquard_common::xrpc::GenericError; +} + +impl jacquard_common::xrpc::XrpcRequest for CountFollows { + const NSID: &'static str = "sh.tangled.graph.countFollows"; + const METHOD: jacquard_common::xrpc::XrpcMethod = jacquard_common::xrpc::XrpcMethod::Query; + type Response = CountFollowsResponse; +} + +/** Endpoint marker for the `sh.tangled.graph.countFollows` query. + +Path: `/xrpc/sh.tangled.graph.countFollows`. The request payload type is `CountFollows`; send that request with `jacquard::Client` or use this marker through lower-level `XrpcEndpoint` APIs.*/ +pub struct CountFollowsRequest; +impl jacquard_common::xrpc::XrpcEndpoint for CountFollowsRequest { + const PATH: &'static str = "/xrpc/sh.tangled.graph.countFollows"; + const METHOD: jacquard_common::xrpc::XrpcMethod = jacquard_common::xrpc::XrpcMethod::Query; + type Request = CountFollows; + type Response = CountFollowsResponse; +} + +pub mod count_follows_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 Subject; + } + /// Empty state - all required fields are unset + pub struct Empty(()); + impl sealed::Sealed for Empty {} + impl State for Empty { + type Subject = Unset; + } + ///State transition - sets the `subject` field to Set + pub struct SetSubject(PhantomData St>); + impl sealed::Sealed for SetSubject {} + impl State for SetSubject { + type Subject = Set; + } + /// Marker types for field names + #[allow(non_camel_case_types)] + pub mod members { + ///Marker type for the `subject` field + pub struct subject(()); + } +} + +/// Builder for constructing an instance of this type. +pub struct CountFollowsBuilder { + _state: PhantomData St>, + _fields: (Option>,), + _type: PhantomData S>, +} + +impl CountFollows { + /// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed + pub fn new() -> CountFollowsBuilder { + CountFollowsBuilder::new() + } +} + +impl CountFollows { + /// Create a new builder for this type + pub fn builder() -> CountFollowsBuilder { + CountFollowsBuilder::builder() + } +} + +impl CountFollowsBuilder { + /// Create a new builder with all fields unset, using the default string type, if needed + pub fn new() -> Self { + CountFollowsBuilder { + _state: PhantomData, + _fields: (None,), + _type: PhantomData, + } + } +} + +impl CountFollowsBuilder { + /// Create a new builder with all fields unset + pub fn builder() -> Self { + CountFollowsBuilder { + _state: PhantomData, + _fields: (None,), + _type: PhantomData, + } + } +} + +impl CountFollowsBuilder +where + St: count_follows_state::State, + St::Subject: count_follows_state::IsUnset, +{ + /// Set the `subject` field (required) + pub fn subject( + mut self, + value: impl Into>, + ) -> CountFollowsBuilder, S> { + self._fields.0 = Option::Some(value.into()); + CountFollowsBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl CountFollowsBuilder +where + St: count_follows_state::State, + St::Subject: count_follows_state::IsSet, +{ + /// Build the final struct. + pub fn build(self) -> CountFollows { + CountFollows { + subject: self._fields.0.unwrap(), + } + } +} diff --git a/crates/jacquard-api/src/sh_tangled/graph/count_follows_by.rs b/crates/jacquard-api/src/sh_tangled/graph/count_follows_by.rs new file mode 100644 index 000000000..52d7d9f8b --- /dev/null +++ b/crates/jacquard-api/src/sh_tangled/graph/count_follows_by.rs @@ -0,0 +1,176 @@ +// @generated by jacquard-lexicon. DO NOT EDIT. +// +// Lexicon: sh.tangled.graph.countFollowsBy +// +// 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::deps::smol_str::SmolStr; +use jacquard_common::types::string::Did; +use jacquard_common::types::value::Data; +use jacquard_common::{BosStr, DefaultStr, FromStaticStr}; +use jacquard_derive::IntoStatic; +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct CountFollowsBy { + pub subject: Did, +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct CountFollowsByOutput { + ///Total number of matching records. + pub count: i64, + ///Number of distinct authors among the matching records. + pub distinct_authors: i64, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +/** Response marker for the `sh.tangled.graph.countFollowsBy` query. + +Implements `jacquard_common::xrpc::XrpcResp`; successful bodies decode as `Self::Output`, which is `CountFollowsByOutput` for this endpoint.*/ +pub struct CountFollowsByResponse; +impl jacquard_common::xrpc::XrpcResp for CountFollowsByResponse { + const NSID: &'static str = "sh.tangled.graph.countFollowsBy"; + const ENCODING: &'static str = "application/json"; + type Output = CountFollowsByOutput; + type Err = jacquard_common::xrpc::GenericError; +} + +impl jacquard_common::xrpc::XrpcRequest for CountFollowsBy { + const NSID: &'static str = "sh.tangled.graph.countFollowsBy"; + const METHOD: jacquard_common::xrpc::XrpcMethod = jacquard_common::xrpc::XrpcMethod::Query; + type Response = CountFollowsByResponse; +} + +/** Endpoint marker for the `sh.tangled.graph.countFollowsBy` query. + +Path: `/xrpc/sh.tangled.graph.countFollowsBy`. The request payload type is `CountFollowsBy`; send that request with `jacquard::Client` or use this marker through lower-level `XrpcEndpoint` APIs.*/ +pub struct CountFollowsByRequest; +impl jacquard_common::xrpc::XrpcEndpoint for CountFollowsByRequest { + const PATH: &'static str = "/xrpc/sh.tangled.graph.countFollowsBy"; + const METHOD: jacquard_common::xrpc::XrpcMethod = jacquard_common::xrpc::XrpcMethod::Query; + type Request = CountFollowsBy; + type Response = CountFollowsByResponse; +} + +pub mod count_follows_by_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 Subject; + } + /// Empty state - all required fields are unset + pub struct Empty(()); + impl sealed::Sealed for Empty {} + impl State for Empty { + type Subject = Unset; + } + ///State transition - sets the `subject` field to Set + pub struct SetSubject(PhantomData St>); + impl sealed::Sealed for SetSubject {} + impl State for SetSubject { + type Subject = Set; + } + /// Marker types for field names + #[allow(non_camel_case_types)] + pub mod members { + ///Marker type for the `subject` field + pub struct subject(()); + } +} + +/// Builder for constructing an instance of this type. +pub struct CountFollowsByBuilder { + _state: PhantomData St>, + _fields: (Option>,), + _type: PhantomData S>, +} + +impl CountFollowsBy { + /// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed + pub fn new() -> CountFollowsByBuilder { + CountFollowsByBuilder::new() + } +} + +impl CountFollowsBy { + /// Create a new builder for this type + pub fn builder() -> CountFollowsByBuilder { + CountFollowsByBuilder::builder() + } +} + +impl CountFollowsByBuilder { + /// Create a new builder with all fields unset, using the default string type, if needed + pub fn new() -> Self { + CountFollowsByBuilder { + _state: PhantomData, + _fields: (None,), + _type: PhantomData, + } + } +} + +impl CountFollowsByBuilder { + /// Create a new builder with all fields unset + pub fn builder() -> Self { + CountFollowsByBuilder { + _state: PhantomData, + _fields: (None,), + _type: PhantomData, + } + } +} + +impl CountFollowsByBuilder +where + St: count_follows_by_state::State, + St::Subject: count_follows_by_state::IsUnset, +{ + /// Set the `subject` field (required) + pub fn subject( + mut self, + value: impl Into>, + ) -> CountFollowsByBuilder, S> { + self._fields.0 = Option::Some(value.into()); + CountFollowsByBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl CountFollowsByBuilder +where + St: count_follows_by_state::State, + St::Subject: count_follows_by_state::IsSet, +{ + /// Build the final struct. + pub fn build(self) -> CountFollowsBy { + CountFollowsBy { + subject: self._fields.0.unwrap(), + } + } +} diff --git a/crates/jacquard-api/src/sh_tangled/graph/count_vouches.rs b/crates/jacquard-api/src/sh_tangled/graph/count_vouches.rs new file mode 100644 index 000000000..ca210e44b --- /dev/null +++ b/crates/jacquard-api/src/sh_tangled/graph/count_vouches.rs @@ -0,0 +1,176 @@ +// @generated by jacquard-lexicon. DO NOT EDIT. +// +// Lexicon: sh.tangled.graph.countVouches +// +// 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::deps::smol_str::SmolStr; +use jacquard_common::types::string::Did; +use jacquard_common::types::value::Data; +use jacquard_common::{BosStr, DefaultStr, FromStaticStr}; +use jacquard_derive::IntoStatic; +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct CountVouches { + pub subject: Did, +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct CountVouchesOutput { + ///Total number of matching records. + pub count: i64, + ///Number of distinct authors among the matching records. + pub distinct_authors: i64, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +/** Response marker for the `sh.tangled.graph.countVouches` query. + +Implements `jacquard_common::xrpc::XrpcResp`; successful bodies decode as `Self::Output`, which is `CountVouchesOutput` for this endpoint.*/ +pub struct CountVouchesResponse; +impl jacquard_common::xrpc::XrpcResp for CountVouchesResponse { + const NSID: &'static str = "sh.tangled.graph.countVouches"; + const ENCODING: &'static str = "application/json"; + type Output = CountVouchesOutput; + type Err = jacquard_common::xrpc::GenericError; +} + +impl jacquard_common::xrpc::XrpcRequest for CountVouches { + const NSID: &'static str = "sh.tangled.graph.countVouches"; + const METHOD: jacquard_common::xrpc::XrpcMethod = jacquard_common::xrpc::XrpcMethod::Query; + type Response = CountVouchesResponse; +} + +/** Endpoint marker for the `sh.tangled.graph.countVouches` query. + +Path: `/xrpc/sh.tangled.graph.countVouches`. The request payload type is `CountVouches`; send that request with `jacquard::Client` or use this marker through lower-level `XrpcEndpoint` APIs.*/ +pub struct CountVouchesRequest; +impl jacquard_common::xrpc::XrpcEndpoint for CountVouchesRequest { + const PATH: &'static str = "/xrpc/sh.tangled.graph.countVouches"; + const METHOD: jacquard_common::xrpc::XrpcMethod = jacquard_common::xrpc::XrpcMethod::Query; + type Request = CountVouches; + type Response = CountVouchesResponse; +} + +pub mod count_vouches_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 Subject; + } + /// Empty state - all required fields are unset + pub struct Empty(()); + impl sealed::Sealed for Empty {} + impl State for Empty { + type Subject = Unset; + } + ///State transition - sets the `subject` field to Set + pub struct SetSubject(PhantomData St>); + impl sealed::Sealed for SetSubject {} + impl State for SetSubject { + type Subject = Set; + } + /// Marker types for field names + #[allow(non_camel_case_types)] + pub mod members { + ///Marker type for the `subject` field + pub struct subject(()); + } +} + +/// Builder for constructing an instance of this type. +pub struct CountVouchesBuilder { + _state: PhantomData St>, + _fields: (Option>,), + _type: PhantomData S>, +} + +impl CountVouches { + /// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed + pub fn new() -> CountVouchesBuilder { + CountVouchesBuilder::new() + } +} + +impl CountVouches { + /// Create a new builder for this type + pub fn builder() -> CountVouchesBuilder { + CountVouchesBuilder::builder() + } +} + +impl CountVouchesBuilder { + /// Create a new builder with all fields unset, using the default string type, if needed + pub fn new() -> Self { + CountVouchesBuilder { + _state: PhantomData, + _fields: (None,), + _type: PhantomData, + } + } +} + +impl CountVouchesBuilder { + /// Create a new builder with all fields unset + pub fn builder() -> Self { + CountVouchesBuilder { + _state: PhantomData, + _fields: (None,), + _type: PhantomData, + } + } +} + +impl CountVouchesBuilder +where + St: count_vouches_state::State, + St::Subject: count_vouches_state::IsUnset, +{ + /// Set the `subject` field (required) + pub fn subject( + mut self, + value: impl Into>, + ) -> CountVouchesBuilder, S> { + self._fields.0 = Option::Some(value.into()); + CountVouchesBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl CountVouchesBuilder +where + St: count_vouches_state::State, + St::Subject: count_vouches_state::IsSet, +{ + /// Build the final struct. + pub fn build(self) -> CountVouches { + CountVouches { + subject: self._fields.0.unwrap(), + } + } +} diff --git a/crates/jacquard-api/src/sh_tangled/graph/count_vouches_by.rs b/crates/jacquard-api/src/sh_tangled/graph/count_vouches_by.rs new file mode 100644 index 000000000..e8ca6b942 --- /dev/null +++ b/crates/jacquard-api/src/sh_tangled/graph/count_vouches_by.rs @@ -0,0 +1,176 @@ +// @generated by jacquard-lexicon. DO NOT EDIT. +// +// Lexicon: sh.tangled.graph.countVouchesBy +// +// 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::deps::smol_str::SmolStr; +use jacquard_common::types::string::Did; +use jacquard_common::types::value::Data; +use jacquard_common::{BosStr, DefaultStr, FromStaticStr}; +use jacquard_derive::IntoStatic; +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct CountVouchesBy { + pub subject: Did, +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct CountVouchesByOutput { + ///Total number of matching records. + pub count: i64, + ///Number of distinct authors among the matching records. + pub distinct_authors: i64, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +/** Response marker for the `sh.tangled.graph.countVouchesBy` query. + +Implements `jacquard_common::xrpc::XrpcResp`; successful bodies decode as `Self::Output`, which is `CountVouchesByOutput` for this endpoint.*/ +pub struct CountVouchesByResponse; +impl jacquard_common::xrpc::XrpcResp for CountVouchesByResponse { + const NSID: &'static str = "sh.tangled.graph.countVouchesBy"; + const ENCODING: &'static str = "application/json"; + type Output = CountVouchesByOutput; + type Err = jacquard_common::xrpc::GenericError; +} + +impl jacquard_common::xrpc::XrpcRequest for CountVouchesBy { + const NSID: &'static str = "sh.tangled.graph.countVouchesBy"; + const METHOD: jacquard_common::xrpc::XrpcMethod = jacquard_common::xrpc::XrpcMethod::Query; + type Response = CountVouchesByResponse; +} + +/** Endpoint marker for the `sh.tangled.graph.countVouchesBy` query. + +Path: `/xrpc/sh.tangled.graph.countVouchesBy`. The request payload type is `CountVouchesBy`; send that request with `jacquard::Client` or use this marker through lower-level `XrpcEndpoint` APIs.*/ +pub struct CountVouchesByRequest; +impl jacquard_common::xrpc::XrpcEndpoint for CountVouchesByRequest { + const PATH: &'static str = "/xrpc/sh.tangled.graph.countVouchesBy"; + const METHOD: jacquard_common::xrpc::XrpcMethod = jacquard_common::xrpc::XrpcMethod::Query; + type Request = CountVouchesBy; + type Response = CountVouchesByResponse; +} + +pub mod count_vouches_by_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 Subject; + } + /// Empty state - all required fields are unset + pub struct Empty(()); + impl sealed::Sealed for Empty {} + impl State for Empty { + type Subject = Unset; + } + ///State transition - sets the `subject` field to Set + pub struct SetSubject(PhantomData St>); + impl sealed::Sealed for SetSubject {} + impl State for SetSubject { + type Subject = Set; + } + /// Marker types for field names + #[allow(non_camel_case_types)] + pub mod members { + ///Marker type for the `subject` field + pub struct subject(()); + } +} + +/// Builder for constructing an instance of this type. +pub struct CountVouchesByBuilder { + _state: PhantomData St>, + _fields: (Option>,), + _type: PhantomData S>, +} + +impl CountVouchesBy { + /// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed + pub fn new() -> CountVouchesByBuilder { + CountVouchesByBuilder::new() + } +} + +impl CountVouchesBy { + /// Create a new builder for this type + pub fn builder() -> CountVouchesByBuilder { + CountVouchesByBuilder::builder() + } +} + +impl CountVouchesByBuilder { + /// Create a new builder with all fields unset, using the default string type, if needed + pub fn new() -> Self { + CountVouchesByBuilder { + _state: PhantomData, + _fields: (None,), + _type: PhantomData, + } + } +} + +impl CountVouchesByBuilder { + /// Create a new builder with all fields unset + pub fn builder() -> Self { + CountVouchesByBuilder { + _state: PhantomData, + _fields: (None,), + _type: PhantomData, + } + } +} + +impl CountVouchesByBuilder +where + St: count_vouches_by_state::State, + St::Subject: count_vouches_by_state::IsUnset, +{ + /// Set the `subject` field (required) + pub fn subject( + mut self, + value: impl Into>, + ) -> CountVouchesByBuilder, S> { + self._fields.0 = Option::Some(value.into()); + CountVouchesByBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl CountVouchesByBuilder +where + St: count_vouches_by_state::State, + St::Subject: count_vouches_by_state::IsSet, +{ + /// Build the final struct. + pub fn build(self) -> CountVouchesBy { + CountVouchesBy { + subject: self._fields.0.unwrap(), + } + } +} diff --git a/crates/jacquard-api/src/sh_tangled/knot.rs b/crates/jacquard-api/src/sh_tangled/knot.rs index a1a448972..3cd02a266 100644 --- a/crates/jacquard-api/src/sh_tangled/knot.rs +++ b/crates/jacquard-api/src/sh_tangled/knot.rs @@ -7,6 +7,10 @@ //! Generated bindings for the `sh.tangled.knot` Lexicon namespace/module. pub mod add_member; +pub mod ban; +pub mod count_knots; +pub mod count_members; +pub mod count_members_by; pub mod list_keys; pub mod list_knots; pub mod list_members; @@ -16,6 +20,7 @@ pub mod remove_member; #[cfg(feature = "streaming")] pub mod subscribe_repos; +pub mod unban; pub mod version; #[allow(unused_imports)] diff --git a/crates/jacquard-api/src/sh_tangled/knot/ban.rs b/crates/jacquard-api/src/sh_tangled/knot/ban.rs new file mode 100644 index 000000000..7f5e8d0c5 --- /dev/null +++ b/crates/jacquard-api/src/sh_tangled/knot/ban.rs @@ -0,0 +1,172 @@ +// @generated by jacquard-lexicon. DO NOT EDIT. +// +// Lexicon: sh.tangled.knot.ban +// +// 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::deps::smol_str::SmolStr; +use jacquard_common::types::string::Did; +use jacquard_common::types::value::Data; +use jacquard_common::{BosStr, DefaultStr, FromStaticStr}; +use jacquard_derive::IntoStatic; +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct Ban { + ///DID of the account to block + pub subject: Did, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +/** Response marker for the `sh.tangled.knot.ban` procedure. + +Implements `jacquard_common::xrpc::XrpcResp`; successful bodies decode as `Self::Output`, which is `()` for this endpoint.*/ +pub struct BanResponse; +impl jacquard_common::xrpc::XrpcResp for BanResponse { + const NSID: &'static str = "sh.tangled.knot.ban"; + const ENCODING: &'static str = "application/json"; + type Output = (); + type Err = jacquard_common::xrpc::GenericError; +} + +impl jacquard_common::xrpc::XrpcRequest for Ban { + const NSID: &'static str = "sh.tangled.knot.ban"; + const METHOD: jacquard_common::xrpc::XrpcMethod = + jacquard_common::xrpc::XrpcMethod::Procedure("application/json"); + type Response = BanResponse; +} + +/** Endpoint marker for the `sh.tangled.knot.ban` procedure. + +Path: `/xrpc/sh.tangled.knot.ban`. The request payload type is `Ban`; send that request with `jacquard::Client` or use this marker through lower-level `XrpcEndpoint` APIs.*/ +pub struct BanRequest; +impl jacquard_common::xrpc::XrpcEndpoint for BanRequest { + const PATH: &'static str = "/xrpc/sh.tangled.knot.ban"; + const METHOD: jacquard_common::xrpc::XrpcMethod = + jacquard_common::xrpc::XrpcMethod::Procedure("application/json"); + type Request = Ban; + type Response = BanResponse; +} + +pub mod ban_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 Subject; + } + /// Empty state - all required fields are unset + pub struct Empty(()); + impl sealed::Sealed for Empty {} + impl State for Empty { + type Subject = Unset; + } + ///State transition - sets the `subject` field to Set + pub struct SetSubject(PhantomData St>); + impl sealed::Sealed for SetSubject {} + impl State for SetSubject { + type Subject = Set; + } + /// Marker types for field names + #[allow(non_camel_case_types)] + pub mod members { + ///Marker type for the `subject` field + pub struct subject(()); + } +} + +/// Builder for constructing an instance of this type. +pub struct BanBuilder { + _state: PhantomData St>, + _fields: (Option>,), + _type: PhantomData S>, +} + +impl Ban { + /// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed + pub fn new() -> BanBuilder { + BanBuilder::new() + } +} + +impl Ban { + /// Create a new builder for this type + pub fn builder() -> BanBuilder { + BanBuilder::builder() + } +} + +impl BanBuilder { + /// Create a new builder with all fields unset, using the default string type, if needed + pub fn new() -> Self { + BanBuilder { + _state: PhantomData, + _fields: (None,), + _type: PhantomData, + } + } +} + +impl BanBuilder { + /// Create a new builder with all fields unset + pub fn builder() -> Self { + BanBuilder { + _state: PhantomData, + _fields: (None,), + _type: PhantomData, + } + } +} + +impl BanBuilder +where + St: ban_state::State, + St::Subject: ban_state::IsUnset, +{ + /// Set the `subject` field (required) + pub fn subject(mut self, value: impl Into>) -> BanBuilder, S> { + self._fields.0 = Option::Some(value.into()); + BanBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl BanBuilder +where + St: ban_state::State, + St::Subject: ban_state::IsSet, +{ + /// Build the final struct. + pub fn build(self) -> Ban { + Ban { + subject: self._fields.0.unwrap(), + extra_data: Default::default(), + } + } + /// Build the final struct with custom extra_data. + pub fn build_with_data(self, extra_data: BTreeMap>) -> Ban { + Ban { + subject: self._fields.0.unwrap(), + extra_data: Some(extra_data), + } + } +} diff --git a/crates/jacquard-api/src/sh_tangled/knot/count_knots.rs b/crates/jacquard-api/src/sh_tangled/knot/count_knots.rs new file mode 100644 index 000000000..f736d0955 --- /dev/null +++ b/crates/jacquard-api/src/sh_tangled/knot/count_knots.rs @@ -0,0 +1,176 @@ +// @generated by jacquard-lexicon. DO NOT EDIT. +// +// Lexicon: sh.tangled.knot.countKnots +// +// 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::deps::smol_str::SmolStr; +use jacquard_common::types::string::Did; +use jacquard_common::types::value::Data; +use jacquard_common::{BosStr, DefaultStr, FromStaticStr}; +use jacquard_derive::IntoStatic; +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct CountKnots { + pub subject: Did, +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct CountKnotsOutput { + ///Total number of matching records. + pub count: i64, + ///Number of distinct authors among the matching records. + pub distinct_authors: i64, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +/** Response marker for the `sh.tangled.knot.countKnots` query. + +Implements `jacquard_common::xrpc::XrpcResp`; successful bodies decode as `Self::Output`, which is `CountKnotsOutput` for this endpoint.*/ +pub struct CountKnotsResponse; +impl jacquard_common::xrpc::XrpcResp for CountKnotsResponse { + const NSID: &'static str = "sh.tangled.knot.countKnots"; + const ENCODING: &'static str = "application/json"; + type Output = CountKnotsOutput; + type Err = jacquard_common::xrpc::GenericError; +} + +impl jacquard_common::xrpc::XrpcRequest for CountKnots { + const NSID: &'static str = "sh.tangled.knot.countKnots"; + const METHOD: jacquard_common::xrpc::XrpcMethod = jacquard_common::xrpc::XrpcMethod::Query; + type Response = CountKnotsResponse; +} + +/** Endpoint marker for the `sh.tangled.knot.countKnots` query. + +Path: `/xrpc/sh.tangled.knot.countKnots`. The request payload type is `CountKnots`; send that request with `jacquard::Client` or use this marker through lower-level `XrpcEndpoint` APIs.*/ +pub struct CountKnotsRequest; +impl jacquard_common::xrpc::XrpcEndpoint for CountKnotsRequest { + const PATH: &'static str = "/xrpc/sh.tangled.knot.countKnots"; + const METHOD: jacquard_common::xrpc::XrpcMethod = jacquard_common::xrpc::XrpcMethod::Query; + type Request = CountKnots; + type Response = CountKnotsResponse; +} + +pub mod count_knots_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 Subject; + } + /// Empty state - all required fields are unset + pub struct Empty(()); + impl sealed::Sealed for Empty {} + impl State for Empty { + type Subject = Unset; + } + ///State transition - sets the `subject` field to Set + pub struct SetSubject(PhantomData St>); + impl sealed::Sealed for SetSubject {} + impl State for SetSubject { + type Subject = Set; + } + /// Marker types for field names + #[allow(non_camel_case_types)] + pub mod members { + ///Marker type for the `subject` field + pub struct subject(()); + } +} + +/// Builder for constructing an instance of this type. +pub struct CountKnotsBuilder { + _state: PhantomData St>, + _fields: (Option>,), + _type: PhantomData S>, +} + +impl CountKnots { + /// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed + pub fn new() -> CountKnotsBuilder { + CountKnotsBuilder::new() + } +} + +impl CountKnots { + /// Create a new builder for this type + pub fn builder() -> CountKnotsBuilder { + CountKnotsBuilder::builder() + } +} + +impl CountKnotsBuilder { + /// Create a new builder with all fields unset, using the default string type, if needed + pub fn new() -> Self { + CountKnotsBuilder { + _state: PhantomData, + _fields: (None,), + _type: PhantomData, + } + } +} + +impl CountKnotsBuilder { + /// Create a new builder with all fields unset + pub fn builder() -> Self { + CountKnotsBuilder { + _state: PhantomData, + _fields: (None,), + _type: PhantomData, + } + } +} + +impl CountKnotsBuilder +where + St: count_knots_state::State, + St::Subject: count_knots_state::IsUnset, +{ + /// Set the `subject` field (required) + pub fn subject( + mut self, + value: impl Into>, + ) -> CountKnotsBuilder, S> { + self._fields.0 = Option::Some(value.into()); + CountKnotsBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl CountKnotsBuilder +where + St: count_knots_state::State, + St::Subject: count_knots_state::IsSet, +{ + /// Build the final struct. + pub fn build(self) -> CountKnots { + CountKnots { + subject: self._fields.0.unwrap(), + } + } +} diff --git a/crates/jacquard-api/src/sh_tangled/knot/count_members.rs b/crates/jacquard-api/src/sh_tangled/knot/count_members.rs new file mode 100644 index 000000000..03cac74dc --- /dev/null +++ b/crates/jacquard-api/src/sh_tangled/knot/count_members.rs @@ -0,0 +1,175 @@ +// @generated by jacquard-lexicon. DO NOT EDIT. +// +// Lexicon: sh.tangled.knot.countMembers +// +// 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::deps::smol_str::SmolStr; +use jacquard_common::types::value::Data; +use jacquard_common::{BosStr, CowStr, DefaultStr, FromStaticStr}; +use jacquard_derive::IntoStatic; +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct CountMembers { + pub subject: S, +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct CountMembersOutput { + ///Total number of matching records. + pub count: i64, + ///Number of distinct authors among the matching records. + pub distinct_authors: i64, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +/** Response marker for the `sh.tangled.knot.countMembers` query. + +Implements `jacquard_common::xrpc::XrpcResp`; successful bodies decode as `Self::Output`, which is `CountMembersOutput` for this endpoint.*/ +pub struct CountMembersResponse; +impl jacquard_common::xrpc::XrpcResp for CountMembersResponse { + const NSID: &'static str = "sh.tangled.knot.countMembers"; + const ENCODING: &'static str = "application/json"; + type Output = CountMembersOutput; + type Err = jacquard_common::xrpc::GenericError; +} + +impl jacquard_common::xrpc::XrpcRequest for CountMembers { + const NSID: &'static str = "sh.tangled.knot.countMembers"; + const METHOD: jacquard_common::xrpc::XrpcMethod = jacquard_common::xrpc::XrpcMethod::Query; + type Response = CountMembersResponse; +} + +/** Endpoint marker for the `sh.tangled.knot.countMembers` query. + +Path: `/xrpc/sh.tangled.knot.countMembers`. The request payload type is `CountMembers`; send that request with `jacquard::Client` or use this marker through lower-level `XrpcEndpoint` APIs.*/ +pub struct CountMembersRequest; +impl jacquard_common::xrpc::XrpcEndpoint for CountMembersRequest { + const PATH: &'static str = "/xrpc/sh.tangled.knot.countMembers"; + const METHOD: jacquard_common::xrpc::XrpcMethod = jacquard_common::xrpc::XrpcMethod::Query; + type Request = CountMembers; + type Response = CountMembersResponse; +} + +pub mod count_members_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 Subject; + } + /// Empty state - all required fields are unset + pub struct Empty(()); + impl sealed::Sealed for Empty {} + impl State for Empty { + type Subject = Unset; + } + ///State transition - sets the `subject` field to Set + pub struct SetSubject(PhantomData St>); + impl sealed::Sealed for SetSubject {} + impl State for SetSubject { + type Subject = Set; + } + /// Marker types for field names + #[allow(non_camel_case_types)] + pub mod members { + ///Marker type for the `subject` field + pub struct subject(()); + } +} + +/// Builder for constructing an instance of this type. +pub struct CountMembersBuilder { + _state: PhantomData St>, + _fields: (Option,), + _type: PhantomData S>, +} + +impl CountMembers { + /// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed + pub fn new() -> CountMembersBuilder { + CountMembersBuilder::new() + } +} + +impl CountMembers { + /// Create a new builder for this type + pub fn builder() -> CountMembersBuilder { + CountMembersBuilder::builder() + } +} + +impl CountMembersBuilder { + /// Create a new builder with all fields unset, using the default string type, if needed + pub fn new() -> Self { + CountMembersBuilder { + _state: PhantomData, + _fields: (None,), + _type: PhantomData, + } + } +} + +impl CountMembersBuilder { + /// Create a new builder with all fields unset + pub fn builder() -> Self { + CountMembersBuilder { + _state: PhantomData, + _fields: (None,), + _type: PhantomData, + } + } +} + +impl CountMembersBuilder +where + St: count_members_state::State, + St::Subject: count_members_state::IsUnset, +{ + /// Set the `subject` field (required) + pub fn subject( + mut self, + value: impl Into, + ) -> CountMembersBuilder, S> { + self._fields.0 = Option::Some(value.into()); + CountMembersBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl CountMembersBuilder +where + St: count_members_state::State, + St::Subject: count_members_state::IsSet, +{ + /// Build the final struct. + pub fn build(self) -> CountMembers { + CountMembers { + subject: self._fields.0.unwrap(), + } + } +} diff --git a/crates/jacquard-api/src/sh_tangled/knot/count_members_by.rs b/crates/jacquard-api/src/sh_tangled/knot/count_members_by.rs new file mode 100644 index 000000000..a9a1649e1 --- /dev/null +++ b/crates/jacquard-api/src/sh_tangled/knot/count_members_by.rs @@ -0,0 +1,176 @@ +// @generated by jacquard-lexicon. DO NOT EDIT. +// +// Lexicon: sh.tangled.knot.countMembersBy +// +// 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::deps::smol_str::SmolStr; +use jacquard_common::types::string::Did; +use jacquard_common::types::value::Data; +use jacquard_common::{BosStr, DefaultStr, FromStaticStr}; +use jacquard_derive::IntoStatic; +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct CountMembersBy { + pub subject: Did, +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct CountMembersByOutput { + ///Total number of matching records. + pub count: i64, + ///Number of distinct authors among the matching records. + pub distinct_authors: i64, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +/** Response marker for the `sh.tangled.knot.countMembersBy` query. + +Implements `jacquard_common::xrpc::XrpcResp`; successful bodies decode as `Self::Output`, which is `CountMembersByOutput` for this endpoint.*/ +pub struct CountMembersByResponse; +impl jacquard_common::xrpc::XrpcResp for CountMembersByResponse { + const NSID: &'static str = "sh.tangled.knot.countMembersBy"; + const ENCODING: &'static str = "application/json"; + type Output = CountMembersByOutput; + type Err = jacquard_common::xrpc::GenericError; +} + +impl jacquard_common::xrpc::XrpcRequest for CountMembersBy { + const NSID: &'static str = "sh.tangled.knot.countMembersBy"; + const METHOD: jacquard_common::xrpc::XrpcMethod = jacquard_common::xrpc::XrpcMethod::Query; + type Response = CountMembersByResponse; +} + +/** Endpoint marker for the `sh.tangled.knot.countMembersBy` query. + +Path: `/xrpc/sh.tangled.knot.countMembersBy`. The request payload type is `CountMembersBy`; send that request with `jacquard::Client` or use this marker through lower-level `XrpcEndpoint` APIs.*/ +pub struct CountMembersByRequest; +impl jacquard_common::xrpc::XrpcEndpoint for CountMembersByRequest { + const PATH: &'static str = "/xrpc/sh.tangled.knot.countMembersBy"; + const METHOD: jacquard_common::xrpc::XrpcMethod = jacquard_common::xrpc::XrpcMethod::Query; + type Request = CountMembersBy; + type Response = CountMembersByResponse; +} + +pub mod count_members_by_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 Subject; + } + /// Empty state - all required fields are unset + pub struct Empty(()); + impl sealed::Sealed for Empty {} + impl State for Empty { + type Subject = Unset; + } + ///State transition - sets the `subject` field to Set + pub struct SetSubject(PhantomData St>); + impl sealed::Sealed for SetSubject {} + impl State for SetSubject { + type Subject = Set; + } + /// Marker types for field names + #[allow(non_camel_case_types)] + pub mod members { + ///Marker type for the `subject` field + pub struct subject(()); + } +} + +/// Builder for constructing an instance of this type. +pub struct CountMembersByBuilder { + _state: PhantomData St>, + _fields: (Option>,), + _type: PhantomData S>, +} + +impl CountMembersBy { + /// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed + pub fn new() -> CountMembersByBuilder { + CountMembersByBuilder::new() + } +} + +impl CountMembersBy { + /// Create a new builder for this type + pub fn builder() -> CountMembersByBuilder { + CountMembersByBuilder::builder() + } +} + +impl CountMembersByBuilder { + /// Create a new builder with all fields unset, using the default string type, if needed + pub fn new() -> Self { + CountMembersByBuilder { + _state: PhantomData, + _fields: (None,), + _type: PhantomData, + } + } +} + +impl CountMembersByBuilder { + /// Create a new builder with all fields unset + pub fn builder() -> Self { + CountMembersByBuilder { + _state: PhantomData, + _fields: (None,), + _type: PhantomData, + } + } +} + +impl CountMembersByBuilder +where + St: count_members_by_state::State, + St::Subject: count_members_by_state::IsUnset, +{ + /// Set the `subject` field (required) + pub fn subject( + mut self, + value: impl Into>, + ) -> CountMembersByBuilder, S> { + self._fields.0 = Option::Some(value.into()); + CountMembersByBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl CountMembersByBuilder +where + St: count_members_by_state::State, + St::Subject: count_members_by_state::IsSet, +{ + /// Build the final struct. + pub fn build(self) -> CountMembersBy { + CountMembersBy { + subject: self._fields.0.unwrap(), + } + } +} diff --git a/crates/jacquard-api/src/sh_tangled/knot/unban.rs b/crates/jacquard-api/src/sh_tangled/knot/unban.rs new file mode 100644 index 000000000..d1b11d915 --- /dev/null +++ b/crates/jacquard-api/src/sh_tangled/knot/unban.rs @@ -0,0 +1,175 @@ +// @generated by jacquard-lexicon. DO NOT EDIT. +// +// Lexicon: sh.tangled.knot.unban +// +// 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::deps::smol_str::SmolStr; +use jacquard_common::types::string::Did; +use jacquard_common::types::value::Data; +use jacquard_common::{BosStr, DefaultStr, FromStaticStr}; +use jacquard_derive::IntoStatic; +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct Unban { + ///DID of the account to unblock + pub subject: Did, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +/** Response marker for the `sh.tangled.knot.unban` procedure. + +Implements `jacquard_common::xrpc::XrpcResp`; successful bodies decode as `Self::Output`, which is `()` for this endpoint.*/ +pub struct UnbanResponse; +impl jacquard_common::xrpc::XrpcResp for UnbanResponse { + const NSID: &'static str = "sh.tangled.knot.unban"; + const ENCODING: &'static str = "application/json"; + type Output = (); + type Err = jacquard_common::xrpc::GenericError; +} + +impl jacquard_common::xrpc::XrpcRequest for Unban { + const NSID: &'static str = "sh.tangled.knot.unban"; + const METHOD: jacquard_common::xrpc::XrpcMethod = + jacquard_common::xrpc::XrpcMethod::Procedure("application/json"); + type Response = UnbanResponse; +} + +/** Endpoint marker for the `sh.tangled.knot.unban` procedure. + +Path: `/xrpc/sh.tangled.knot.unban`. The request payload type is `Unban`; send that request with `jacquard::Client` or use this marker through lower-level `XrpcEndpoint` APIs.*/ +pub struct UnbanRequest; +impl jacquard_common::xrpc::XrpcEndpoint for UnbanRequest { + const PATH: &'static str = "/xrpc/sh.tangled.knot.unban"; + const METHOD: jacquard_common::xrpc::XrpcMethod = + jacquard_common::xrpc::XrpcMethod::Procedure("application/json"); + type Request = Unban; + type Response = UnbanResponse; +} + +pub mod unban_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 Subject; + } + /// Empty state - all required fields are unset + pub struct Empty(()); + impl sealed::Sealed for Empty {} + impl State for Empty { + type Subject = Unset; + } + ///State transition - sets the `subject` field to Set + pub struct SetSubject(PhantomData St>); + impl sealed::Sealed for SetSubject {} + impl State for SetSubject { + type Subject = Set; + } + /// Marker types for field names + #[allow(non_camel_case_types)] + pub mod members { + ///Marker type for the `subject` field + pub struct subject(()); + } +} + +/// Builder for constructing an instance of this type. +pub struct UnbanBuilder { + _state: PhantomData St>, + _fields: (Option>,), + _type: PhantomData S>, +} + +impl Unban { + /// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed + pub fn new() -> UnbanBuilder { + UnbanBuilder::new() + } +} + +impl Unban { + /// Create a new builder for this type + pub fn builder() -> UnbanBuilder { + UnbanBuilder::builder() + } +} + +impl UnbanBuilder { + /// Create a new builder with all fields unset, using the default string type, if needed + pub fn new() -> Self { + UnbanBuilder { + _state: PhantomData, + _fields: (None,), + _type: PhantomData, + } + } +} + +impl UnbanBuilder { + /// Create a new builder with all fields unset + pub fn builder() -> Self { + UnbanBuilder { + _state: PhantomData, + _fields: (None,), + _type: PhantomData, + } + } +} + +impl UnbanBuilder +where + St: unban_state::State, + St::Subject: unban_state::IsUnset, +{ + /// Set the `subject` field (required) + pub fn subject( + mut self, + value: impl Into>, + ) -> UnbanBuilder, S> { + self._fields.0 = Option::Some(value.into()); + UnbanBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl UnbanBuilder +where + St: unban_state::State, + St::Subject: unban_state::IsSet, +{ + /// Build the final struct. + pub fn build(self) -> Unban { + Unban { + subject: self._fields.0.unwrap(), + extra_data: Default::default(), + } + } + /// Build the final struct with custom extra_data. + pub fn build_with_data(self, extra_data: BTreeMap>) -> Unban { + Unban { + subject: self._fields.0.unwrap(), + extra_data: Some(extra_data), + } + } +} diff --git a/crates/jacquard-api/src/sh_tangled/label.rs b/crates/jacquard-api/src/sh_tangled/label.rs index 1358b866d..22eca317c 100644 --- a/crates/jacquard-api/src/sh_tangled/label.rs +++ b/crates/jacquard-api/src/sh_tangled/label.rs @@ -4,6 +4,9 @@ // Any manual changes will be overwritten on the next regeneration. //! Generated bindings for the `sh.tangled.label` Lexicon namespace/module. +pub mod count_definitions; +pub mod count_ops; +pub mod count_ops_by; pub mod definition; pub mod list_definitions; pub mod list_ops; diff --git a/crates/jacquard-api/src/sh_tangled/label/count_definitions.rs b/crates/jacquard-api/src/sh_tangled/label/count_definitions.rs new file mode 100644 index 000000000..873c857f9 --- /dev/null +++ b/crates/jacquard-api/src/sh_tangled/label/count_definitions.rs @@ -0,0 +1,175 @@ +// @generated by jacquard-lexicon. DO NOT EDIT. +// +// Lexicon: sh.tangled.label.countDefinitions +// +// 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::deps::smol_str::SmolStr; +use jacquard_common::types::value::Data; +use jacquard_common::{BosStr, CowStr, DefaultStr, FromStaticStr}; +use jacquard_derive::IntoStatic; +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct CountDefinitions { + pub subject: S, +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct CountDefinitionsOutput { + ///Total number of matching records. + pub count: i64, + ///Number of distinct authors among the matching records. + pub distinct_authors: i64, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +/** Response marker for the `sh.tangled.label.countDefinitions` query. + +Implements `jacquard_common::xrpc::XrpcResp`; successful bodies decode as `Self::Output`, which is `CountDefinitionsOutput` for this endpoint.*/ +pub struct CountDefinitionsResponse; +impl jacquard_common::xrpc::XrpcResp for CountDefinitionsResponse { + const NSID: &'static str = "sh.tangled.label.countDefinitions"; + const ENCODING: &'static str = "application/json"; + type Output = CountDefinitionsOutput; + type Err = jacquard_common::xrpc::GenericError; +} + +impl jacquard_common::xrpc::XrpcRequest for CountDefinitions { + const NSID: &'static str = "sh.tangled.label.countDefinitions"; + const METHOD: jacquard_common::xrpc::XrpcMethod = jacquard_common::xrpc::XrpcMethod::Query; + type Response = CountDefinitionsResponse; +} + +/** Endpoint marker for the `sh.tangled.label.countDefinitions` query. + +Path: `/xrpc/sh.tangled.label.countDefinitions`. The request payload type is `CountDefinitions`; send that request with `jacquard::Client` or use this marker through lower-level `XrpcEndpoint` APIs.*/ +pub struct CountDefinitionsRequest; +impl jacquard_common::xrpc::XrpcEndpoint for CountDefinitionsRequest { + const PATH: &'static str = "/xrpc/sh.tangled.label.countDefinitions"; + const METHOD: jacquard_common::xrpc::XrpcMethod = jacquard_common::xrpc::XrpcMethod::Query; + type Request = CountDefinitions; + type Response = CountDefinitionsResponse; +} + +pub mod count_definitions_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 Subject; + } + /// Empty state - all required fields are unset + pub struct Empty(()); + impl sealed::Sealed for Empty {} + impl State for Empty { + type Subject = Unset; + } + ///State transition - sets the `subject` field to Set + pub struct SetSubject(PhantomData St>); + impl sealed::Sealed for SetSubject {} + impl State for SetSubject { + type Subject = Set; + } + /// Marker types for field names + #[allow(non_camel_case_types)] + pub mod members { + ///Marker type for the `subject` field + pub struct subject(()); + } +} + +/// Builder for constructing an instance of this type. +pub struct CountDefinitionsBuilder { + _state: PhantomData St>, + _fields: (Option,), + _type: PhantomData S>, +} + +impl CountDefinitions { + /// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed + pub fn new() -> CountDefinitionsBuilder { + CountDefinitionsBuilder::new() + } +} + +impl CountDefinitions { + /// Create a new builder for this type + pub fn builder() -> CountDefinitionsBuilder { + CountDefinitionsBuilder::builder() + } +} + +impl CountDefinitionsBuilder { + /// Create a new builder with all fields unset, using the default string type, if needed + pub fn new() -> Self { + CountDefinitionsBuilder { + _state: PhantomData, + _fields: (None,), + _type: PhantomData, + } + } +} + +impl CountDefinitionsBuilder { + /// Create a new builder with all fields unset + pub fn builder() -> Self { + CountDefinitionsBuilder { + _state: PhantomData, + _fields: (None,), + _type: PhantomData, + } + } +} + +impl CountDefinitionsBuilder +where + St: count_definitions_state::State, + St::Subject: count_definitions_state::IsUnset, +{ + /// Set the `subject` field (required) + pub fn subject( + mut self, + value: impl Into, + ) -> CountDefinitionsBuilder, S> { + self._fields.0 = Option::Some(value.into()); + CountDefinitionsBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl CountDefinitionsBuilder +where + St: count_definitions_state::State, + St::Subject: count_definitions_state::IsSet, +{ + /// Build the final struct. + pub fn build(self) -> CountDefinitions { + CountDefinitions { + subject: self._fields.0.unwrap(), + } + } +} diff --git a/crates/jacquard-api/src/sh_tangled/label/count_ops.rs b/crates/jacquard-api/src/sh_tangled/label/count_ops.rs new file mode 100644 index 000000000..ac9a3ff62 --- /dev/null +++ b/crates/jacquard-api/src/sh_tangled/label/count_ops.rs @@ -0,0 +1,175 @@ +// @generated by jacquard-lexicon. DO NOT EDIT. +// +// Lexicon: sh.tangled.label.countOps +// +// 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::deps::smol_str::SmolStr; +use jacquard_common::types::value::Data; +use jacquard_common::{BosStr, CowStr, DefaultStr, FromStaticStr}; +use jacquard_derive::IntoStatic; +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct CountOps { + pub subject: S, +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct CountOpsOutput { + ///Total number of matching records. + pub count: i64, + ///Number of distinct authors among the matching records. + pub distinct_authors: i64, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +/** Response marker for the `sh.tangled.label.countOps` query. + +Implements `jacquard_common::xrpc::XrpcResp`; successful bodies decode as `Self::Output`, which is `CountOpsOutput` for this endpoint.*/ +pub struct CountOpsResponse; +impl jacquard_common::xrpc::XrpcResp for CountOpsResponse { + const NSID: &'static str = "sh.tangled.label.countOps"; + const ENCODING: &'static str = "application/json"; + type Output = CountOpsOutput; + type Err = jacquard_common::xrpc::GenericError; +} + +impl jacquard_common::xrpc::XrpcRequest for CountOps { + const NSID: &'static str = "sh.tangled.label.countOps"; + const METHOD: jacquard_common::xrpc::XrpcMethod = jacquard_common::xrpc::XrpcMethod::Query; + type Response = CountOpsResponse; +} + +/** Endpoint marker for the `sh.tangled.label.countOps` query. + +Path: `/xrpc/sh.tangled.label.countOps`. The request payload type is `CountOps`; send that request with `jacquard::Client` or use this marker through lower-level `XrpcEndpoint` APIs.*/ +pub struct CountOpsRequest; +impl jacquard_common::xrpc::XrpcEndpoint for CountOpsRequest { + const PATH: &'static str = "/xrpc/sh.tangled.label.countOps"; + const METHOD: jacquard_common::xrpc::XrpcMethod = jacquard_common::xrpc::XrpcMethod::Query; + type Request = CountOps; + type Response = CountOpsResponse; +} + +pub mod count_ops_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 Subject; + } + /// Empty state - all required fields are unset + pub struct Empty(()); + impl sealed::Sealed for Empty {} + impl State for Empty { + type Subject = Unset; + } + ///State transition - sets the `subject` field to Set + pub struct SetSubject(PhantomData St>); + impl sealed::Sealed for SetSubject {} + impl State for SetSubject { + type Subject = Set; + } + /// Marker types for field names + #[allow(non_camel_case_types)] + pub mod members { + ///Marker type for the `subject` field + pub struct subject(()); + } +} + +/// Builder for constructing an instance of this type. +pub struct CountOpsBuilder { + _state: PhantomData St>, + _fields: (Option,), + _type: PhantomData S>, +} + +impl CountOps { + /// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed + pub fn new() -> CountOpsBuilder { + CountOpsBuilder::new() + } +} + +impl CountOps { + /// Create a new builder for this type + pub fn builder() -> CountOpsBuilder { + CountOpsBuilder::builder() + } +} + +impl CountOpsBuilder { + /// Create a new builder with all fields unset, using the default string type, if needed + pub fn new() -> Self { + CountOpsBuilder { + _state: PhantomData, + _fields: (None,), + _type: PhantomData, + } + } +} + +impl CountOpsBuilder { + /// Create a new builder with all fields unset + pub fn builder() -> Self { + CountOpsBuilder { + _state: PhantomData, + _fields: (None,), + _type: PhantomData, + } + } +} + +impl CountOpsBuilder +where + St: count_ops_state::State, + St::Subject: count_ops_state::IsUnset, +{ + /// Set the `subject` field (required) + pub fn subject( + mut self, + value: impl Into, + ) -> CountOpsBuilder, S> { + self._fields.0 = Option::Some(value.into()); + CountOpsBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl CountOpsBuilder +where + St: count_ops_state::State, + St::Subject: count_ops_state::IsSet, +{ + /// Build the final struct. + pub fn build(self) -> CountOps { + CountOps { + subject: self._fields.0.unwrap(), + } + } +} diff --git a/crates/jacquard-api/src/sh_tangled/label/count_ops_by.rs b/crates/jacquard-api/src/sh_tangled/label/count_ops_by.rs new file mode 100644 index 000000000..2ce991025 --- /dev/null +++ b/crates/jacquard-api/src/sh_tangled/label/count_ops_by.rs @@ -0,0 +1,176 @@ +// @generated by jacquard-lexicon. DO NOT EDIT. +// +// Lexicon: sh.tangled.label.countOpsBy +// +// 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::deps::smol_str::SmolStr; +use jacquard_common::types::string::Did; +use jacquard_common::types::value::Data; +use jacquard_common::{BosStr, DefaultStr, FromStaticStr}; +use jacquard_derive::IntoStatic; +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct CountOpsBy { + pub subject: Did, +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct CountOpsByOutput { + ///Total number of matching records. + pub count: i64, + ///Number of distinct authors among the matching records. + pub distinct_authors: i64, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +/** Response marker for the `sh.tangled.label.countOpsBy` query. + +Implements `jacquard_common::xrpc::XrpcResp`; successful bodies decode as `Self::Output`, which is `CountOpsByOutput` for this endpoint.*/ +pub struct CountOpsByResponse; +impl jacquard_common::xrpc::XrpcResp for CountOpsByResponse { + const NSID: &'static str = "sh.tangled.label.countOpsBy"; + const ENCODING: &'static str = "application/json"; + type Output = CountOpsByOutput; + type Err = jacquard_common::xrpc::GenericError; +} + +impl jacquard_common::xrpc::XrpcRequest for CountOpsBy { + const NSID: &'static str = "sh.tangled.label.countOpsBy"; + const METHOD: jacquard_common::xrpc::XrpcMethod = jacquard_common::xrpc::XrpcMethod::Query; + type Response = CountOpsByResponse; +} + +/** Endpoint marker for the `sh.tangled.label.countOpsBy` query. + +Path: `/xrpc/sh.tangled.label.countOpsBy`. The request payload type is `CountOpsBy`; send that request with `jacquard::Client` or use this marker through lower-level `XrpcEndpoint` APIs.*/ +pub struct CountOpsByRequest; +impl jacquard_common::xrpc::XrpcEndpoint for CountOpsByRequest { + const PATH: &'static str = "/xrpc/sh.tangled.label.countOpsBy"; + const METHOD: jacquard_common::xrpc::XrpcMethod = jacquard_common::xrpc::XrpcMethod::Query; + type Request = CountOpsBy; + type Response = CountOpsByResponse; +} + +pub mod count_ops_by_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 Subject; + } + /// Empty state - all required fields are unset + pub struct Empty(()); + impl sealed::Sealed for Empty {} + impl State for Empty { + type Subject = Unset; + } + ///State transition - sets the `subject` field to Set + pub struct SetSubject(PhantomData St>); + impl sealed::Sealed for SetSubject {} + impl State for SetSubject { + type Subject = Set; + } + /// Marker types for field names + #[allow(non_camel_case_types)] + pub mod members { + ///Marker type for the `subject` field + pub struct subject(()); + } +} + +/// Builder for constructing an instance of this type. +pub struct CountOpsByBuilder { + _state: PhantomData St>, + _fields: (Option>,), + _type: PhantomData S>, +} + +impl CountOpsBy { + /// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed + pub fn new() -> CountOpsByBuilder { + CountOpsByBuilder::new() + } +} + +impl CountOpsBy { + /// Create a new builder for this type + pub fn builder() -> CountOpsByBuilder { + CountOpsByBuilder::builder() + } +} + +impl CountOpsByBuilder { + /// Create a new builder with all fields unset, using the default string type, if needed + pub fn new() -> Self { + CountOpsByBuilder { + _state: PhantomData, + _fields: (None,), + _type: PhantomData, + } + } +} + +impl CountOpsByBuilder { + /// Create a new builder with all fields unset + pub fn builder() -> Self { + CountOpsByBuilder { + _state: PhantomData, + _fields: (None,), + _type: PhantomData, + } + } +} + +impl CountOpsByBuilder +where + St: count_ops_by_state::State, + St::Subject: count_ops_by_state::IsUnset, +{ + /// Set the `subject` field (required) + pub fn subject( + mut self, + value: impl Into>, + ) -> CountOpsByBuilder, S> { + self._fields.0 = Option::Some(value.into()); + CountOpsByBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl CountOpsByBuilder +where + St: count_ops_by_state::State, + St::Subject: count_ops_by_state::IsSet, +{ + /// Build the final struct. + pub fn build(self) -> CountOpsBy { + CountOpsBy { + subject: self._fields.0.unwrap(), + } + } +} diff --git a/crates/jacquard-api/src/sh_tangled/pipeline.rs b/crates/jacquard-api/src/sh_tangled/pipeline.rs index 3536216d9..27741e1f5 100644 --- a/crates/jacquard-api/src/sh_tangled/pipeline.rs +++ b/crates/jacquard-api/src/sh_tangled/pipeline.rs @@ -7,6 +7,10 @@ //! Generated bindings for the `sh.tangled.pipeline` Lexicon namespace/module. pub mod cancel_pipeline; +pub mod count_pipelines; +pub mod count_pipelines_by; +pub mod count_statuses; +pub mod count_statuses_by; pub mod list_pipelines; pub mod list_pipelines_by; pub mod list_statuses; @@ -84,6 +88,11 @@ pub struct PipelineGetRecordOutput { pub struct ManualTriggerData { #[serde(skip_serializing_if = "Option::is_none")] pub inputs: Option>>, + ///optional ref the SHA was resolved from, for display and TANGLED_REF + #[serde(skip_serializing_if = "Option::is_none")] + pub r#ref: Option, + ///commit SHA the manual run targets + pub sha: S, #[serde(flatten, default, skip_serializing_if = "Option::is_none")] pub extra_data: Option>>, } @@ -106,7 +115,12 @@ pub struct Pair { bound(deserialize = "S: Deserialize<'de> + BosStr") )] pub struct PullRequestTriggerData { - pub action: S, + ///the pull request lifecycle action that produced this trigger + #[serde(skip_serializing_if = "Option::is_none")] + pub action: Option, + ///AT-URI of the sh.tangled.repo.pull record this run belongs to + #[serde(skip_serializing_if = "Option::is_none")] + pub pull: Option>, pub source_branch: S, pub source_sha: S, pub target_branch: S, @@ -141,6 +155,9 @@ pub struct TriggerMetadata { #[serde(skip_serializing_if = "Option::is_none")] pub push: Option>, pub repo: pipeline::TriggerRepo, + ///Repository DID that code and workflow definitions are checked out from, when different from repo (e.g. a fork's commit for a fork-based manual trigger). If absent, source uses repo itself. + #[serde(skip_serializing_if = "Option::is_none")] + pub source_repo: Option>, #[serde(flatten, default, skip_serializing_if = "Option::is_none")] pub extra_data: Option>>, } @@ -173,6 +190,8 @@ pub struct Workflow { pub engine: S, pub name: S, pub raw: S, + #[serde(skip_serializing_if = "Option::is_none")] + pub runs_on: Option>, #[serde(flatten, default, skip_serializing_if = "Option::is_none")] pub extra_data: Option>>, } @@ -251,6 +270,28 @@ impl LexiconSchema for ManualTriggerData { lexicon_doc_sh_tangled_pipeline() } fn validate(&self) -> Result<(), ConstraintError> { + { + let value = &self.sha; + #[allow(unused_comparisons)] + if ::len(value.as_ref()) > 40usize { + return Err(ConstraintError::MaxLength { + path: ValidationPath::from_field("sha"), + max: 40usize, + actual: ::len(value.as_ref()), + }); + } + } + { + let value = &self.sha; + #[allow(unused_comparisons)] + if ::len(value.as_ref()) < 40usize { + return Err(ConstraintError::MinLength { + path: ValidationPath::from_field("sha"), + min: 40usize, + actual: ::len(value.as_ref()), + }); + } + } Ok(()) } } @@ -690,6 +731,9 @@ fn lexicon_doc_sh_tangled_pipeline() -> LexiconDoc<'static> { LexUserType::Record(LexRecord { key: Some(CowStr::new_static("tid")), record: LexRecordRecord::Object(LexObject { + description: Some(CowStr::new_static( + "DEPRECATED: use sh.tangled.ci.pipeline instead", + )), required: Some(vec![ SmolStr::new_static("triggerMetadata"), SmolStr::new_static("workflows"), @@ -724,6 +768,7 @@ fn lexicon_doc_sh_tangled_pipeline() -> LexiconDoc<'static> { map.insert( SmolStr::new_static("manualTriggerData"), LexUserType::Object(LexObject { + required: Some(vec![SmolStr::new_static("sha")]), properties: { #[allow(unused_mut)] let mut map = BTreeMap::new(); @@ -737,6 +782,28 @@ fn lexicon_doc_sh_tangled_pipeline() -> LexiconDoc<'static> { ..Default::default() }), ); + map.insert( + SmolStr::new_static("ref"), + LexObjectProperty::String(LexString { + description: Some( + CowStr::new_static( + "optional ref the SHA was resolved from, for display and TANGLED_REF", + ), + ), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("sha"), + LexObjectProperty::String(LexString { + description: Some( + CowStr::new_static("commit SHA the manual run targets"), + ), + min_length: Some(40usize), + max_length: Some(40usize), + ..Default::default() + }), + ); map }, ..Default::default() @@ -776,7 +843,6 @@ fn lexicon_doc_sh_tangled_pipeline() -> LexiconDoc<'static> { SmolStr::new_static("sourceBranch"), SmolStr::new_static("targetBranch"), SmolStr::new_static("sourceSha"), - SmolStr::new_static("action"), ]), properties: { #[allow(unused_mut)] @@ -784,6 +850,19 @@ fn lexicon_doc_sh_tangled_pipeline() -> LexiconDoc<'static> { map.insert( SmolStr::new_static("action"), LexObjectProperty::String(LexString { + description: Some(CowStr::new_static( + "the pull request lifecycle action that produced this trigger", + )), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("pull"), + LexObjectProperty::String(LexString { + description: Some(CowStr::new_static( + "AT-URI of the sh.tangled.repo.pull record this run belongs to", + )), + format: Some(LexStringFormat::AtUri), ..Default::default() }), ); @@ -853,18 +932,15 @@ fn lexicon_doc_sh_tangled_pipeline() -> LexiconDoc<'static> { map.insert( SmolStr::new_static("triggerMetadata"), LexUserType::Object(LexObject { - required: Some(vec![ - SmolStr::new_static("kind"), - SmolStr::new_static("repo"), - ]), + required: Some( + vec![SmolStr::new_static("kind"), SmolStr::new_static("repo")], + ), properties: { #[allow(unused_mut)] let mut map = BTreeMap::new(); map.insert( SmolStr::new_static("kind"), - LexObjectProperty::String(LexString { - ..Default::default() - }), + LexObjectProperty::String(LexString { ..Default::default() }), ); map.insert( SmolStr::new_static("manual"), @@ -894,6 +970,18 @@ fn lexicon_doc_sh_tangled_pipeline() -> LexiconDoc<'static> { ..Default::default() }), ); + map.insert( + SmolStr::new_static("sourceRepo"), + LexObjectProperty::String(LexString { + description: Some( + CowStr::new_static( + "Repository DID that code and workflow definitions are checked out from, when different from repo (e.g. a fork's commit for a fork-based manual trigger). If absent, source uses repo itself.", + ), + ), + format: Some(LexStringFormat::Did), + ..Default::default() + }), + ); map }, ..Default::default() @@ -985,6 +1073,15 @@ fn lexicon_doc_sh_tangled_pipeline() -> LexiconDoc<'static> { ..Default::default() }), ); + map.insert( + SmolStr::new_static("runsOn"), + LexObjectProperty::Array(LexArray { + items: LexArrayItem::String(LexString { + ..Default::default() + }), + ..Default::default() + }), + ); map }, ..Default::default() @@ -1201,6 +1298,7 @@ pub struct TriggerMetadataBuilder>, Option>, Option>, + Option>, ), _type: PhantomData S>, } @@ -1224,7 +1322,7 @@ impl TriggerMetadataBuilder { pub fn new() -> Self { TriggerMetadataBuilder { _state: PhantomData, - _fields: (None, None, None, None, None), + _fields: (None, None, None, None, None, None), _type: PhantomData, } } @@ -1235,7 +1333,7 @@ impl TriggerMetadataBuilder { pub fn builder() -> Self { TriggerMetadataBuilder { _state: PhantomData, - _fields: (None, None, None, None, None), + _fields: (None, None, None, None, None, None), _type: PhantomData, } } @@ -1324,6 +1422,19 @@ where } } +impl TriggerMetadataBuilder { + /// Set the `sourceRepo` field (optional) + pub fn source_repo(mut self, value: impl Into>>) -> Self { + self._fields.5 = value.into(); + self + } + /// Set the `sourceRepo` field to an Option value (optional) + pub fn maybe_source_repo(mut self, value: Option>) -> Self { + self._fields.5 = value; + self + } +} + impl TriggerMetadataBuilder where St: trigger_metadata_state::State, @@ -1338,6 +1449,7 @@ where pull_request: self._fields.2, push: self._fields.3, repo: self._fields.4.unwrap(), + source_repo: self._fields.5, extra_data: Default::default(), } } @@ -1349,6 +1461,7 @@ where pull_request: self._fields.2, push: self._fields.3, repo: self._fields.4.unwrap(), + source_repo: self._fields.5, extra_data: Some(extra_data), } } @@ -1657,6 +1770,7 @@ pub struct WorkflowBuilder { Option, Option, Option, + Option>, ), _type: PhantomData S>, } @@ -1680,7 +1794,7 @@ impl WorkflowBuilder { pub fn new() -> Self { WorkflowBuilder { _state: PhantomData, - _fields: (None, None, None, None), + _fields: (None, None, None, None, None), _type: PhantomData, } } @@ -1691,7 +1805,7 @@ impl WorkflowBuilder { pub fn builder() -> Self { WorkflowBuilder { _state: PhantomData, - _fields: (None, None, None, None), + _fields: (None, None, None, None, None), _type: PhantomData, } } @@ -1767,6 +1881,19 @@ where } } +impl WorkflowBuilder { + /// Set the `runsOn` field (optional) + pub fn runs_on(mut self, value: impl Into>>) -> Self { + self._fields.4 = value.into(); + self + } + /// Set the `runsOn` field to an Option value (optional) + pub fn maybe_runs_on(mut self, value: Option>) -> Self { + self._fields.4 = value; + self + } +} + impl WorkflowBuilder where St: workflow_state::State, @@ -1782,6 +1909,7 @@ where engine: self._fields.1.unwrap(), name: self._fields.2.unwrap(), raw: self._fields.3.unwrap(), + runs_on: self._fields.4, extra_data: Default::default(), } } @@ -1792,6 +1920,7 @@ where engine: self._fields.1.unwrap(), name: self._fields.2.unwrap(), raw: self._fields.3.unwrap(), + runs_on: self._fields.4, extra_data: Some(extra_data), } } diff --git a/crates/jacquard-api/src/sh_tangled/pipeline/count_pipelines.rs b/crates/jacquard-api/src/sh_tangled/pipeline/count_pipelines.rs new file mode 100644 index 000000000..d9e490d91 --- /dev/null +++ b/crates/jacquard-api/src/sh_tangled/pipeline/count_pipelines.rs @@ -0,0 +1,175 @@ +// @generated by jacquard-lexicon. DO NOT EDIT. +// +// Lexicon: sh.tangled.pipeline.countPipelines +// +// 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::deps::smol_str::SmolStr; +use jacquard_common::types::value::Data; +use jacquard_common::{BosStr, CowStr, DefaultStr, FromStaticStr}; +use jacquard_derive::IntoStatic; +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct CountPipelines { + pub subject: S, +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct CountPipelinesOutput { + ///Total number of matching records. + pub count: i64, + ///Number of distinct authors among the matching records. + pub distinct_authors: i64, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +/** Response marker for the `sh.tangled.pipeline.countPipelines` query. + +Implements `jacquard_common::xrpc::XrpcResp`; successful bodies decode as `Self::Output`, which is `CountPipelinesOutput` for this endpoint.*/ +pub struct CountPipelinesResponse; +impl jacquard_common::xrpc::XrpcResp for CountPipelinesResponse { + const NSID: &'static str = "sh.tangled.pipeline.countPipelines"; + const ENCODING: &'static str = "application/json"; + type Output = CountPipelinesOutput; + type Err = jacquard_common::xrpc::GenericError; +} + +impl jacquard_common::xrpc::XrpcRequest for CountPipelines { + const NSID: &'static str = "sh.tangled.pipeline.countPipelines"; + const METHOD: jacquard_common::xrpc::XrpcMethod = jacquard_common::xrpc::XrpcMethod::Query; + type Response = CountPipelinesResponse; +} + +/** Endpoint marker for the `sh.tangled.pipeline.countPipelines` query. + +Path: `/xrpc/sh.tangled.pipeline.countPipelines`. The request payload type is `CountPipelines`; send that request with `jacquard::Client` or use this marker through lower-level `XrpcEndpoint` APIs.*/ +pub struct CountPipelinesRequest; +impl jacquard_common::xrpc::XrpcEndpoint for CountPipelinesRequest { + const PATH: &'static str = "/xrpc/sh.tangled.pipeline.countPipelines"; + const METHOD: jacquard_common::xrpc::XrpcMethod = jacquard_common::xrpc::XrpcMethod::Query; + type Request = CountPipelines; + type Response = CountPipelinesResponse; +} + +pub mod count_pipelines_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 Subject; + } + /// Empty state - all required fields are unset + pub struct Empty(()); + impl sealed::Sealed for Empty {} + impl State for Empty { + type Subject = Unset; + } + ///State transition - sets the `subject` field to Set + pub struct SetSubject(PhantomData St>); + impl sealed::Sealed for SetSubject {} + impl State for SetSubject { + type Subject = Set; + } + /// Marker types for field names + #[allow(non_camel_case_types)] + pub mod members { + ///Marker type for the `subject` field + pub struct subject(()); + } +} + +/// Builder for constructing an instance of this type. +pub struct CountPipelinesBuilder { + _state: PhantomData St>, + _fields: (Option,), + _type: PhantomData S>, +} + +impl CountPipelines { + /// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed + pub fn new() -> CountPipelinesBuilder { + CountPipelinesBuilder::new() + } +} + +impl CountPipelines { + /// Create a new builder for this type + pub fn builder() -> CountPipelinesBuilder { + CountPipelinesBuilder::builder() + } +} + +impl CountPipelinesBuilder { + /// Create a new builder with all fields unset, using the default string type, if needed + pub fn new() -> Self { + CountPipelinesBuilder { + _state: PhantomData, + _fields: (None,), + _type: PhantomData, + } + } +} + +impl CountPipelinesBuilder { + /// Create a new builder with all fields unset + pub fn builder() -> Self { + CountPipelinesBuilder { + _state: PhantomData, + _fields: (None,), + _type: PhantomData, + } + } +} + +impl CountPipelinesBuilder +where + St: count_pipelines_state::State, + St::Subject: count_pipelines_state::IsUnset, +{ + /// Set the `subject` field (required) + pub fn subject( + mut self, + value: impl Into, + ) -> CountPipelinesBuilder, S> { + self._fields.0 = Option::Some(value.into()); + CountPipelinesBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl CountPipelinesBuilder +where + St: count_pipelines_state::State, + St::Subject: count_pipelines_state::IsSet, +{ + /// Build the final struct. + pub fn build(self) -> CountPipelines { + CountPipelines { + subject: self._fields.0.unwrap(), + } + } +} diff --git a/crates/jacquard-api/src/sh_tangled/pipeline/count_pipelines_by.rs b/crates/jacquard-api/src/sh_tangled/pipeline/count_pipelines_by.rs new file mode 100644 index 000000000..33ed58923 --- /dev/null +++ b/crates/jacquard-api/src/sh_tangled/pipeline/count_pipelines_by.rs @@ -0,0 +1,176 @@ +// @generated by jacquard-lexicon. DO NOT EDIT. +// +// Lexicon: sh.tangled.pipeline.countPipelinesBy +// +// 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::deps::smol_str::SmolStr; +use jacquard_common::types::string::Did; +use jacquard_common::types::value::Data; +use jacquard_common::{BosStr, DefaultStr, FromStaticStr}; +use jacquard_derive::IntoStatic; +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct CountPipelinesBy { + pub subject: Did, +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct CountPipelinesByOutput { + ///Total number of matching records. + pub count: i64, + ///Number of distinct authors among the matching records. + pub distinct_authors: i64, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +/** Response marker for the `sh.tangled.pipeline.countPipelinesBy` query. + +Implements `jacquard_common::xrpc::XrpcResp`; successful bodies decode as `Self::Output`, which is `CountPipelinesByOutput` for this endpoint.*/ +pub struct CountPipelinesByResponse; +impl jacquard_common::xrpc::XrpcResp for CountPipelinesByResponse { + const NSID: &'static str = "sh.tangled.pipeline.countPipelinesBy"; + const ENCODING: &'static str = "application/json"; + type Output = CountPipelinesByOutput; + type Err = jacquard_common::xrpc::GenericError; +} + +impl jacquard_common::xrpc::XrpcRequest for CountPipelinesBy { + const NSID: &'static str = "sh.tangled.pipeline.countPipelinesBy"; + const METHOD: jacquard_common::xrpc::XrpcMethod = jacquard_common::xrpc::XrpcMethod::Query; + type Response = CountPipelinesByResponse; +} + +/** Endpoint marker for the `sh.tangled.pipeline.countPipelinesBy` query. + +Path: `/xrpc/sh.tangled.pipeline.countPipelinesBy`. The request payload type is `CountPipelinesBy`; send that request with `jacquard::Client` or use this marker through lower-level `XrpcEndpoint` APIs.*/ +pub struct CountPipelinesByRequest; +impl jacquard_common::xrpc::XrpcEndpoint for CountPipelinesByRequest { + const PATH: &'static str = "/xrpc/sh.tangled.pipeline.countPipelinesBy"; + const METHOD: jacquard_common::xrpc::XrpcMethod = jacquard_common::xrpc::XrpcMethod::Query; + type Request = CountPipelinesBy; + type Response = CountPipelinesByResponse; +} + +pub mod count_pipelines_by_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 Subject; + } + /// Empty state - all required fields are unset + pub struct Empty(()); + impl sealed::Sealed for Empty {} + impl State for Empty { + type Subject = Unset; + } + ///State transition - sets the `subject` field to Set + pub struct SetSubject(PhantomData St>); + impl sealed::Sealed for SetSubject {} + impl State for SetSubject { + type Subject = Set; + } + /// Marker types for field names + #[allow(non_camel_case_types)] + pub mod members { + ///Marker type for the `subject` field + pub struct subject(()); + } +} + +/// Builder for constructing an instance of this type. +pub struct CountPipelinesByBuilder { + _state: PhantomData St>, + _fields: (Option>,), + _type: PhantomData S>, +} + +impl CountPipelinesBy { + /// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed + pub fn new() -> CountPipelinesByBuilder { + CountPipelinesByBuilder::new() + } +} + +impl CountPipelinesBy { + /// Create a new builder for this type + pub fn builder() -> CountPipelinesByBuilder { + CountPipelinesByBuilder::builder() + } +} + +impl CountPipelinesByBuilder { + /// Create a new builder with all fields unset, using the default string type, if needed + pub fn new() -> Self { + CountPipelinesByBuilder { + _state: PhantomData, + _fields: (None,), + _type: PhantomData, + } + } +} + +impl CountPipelinesByBuilder { + /// Create a new builder with all fields unset + pub fn builder() -> Self { + CountPipelinesByBuilder { + _state: PhantomData, + _fields: (None,), + _type: PhantomData, + } + } +} + +impl CountPipelinesByBuilder +where + St: count_pipelines_by_state::State, + St::Subject: count_pipelines_by_state::IsUnset, +{ + /// Set the `subject` field (required) + pub fn subject( + mut self, + value: impl Into>, + ) -> CountPipelinesByBuilder, S> { + self._fields.0 = Option::Some(value.into()); + CountPipelinesByBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl CountPipelinesByBuilder +where + St: count_pipelines_by_state::State, + St::Subject: count_pipelines_by_state::IsSet, +{ + /// Build the final struct. + pub fn build(self) -> CountPipelinesBy { + CountPipelinesBy { + subject: self._fields.0.unwrap(), + } + } +} diff --git a/crates/jacquard-api/src/sh_tangled/pipeline/count_statuses.rs b/crates/jacquard-api/src/sh_tangled/pipeline/count_statuses.rs new file mode 100644 index 000000000..e0358a510 --- /dev/null +++ b/crates/jacquard-api/src/sh_tangled/pipeline/count_statuses.rs @@ -0,0 +1,176 @@ +// @generated by jacquard-lexicon. DO NOT EDIT. +// +// Lexicon: sh.tangled.pipeline.countStatuses +// +// 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::deps::smol_str::SmolStr; +use jacquard_common::types::string::AtUri; +use jacquard_common::types::value::Data; +use jacquard_common::{BosStr, DefaultStr, FromStaticStr}; +use jacquard_derive::IntoStatic; +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct CountStatuses { + pub subject: AtUri, +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct CountStatusesOutput { + ///Total number of matching records. + pub count: i64, + ///Number of distinct authors among the matching records. + pub distinct_authors: i64, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +/** Response marker for the `sh.tangled.pipeline.countStatuses` query. + +Implements `jacquard_common::xrpc::XrpcResp`; successful bodies decode as `Self::Output`, which is `CountStatusesOutput` for this endpoint.*/ +pub struct CountStatusesResponse; +impl jacquard_common::xrpc::XrpcResp for CountStatusesResponse { + const NSID: &'static str = "sh.tangled.pipeline.countStatuses"; + const ENCODING: &'static str = "application/json"; + type Output = CountStatusesOutput; + type Err = jacquard_common::xrpc::GenericError; +} + +impl jacquard_common::xrpc::XrpcRequest for CountStatuses { + const NSID: &'static str = "sh.tangled.pipeline.countStatuses"; + const METHOD: jacquard_common::xrpc::XrpcMethod = jacquard_common::xrpc::XrpcMethod::Query; + type Response = CountStatusesResponse; +} + +/** Endpoint marker for the `sh.tangled.pipeline.countStatuses` query. + +Path: `/xrpc/sh.tangled.pipeline.countStatuses`. The request payload type is `CountStatuses`; send that request with `jacquard::Client` or use this marker through lower-level `XrpcEndpoint` APIs.*/ +pub struct CountStatusesRequest; +impl jacquard_common::xrpc::XrpcEndpoint for CountStatusesRequest { + const PATH: &'static str = "/xrpc/sh.tangled.pipeline.countStatuses"; + const METHOD: jacquard_common::xrpc::XrpcMethod = jacquard_common::xrpc::XrpcMethod::Query; + type Request = CountStatuses; + type Response = CountStatusesResponse; +} + +pub mod count_statuses_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 Subject; + } + /// Empty state - all required fields are unset + pub struct Empty(()); + impl sealed::Sealed for Empty {} + impl State for Empty { + type Subject = Unset; + } + ///State transition - sets the `subject` field to Set + pub struct SetSubject(PhantomData St>); + impl sealed::Sealed for SetSubject {} + impl State for SetSubject { + type Subject = Set; + } + /// Marker types for field names + #[allow(non_camel_case_types)] + pub mod members { + ///Marker type for the `subject` field + pub struct subject(()); + } +} + +/// Builder for constructing an instance of this type. +pub struct CountStatusesBuilder { + _state: PhantomData St>, + _fields: (Option>,), + _type: PhantomData S>, +} + +impl CountStatuses { + /// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed + pub fn new() -> CountStatusesBuilder { + CountStatusesBuilder::new() + } +} + +impl CountStatuses { + /// Create a new builder for this type + pub fn builder() -> CountStatusesBuilder { + CountStatusesBuilder::builder() + } +} + +impl CountStatusesBuilder { + /// Create a new builder with all fields unset, using the default string type, if needed + pub fn new() -> Self { + CountStatusesBuilder { + _state: PhantomData, + _fields: (None,), + _type: PhantomData, + } + } +} + +impl CountStatusesBuilder { + /// Create a new builder with all fields unset + pub fn builder() -> Self { + CountStatusesBuilder { + _state: PhantomData, + _fields: (None,), + _type: PhantomData, + } + } +} + +impl CountStatusesBuilder +where + St: count_statuses_state::State, + St::Subject: count_statuses_state::IsUnset, +{ + /// Set the `subject` field (required) + pub fn subject( + mut self, + value: impl Into>, + ) -> CountStatusesBuilder, S> { + self._fields.0 = Option::Some(value.into()); + CountStatusesBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl CountStatusesBuilder +where + St: count_statuses_state::State, + St::Subject: count_statuses_state::IsSet, +{ + /// Build the final struct. + pub fn build(self) -> CountStatuses { + CountStatuses { + subject: self._fields.0.unwrap(), + } + } +} diff --git a/crates/jacquard-api/src/sh_tangled/pipeline/count_statuses_by.rs b/crates/jacquard-api/src/sh_tangled/pipeline/count_statuses_by.rs new file mode 100644 index 000000000..1bfba2084 --- /dev/null +++ b/crates/jacquard-api/src/sh_tangled/pipeline/count_statuses_by.rs @@ -0,0 +1,176 @@ +// @generated by jacquard-lexicon. DO NOT EDIT. +// +// Lexicon: sh.tangled.pipeline.countStatusesBy +// +// 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::deps::smol_str::SmolStr; +use jacquard_common::types::string::Did; +use jacquard_common::types::value::Data; +use jacquard_common::{BosStr, DefaultStr, FromStaticStr}; +use jacquard_derive::IntoStatic; +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct CountStatusesBy { + pub subject: Did, +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct CountStatusesByOutput { + ///Total number of matching records. + pub count: i64, + ///Number of distinct authors among the matching records. + pub distinct_authors: i64, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +/** Response marker for the `sh.tangled.pipeline.countStatusesBy` query. + +Implements `jacquard_common::xrpc::XrpcResp`; successful bodies decode as `Self::Output`, which is `CountStatusesByOutput` for this endpoint.*/ +pub struct CountStatusesByResponse; +impl jacquard_common::xrpc::XrpcResp for CountStatusesByResponse { + const NSID: &'static str = "sh.tangled.pipeline.countStatusesBy"; + const ENCODING: &'static str = "application/json"; + type Output = CountStatusesByOutput; + type Err = jacquard_common::xrpc::GenericError; +} + +impl jacquard_common::xrpc::XrpcRequest for CountStatusesBy { + const NSID: &'static str = "sh.tangled.pipeline.countStatusesBy"; + const METHOD: jacquard_common::xrpc::XrpcMethod = jacquard_common::xrpc::XrpcMethod::Query; + type Response = CountStatusesByResponse; +} + +/** Endpoint marker for the `sh.tangled.pipeline.countStatusesBy` query. + +Path: `/xrpc/sh.tangled.pipeline.countStatusesBy`. The request payload type is `CountStatusesBy`; send that request with `jacquard::Client` or use this marker through lower-level `XrpcEndpoint` APIs.*/ +pub struct CountStatusesByRequest; +impl jacquard_common::xrpc::XrpcEndpoint for CountStatusesByRequest { + const PATH: &'static str = "/xrpc/sh.tangled.pipeline.countStatusesBy"; + const METHOD: jacquard_common::xrpc::XrpcMethod = jacquard_common::xrpc::XrpcMethod::Query; + type Request = CountStatusesBy; + type Response = CountStatusesByResponse; +} + +pub mod count_statuses_by_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 Subject; + } + /// Empty state - all required fields are unset + pub struct Empty(()); + impl sealed::Sealed for Empty {} + impl State for Empty { + type Subject = Unset; + } + ///State transition - sets the `subject` field to Set + pub struct SetSubject(PhantomData St>); + impl sealed::Sealed for SetSubject {} + impl State for SetSubject { + type Subject = Set; + } + /// Marker types for field names + #[allow(non_camel_case_types)] + pub mod members { + ///Marker type for the `subject` field + pub struct subject(()); + } +} + +/// Builder for constructing an instance of this type. +pub struct CountStatusesByBuilder { + _state: PhantomData St>, + _fields: (Option>,), + _type: PhantomData S>, +} + +impl CountStatusesBy { + /// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed + pub fn new() -> CountStatusesByBuilder { + CountStatusesByBuilder::new() + } +} + +impl CountStatusesBy { + /// Create a new builder for this type + pub fn builder() -> CountStatusesByBuilder { + CountStatusesByBuilder::builder() + } +} + +impl CountStatusesByBuilder { + /// Create a new builder with all fields unset, using the default string type, if needed + pub fn new() -> Self { + CountStatusesByBuilder { + _state: PhantomData, + _fields: (None,), + _type: PhantomData, + } + } +} + +impl CountStatusesByBuilder { + /// Create a new builder with all fields unset + pub fn builder() -> Self { + CountStatusesByBuilder { + _state: PhantomData, + _fields: (None,), + _type: PhantomData, + } + } +} + +impl CountStatusesByBuilder +where + St: count_statuses_by_state::State, + St::Subject: count_statuses_by_state::IsUnset, +{ + /// Set the `subject` field (required) + pub fn subject( + mut self, + value: impl Into>, + ) -> CountStatusesByBuilder, S> { + self._fields.0 = Option::Some(value.into()); + CountStatusesByBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl CountStatusesByBuilder +where + St: count_statuses_by_state::State, + St::Subject: count_statuses_by_state::IsSet, +{ + /// Build the final struct. + pub fn build(self) -> CountStatusesBy { + CountStatusesBy { + subject: self._fields.0.unwrap(), + } + } +} diff --git a/crates/jacquard-api/src/sh_tangled/pipeline/status.rs b/crates/jacquard-api/src/sh_tangled/pipeline/status.rs index 706bb036c..47189d615 100644 --- a/crates/jacquard-api/src/sh_tangled/pipeline/status.rs +++ b/crates/jacquard-api/src/sh_tangled/pipeline/status.rs @@ -385,6 +385,9 @@ fn lexicon_doc_sh_tangled_pipeline_status() -> LexiconDoc<'static> { LexUserType::Record(LexRecord { key: Some(CowStr::new_static("tid")), record: LexRecordRecord::Object(LexObject { + description: Some(CowStr::new_static( + "DEPRECATED: use sh.tangled.ci.pipeline instead", + )), required: Some(vec![ SmolStr::new_static("pipeline"), SmolStr::new_static("workflow"), diff --git a/crates/jacquard-api/src/sh_tangled/publicKey.rs b/crates/jacquard-api/src/sh_tangled/publicKey.rs index 29c783e4b..ea83c0ed3 100644 --- a/crates/jacquard-api/src/sh_tangled/publicKey.rs +++ b/crates/jacquard-api/src/sh_tangled/publicKey.rs @@ -4,4 +4,5 @@ // Any manual changes will be overwritten on the next regeneration. //! Generated bindings for the `sh.tangled.publicKey` Lexicon namespace/module. +pub mod count_keys; pub mod list_keys; diff --git a/crates/jacquard-api/src/sh_tangled/publicKey/count_keys.rs b/crates/jacquard-api/src/sh_tangled/publicKey/count_keys.rs new file mode 100644 index 000000000..9465adf31 --- /dev/null +++ b/crates/jacquard-api/src/sh_tangled/publicKey/count_keys.rs @@ -0,0 +1,176 @@ +// @generated by jacquard-lexicon. DO NOT EDIT. +// +// Lexicon: sh.tangled.publicKey.countKeys +// +// 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::deps::smol_str::SmolStr; +use jacquard_common::types::string::Did; +use jacquard_common::types::value::Data; +use jacquard_common::{BosStr, DefaultStr, FromStaticStr}; +use jacquard_derive::IntoStatic; +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct CountKeys { + pub subject: Did, +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct CountKeysOutput { + ///Total number of matching records. + pub count: i64, + ///Number of distinct authors among the matching records. + pub distinct_authors: i64, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +/** Response marker for the `sh.tangled.publicKey.countKeys` query. + +Implements `jacquard_common::xrpc::XrpcResp`; successful bodies decode as `Self::Output`, which is `CountKeysOutput` for this endpoint.*/ +pub struct CountKeysResponse; +impl jacquard_common::xrpc::XrpcResp for CountKeysResponse { + const NSID: &'static str = "sh.tangled.publicKey.countKeys"; + const ENCODING: &'static str = "application/json"; + type Output = CountKeysOutput; + type Err = jacquard_common::xrpc::GenericError; +} + +impl jacquard_common::xrpc::XrpcRequest for CountKeys { + const NSID: &'static str = "sh.tangled.publicKey.countKeys"; + const METHOD: jacquard_common::xrpc::XrpcMethod = jacquard_common::xrpc::XrpcMethod::Query; + type Response = CountKeysResponse; +} + +/** Endpoint marker for the `sh.tangled.publicKey.countKeys` query. + +Path: `/xrpc/sh.tangled.publicKey.countKeys`. The request payload type is `CountKeys`; send that request with `jacquard::Client` or use this marker through lower-level `XrpcEndpoint` APIs.*/ +pub struct CountKeysRequest; +impl jacquard_common::xrpc::XrpcEndpoint for CountKeysRequest { + const PATH: &'static str = "/xrpc/sh.tangled.publicKey.countKeys"; + const METHOD: jacquard_common::xrpc::XrpcMethod = jacquard_common::xrpc::XrpcMethod::Query; + type Request = CountKeys; + type Response = CountKeysResponse; +} + +pub mod count_keys_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 Subject; + } + /// Empty state - all required fields are unset + pub struct Empty(()); + impl sealed::Sealed for Empty {} + impl State for Empty { + type Subject = Unset; + } + ///State transition - sets the `subject` field to Set + pub struct SetSubject(PhantomData St>); + impl sealed::Sealed for SetSubject {} + impl State for SetSubject { + type Subject = Set; + } + /// Marker types for field names + #[allow(non_camel_case_types)] + pub mod members { + ///Marker type for the `subject` field + pub struct subject(()); + } +} + +/// Builder for constructing an instance of this type. +pub struct CountKeysBuilder { + _state: PhantomData St>, + _fields: (Option>,), + _type: PhantomData S>, +} + +impl CountKeys { + /// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed + pub fn new() -> CountKeysBuilder { + CountKeysBuilder::new() + } +} + +impl CountKeys { + /// Create a new builder for this type + pub fn builder() -> CountKeysBuilder { + CountKeysBuilder::builder() + } +} + +impl CountKeysBuilder { + /// Create a new builder with all fields unset, using the default string type, if needed + pub fn new() -> Self { + CountKeysBuilder { + _state: PhantomData, + _fields: (None,), + _type: PhantomData, + } + } +} + +impl CountKeysBuilder { + /// Create a new builder with all fields unset + pub fn builder() -> Self { + CountKeysBuilder { + _state: PhantomData, + _fields: (None,), + _type: PhantomData, + } + } +} + +impl CountKeysBuilder +where + St: count_keys_state::State, + St::Subject: count_keys_state::IsUnset, +{ + /// Set the `subject` field (required) + pub fn subject( + mut self, + value: impl Into>, + ) -> CountKeysBuilder, S> { + self._fields.0 = Option::Some(value.into()); + CountKeysBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl CountKeysBuilder +where + St: count_keys_state::State, + St::Subject: count_keys_state::IsSet, +{ + /// Build the final struct. + pub fn build(self) -> CountKeys { + CountKeys { + subject: self._fields.0.unwrap(), + } + } +} diff --git a/crates/jacquard-api/src/sh_tangled/repo.rs b/crates/jacquard-api/src/sh_tangled/repo.rs index 7a47d64ff..cc9eb0d6b 100644 --- a/crates/jacquard-api/src/sh_tangled/repo.rs +++ b/crates/jacquard-api/src/sh_tangled/repo.rs @@ -15,6 +15,15 @@ pub mod branch; pub mod branches; pub mod collaborator; pub mod compare; +pub mod count_artifacts; +pub mod count_artifacts_by; +pub mod count_collaborators; +pub mod count_collaborators_by; +pub mod count_issues; +pub mod count_issues_by; +pub mod count_pulls; +pub mod count_pulls_by; +pub mod count_repos; pub mod create; pub mod delete; pub mod delete_branch; @@ -23,6 +32,13 @@ pub mod diff; pub mod fork_status; pub mod fork_sync; pub mod get_default_branch; +pub mod get_issue; +pub mod get_issues; +pub mod get_pull; +pub mod get_pulls; +pub mod get_repo; +pub mod get_repo_by_repo_did; +pub mod get_repos; pub mod hidden_ref; pub mod issue; pub mod languages; @@ -40,8 +56,11 @@ pub mod log; pub mod merge; pub mod merge_check; pub mod pull; +pub mod push; pub mod remove_collaborator; pub mod remove_secret; +pub mod rename; +pub mod reserve_key; pub mod set_default_branch; pub mod tag; pub mod tags; @@ -197,6 +216,30 @@ impl LexiconSchema for Repo { }); } } + if let Some(values) = &self.topics { + for value in values { + #[allow(unused_comparisons)] + if ::len(value.as_ref()) > 50usize { + return Err(ConstraintError::MaxLength { + path: ValidationPath::from_field("topics"), + max: 50usize, + actual: ::len(value.as_ref()), + }); + } + } + } + if let Some(values) = &self.topics { + for value in values { + #[allow(unused_comparisons)] + if ::len(value.as_ref()) < 1usize { + return Err(ConstraintError::MinLength { + path: ValidationPath::from_field("topics"), + min: 1usize, + actual: ::len(value.as_ref()), + }); + } + } + } Ok(()) } } diff --git a/crates/jacquard-api/src/sh_tangled/repo/count_artifacts.rs b/crates/jacquard-api/src/sh_tangled/repo/count_artifacts.rs new file mode 100644 index 000000000..d72e59fca --- /dev/null +++ b/crates/jacquard-api/src/sh_tangled/repo/count_artifacts.rs @@ -0,0 +1,175 @@ +// @generated by jacquard-lexicon. DO NOT EDIT. +// +// Lexicon: sh.tangled.repo.countArtifacts +// +// 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::deps::smol_str::SmolStr; +use jacquard_common::types::value::Data; +use jacquard_common::{BosStr, CowStr, DefaultStr, FromStaticStr}; +use jacquard_derive::IntoStatic; +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct CountArtifacts { + pub subject: S, +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct CountArtifactsOutput { + ///Total number of matching records. + pub count: i64, + ///Number of distinct authors among the matching records. + pub distinct_authors: i64, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +/** Response marker for the `sh.tangled.repo.countArtifacts` query. + +Implements `jacquard_common::xrpc::XrpcResp`; successful bodies decode as `Self::Output`, which is `CountArtifactsOutput` for this endpoint.*/ +pub struct CountArtifactsResponse; +impl jacquard_common::xrpc::XrpcResp for CountArtifactsResponse { + const NSID: &'static str = "sh.tangled.repo.countArtifacts"; + const ENCODING: &'static str = "application/json"; + type Output = CountArtifactsOutput; + type Err = jacquard_common::xrpc::GenericError; +} + +impl jacquard_common::xrpc::XrpcRequest for CountArtifacts { + const NSID: &'static str = "sh.tangled.repo.countArtifacts"; + const METHOD: jacquard_common::xrpc::XrpcMethod = jacquard_common::xrpc::XrpcMethod::Query; + type Response = CountArtifactsResponse; +} + +/** Endpoint marker for the `sh.tangled.repo.countArtifacts` query. + +Path: `/xrpc/sh.tangled.repo.countArtifacts`. The request payload type is `CountArtifacts`; send that request with `jacquard::Client` or use this marker through lower-level `XrpcEndpoint` APIs.*/ +pub struct CountArtifactsRequest; +impl jacquard_common::xrpc::XrpcEndpoint for CountArtifactsRequest { + const PATH: &'static str = "/xrpc/sh.tangled.repo.countArtifacts"; + const METHOD: jacquard_common::xrpc::XrpcMethod = jacquard_common::xrpc::XrpcMethod::Query; + type Request = CountArtifacts; + type Response = CountArtifactsResponse; +} + +pub mod count_artifacts_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 Subject; + } + /// Empty state - all required fields are unset + pub struct Empty(()); + impl sealed::Sealed for Empty {} + impl State for Empty { + type Subject = Unset; + } + ///State transition - sets the `subject` field to Set + pub struct SetSubject(PhantomData St>); + impl sealed::Sealed for SetSubject {} + impl State for SetSubject { + type Subject = Set; + } + /// Marker types for field names + #[allow(non_camel_case_types)] + pub mod members { + ///Marker type for the `subject` field + pub struct subject(()); + } +} + +/// Builder for constructing an instance of this type. +pub struct CountArtifactsBuilder { + _state: PhantomData St>, + _fields: (Option,), + _type: PhantomData S>, +} + +impl CountArtifacts { + /// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed + pub fn new() -> CountArtifactsBuilder { + CountArtifactsBuilder::new() + } +} + +impl CountArtifacts { + /// Create a new builder for this type + pub fn builder() -> CountArtifactsBuilder { + CountArtifactsBuilder::builder() + } +} + +impl CountArtifactsBuilder { + /// Create a new builder with all fields unset, using the default string type, if needed + pub fn new() -> Self { + CountArtifactsBuilder { + _state: PhantomData, + _fields: (None,), + _type: PhantomData, + } + } +} + +impl CountArtifactsBuilder { + /// Create a new builder with all fields unset + pub fn builder() -> Self { + CountArtifactsBuilder { + _state: PhantomData, + _fields: (None,), + _type: PhantomData, + } + } +} + +impl CountArtifactsBuilder +where + St: count_artifacts_state::State, + St::Subject: count_artifacts_state::IsUnset, +{ + /// Set the `subject` field (required) + pub fn subject( + mut self, + value: impl Into, + ) -> CountArtifactsBuilder, S> { + self._fields.0 = Option::Some(value.into()); + CountArtifactsBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl CountArtifactsBuilder +where + St: count_artifacts_state::State, + St::Subject: count_artifacts_state::IsSet, +{ + /// Build the final struct. + pub fn build(self) -> CountArtifacts { + CountArtifacts { + subject: self._fields.0.unwrap(), + } + } +} diff --git a/crates/jacquard-api/src/sh_tangled/repo/count_artifacts_by.rs b/crates/jacquard-api/src/sh_tangled/repo/count_artifacts_by.rs new file mode 100644 index 000000000..9e28504d6 --- /dev/null +++ b/crates/jacquard-api/src/sh_tangled/repo/count_artifacts_by.rs @@ -0,0 +1,176 @@ +// @generated by jacquard-lexicon. DO NOT EDIT. +// +// Lexicon: sh.tangled.repo.countArtifactsBy +// +// 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::deps::smol_str::SmolStr; +use jacquard_common::types::string::Did; +use jacquard_common::types::value::Data; +use jacquard_common::{BosStr, DefaultStr, FromStaticStr}; +use jacquard_derive::IntoStatic; +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct CountArtifactsBy { + pub subject: Did, +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct CountArtifactsByOutput { + ///Total number of matching records. + pub count: i64, + ///Number of distinct authors among the matching records. + pub distinct_authors: i64, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +/** Response marker for the `sh.tangled.repo.countArtifactsBy` query. + +Implements `jacquard_common::xrpc::XrpcResp`; successful bodies decode as `Self::Output`, which is `CountArtifactsByOutput` for this endpoint.*/ +pub struct CountArtifactsByResponse; +impl jacquard_common::xrpc::XrpcResp for CountArtifactsByResponse { + const NSID: &'static str = "sh.tangled.repo.countArtifactsBy"; + const ENCODING: &'static str = "application/json"; + type Output = CountArtifactsByOutput; + type Err = jacquard_common::xrpc::GenericError; +} + +impl jacquard_common::xrpc::XrpcRequest for CountArtifactsBy { + const NSID: &'static str = "sh.tangled.repo.countArtifactsBy"; + const METHOD: jacquard_common::xrpc::XrpcMethod = jacquard_common::xrpc::XrpcMethod::Query; + type Response = CountArtifactsByResponse; +} + +/** Endpoint marker for the `sh.tangled.repo.countArtifactsBy` query. + +Path: `/xrpc/sh.tangled.repo.countArtifactsBy`. The request payload type is `CountArtifactsBy`; send that request with `jacquard::Client` or use this marker through lower-level `XrpcEndpoint` APIs.*/ +pub struct CountArtifactsByRequest; +impl jacquard_common::xrpc::XrpcEndpoint for CountArtifactsByRequest { + const PATH: &'static str = "/xrpc/sh.tangled.repo.countArtifactsBy"; + const METHOD: jacquard_common::xrpc::XrpcMethod = jacquard_common::xrpc::XrpcMethod::Query; + type Request = CountArtifactsBy; + type Response = CountArtifactsByResponse; +} + +pub mod count_artifacts_by_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 Subject; + } + /// Empty state - all required fields are unset + pub struct Empty(()); + impl sealed::Sealed for Empty {} + impl State for Empty { + type Subject = Unset; + } + ///State transition - sets the `subject` field to Set + pub struct SetSubject(PhantomData St>); + impl sealed::Sealed for SetSubject {} + impl State for SetSubject { + type Subject = Set; + } + /// Marker types for field names + #[allow(non_camel_case_types)] + pub mod members { + ///Marker type for the `subject` field + pub struct subject(()); + } +} + +/// Builder for constructing an instance of this type. +pub struct CountArtifactsByBuilder { + _state: PhantomData St>, + _fields: (Option>,), + _type: PhantomData S>, +} + +impl CountArtifactsBy { + /// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed + pub fn new() -> CountArtifactsByBuilder { + CountArtifactsByBuilder::new() + } +} + +impl CountArtifactsBy { + /// Create a new builder for this type + pub fn builder() -> CountArtifactsByBuilder { + CountArtifactsByBuilder::builder() + } +} + +impl CountArtifactsByBuilder { + /// Create a new builder with all fields unset, using the default string type, if needed + pub fn new() -> Self { + CountArtifactsByBuilder { + _state: PhantomData, + _fields: (None,), + _type: PhantomData, + } + } +} + +impl CountArtifactsByBuilder { + /// Create a new builder with all fields unset + pub fn builder() -> Self { + CountArtifactsByBuilder { + _state: PhantomData, + _fields: (None,), + _type: PhantomData, + } + } +} + +impl CountArtifactsByBuilder +where + St: count_artifacts_by_state::State, + St::Subject: count_artifacts_by_state::IsUnset, +{ + /// Set the `subject` field (required) + pub fn subject( + mut self, + value: impl Into>, + ) -> CountArtifactsByBuilder, S> { + self._fields.0 = Option::Some(value.into()); + CountArtifactsByBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl CountArtifactsByBuilder +where + St: count_artifacts_by_state::State, + St::Subject: count_artifacts_by_state::IsSet, +{ + /// Build the final struct. + pub fn build(self) -> CountArtifactsBy { + CountArtifactsBy { + subject: self._fields.0.unwrap(), + } + } +} diff --git a/crates/jacquard-api/src/sh_tangled/repo/count_collaborators.rs b/crates/jacquard-api/src/sh_tangled/repo/count_collaborators.rs new file mode 100644 index 000000000..cfa3d5b48 --- /dev/null +++ b/crates/jacquard-api/src/sh_tangled/repo/count_collaborators.rs @@ -0,0 +1,176 @@ +// @generated by jacquard-lexicon. DO NOT EDIT. +// +// Lexicon: sh.tangled.repo.countCollaborators +// +// 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::deps::smol_str::SmolStr; +use jacquard_common::types::string::Did; +use jacquard_common::types::value::Data; +use jacquard_common::{BosStr, DefaultStr, FromStaticStr}; +use jacquard_derive::IntoStatic; +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct CountCollaborators { + pub subject: Did, +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct CountCollaboratorsOutput { + ///Total number of matching records. + pub count: i64, + ///Number of distinct authors among the matching records. + pub distinct_authors: i64, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +/** Response marker for the `sh.tangled.repo.countCollaborators` query. + +Implements `jacquard_common::xrpc::XrpcResp`; successful bodies decode as `Self::Output`, which is `CountCollaboratorsOutput` for this endpoint.*/ +pub struct CountCollaboratorsResponse; +impl jacquard_common::xrpc::XrpcResp for CountCollaboratorsResponse { + const NSID: &'static str = "sh.tangled.repo.countCollaborators"; + const ENCODING: &'static str = "application/json"; + type Output = CountCollaboratorsOutput; + type Err = jacquard_common::xrpc::GenericError; +} + +impl jacquard_common::xrpc::XrpcRequest for CountCollaborators { + const NSID: &'static str = "sh.tangled.repo.countCollaborators"; + const METHOD: jacquard_common::xrpc::XrpcMethod = jacquard_common::xrpc::XrpcMethod::Query; + type Response = CountCollaboratorsResponse; +} + +/** Endpoint marker for the `sh.tangled.repo.countCollaborators` query. + +Path: `/xrpc/sh.tangled.repo.countCollaborators`. The request payload type is `CountCollaborators`; send that request with `jacquard::Client` or use this marker through lower-level `XrpcEndpoint` APIs.*/ +pub struct CountCollaboratorsRequest; +impl jacquard_common::xrpc::XrpcEndpoint for CountCollaboratorsRequest { + const PATH: &'static str = "/xrpc/sh.tangled.repo.countCollaborators"; + const METHOD: jacquard_common::xrpc::XrpcMethod = jacquard_common::xrpc::XrpcMethod::Query; + type Request = CountCollaborators; + type Response = CountCollaboratorsResponse; +} + +pub mod count_collaborators_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 Subject; + } + /// Empty state - all required fields are unset + pub struct Empty(()); + impl sealed::Sealed for Empty {} + impl State for Empty { + type Subject = Unset; + } + ///State transition - sets the `subject` field to Set + pub struct SetSubject(PhantomData St>); + impl sealed::Sealed for SetSubject {} + impl State for SetSubject { + type Subject = Set; + } + /// Marker types for field names + #[allow(non_camel_case_types)] + pub mod members { + ///Marker type for the `subject` field + pub struct subject(()); + } +} + +/// Builder for constructing an instance of this type. +pub struct CountCollaboratorsBuilder { + _state: PhantomData St>, + _fields: (Option>,), + _type: PhantomData S>, +} + +impl CountCollaborators { + /// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed + pub fn new() -> CountCollaboratorsBuilder { + CountCollaboratorsBuilder::new() + } +} + +impl CountCollaborators { + /// Create a new builder for this type + pub fn builder() -> CountCollaboratorsBuilder { + CountCollaboratorsBuilder::builder() + } +} + +impl CountCollaboratorsBuilder { + /// Create a new builder with all fields unset, using the default string type, if needed + pub fn new() -> Self { + CountCollaboratorsBuilder { + _state: PhantomData, + _fields: (None,), + _type: PhantomData, + } + } +} + +impl CountCollaboratorsBuilder { + /// Create a new builder with all fields unset + pub fn builder() -> Self { + CountCollaboratorsBuilder { + _state: PhantomData, + _fields: (None,), + _type: PhantomData, + } + } +} + +impl CountCollaboratorsBuilder +where + St: count_collaborators_state::State, + St::Subject: count_collaborators_state::IsUnset, +{ + /// Set the `subject` field (required) + pub fn subject( + mut self, + value: impl Into>, + ) -> CountCollaboratorsBuilder, S> { + self._fields.0 = Option::Some(value.into()); + CountCollaboratorsBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl CountCollaboratorsBuilder +where + St: count_collaborators_state::State, + St::Subject: count_collaborators_state::IsSet, +{ + /// Build the final struct. + pub fn build(self) -> CountCollaborators { + CountCollaborators { + subject: self._fields.0.unwrap(), + } + } +} diff --git a/crates/jacquard-api/src/sh_tangled/repo/count_collaborators_by.rs b/crates/jacquard-api/src/sh_tangled/repo/count_collaborators_by.rs new file mode 100644 index 000000000..805a7be59 --- /dev/null +++ b/crates/jacquard-api/src/sh_tangled/repo/count_collaborators_by.rs @@ -0,0 +1,179 @@ +// @generated by jacquard-lexicon. DO NOT EDIT. +// +// Lexicon: sh.tangled.repo.countCollaboratorsBy +// +// 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::deps::smol_str::SmolStr; +use jacquard_common::types::string::Did; +use jacquard_common::types::value::Data; +use jacquard_common::{BosStr, DefaultStr, FromStaticStr}; +use jacquard_derive::IntoStatic; +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct CountCollaboratorsBy { + pub subject: Did, +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct CountCollaboratorsByOutput { + ///Total number of matching records. + pub count: i64, + ///Number of distinct authors among the matching records. + pub distinct_authors: i64, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +/** Response marker for the `sh.tangled.repo.countCollaboratorsBy` query. + +Implements `jacquard_common::xrpc::XrpcResp`; successful bodies decode as `Self::Output`, which is `CountCollaboratorsByOutput` for this endpoint.*/ +pub struct CountCollaboratorsByResponse; +impl jacquard_common::xrpc::XrpcResp for CountCollaboratorsByResponse { + const NSID: &'static str = "sh.tangled.repo.countCollaboratorsBy"; + const ENCODING: &'static str = "application/json"; + type Output = CountCollaboratorsByOutput; + type Err = jacquard_common::xrpc::GenericError; +} + +impl jacquard_common::xrpc::XrpcRequest for CountCollaboratorsBy { + const NSID: &'static str = "sh.tangled.repo.countCollaboratorsBy"; + const METHOD: jacquard_common::xrpc::XrpcMethod = jacquard_common::xrpc::XrpcMethod::Query; + type Response = CountCollaboratorsByResponse; +} + +/** Endpoint marker for the `sh.tangled.repo.countCollaboratorsBy` query. + +Path: `/xrpc/sh.tangled.repo.countCollaboratorsBy`. The request payload type is `CountCollaboratorsBy`; send that request with `jacquard::Client` or use this marker through lower-level `XrpcEndpoint` APIs.*/ +pub struct CountCollaboratorsByRequest; +impl jacquard_common::xrpc::XrpcEndpoint for CountCollaboratorsByRequest { + const PATH: &'static str = "/xrpc/sh.tangled.repo.countCollaboratorsBy"; + const METHOD: jacquard_common::xrpc::XrpcMethod = jacquard_common::xrpc::XrpcMethod::Query; + type Request = CountCollaboratorsBy; + type Response = CountCollaboratorsByResponse; +} + +pub mod count_collaborators_by_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 Subject; + } + /// Empty state - all required fields are unset + pub struct Empty(()); + impl sealed::Sealed for Empty {} + impl State for Empty { + type Subject = Unset; + } + ///State transition - sets the `subject` field to Set + pub struct SetSubject(PhantomData St>); + impl sealed::Sealed for SetSubject {} + impl State for SetSubject { + type Subject = Set; + } + /// Marker types for field names + #[allow(non_camel_case_types)] + pub mod members { + ///Marker type for the `subject` field + pub struct subject(()); + } +} + +/// Builder for constructing an instance of this type. +pub struct CountCollaboratorsByBuilder< + St: count_collaborators_by_state::State, + S: BosStr = DefaultStr, +> { + _state: PhantomData St>, + _fields: (Option>,), + _type: PhantomData S>, +} + +impl CountCollaboratorsBy { + /// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed + pub fn new() -> CountCollaboratorsByBuilder { + CountCollaboratorsByBuilder::new() + } +} + +impl CountCollaboratorsBy { + /// Create a new builder for this type + pub fn builder() -> CountCollaboratorsByBuilder { + CountCollaboratorsByBuilder::builder() + } +} + +impl CountCollaboratorsByBuilder { + /// Create a new builder with all fields unset, using the default string type, if needed + pub fn new() -> Self { + CountCollaboratorsByBuilder { + _state: PhantomData, + _fields: (None,), + _type: PhantomData, + } + } +} + +impl CountCollaboratorsByBuilder { + /// Create a new builder with all fields unset + pub fn builder() -> Self { + CountCollaboratorsByBuilder { + _state: PhantomData, + _fields: (None,), + _type: PhantomData, + } + } +} + +impl CountCollaboratorsByBuilder +where + St: count_collaborators_by_state::State, + St::Subject: count_collaborators_by_state::IsUnset, +{ + /// Set the `subject` field (required) + pub fn subject( + mut self, + value: impl Into>, + ) -> CountCollaboratorsByBuilder, S> { + self._fields.0 = Option::Some(value.into()); + CountCollaboratorsByBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl CountCollaboratorsByBuilder +where + St: count_collaborators_by_state::State, + St::Subject: count_collaborators_by_state::IsSet, +{ + /// Build the final struct. + pub fn build(self) -> CountCollaboratorsBy { + CountCollaboratorsBy { + subject: self._fields.0.unwrap(), + } + } +} diff --git a/crates/jacquard-api/src/sh_tangled/repo/count_issues.rs b/crates/jacquard-api/src/sh_tangled/repo/count_issues.rs new file mode 100644 index 000000000..3de73b286 --- /dev/null +++ b/crates/jacquard-api/src/sh_tangled/repo/count_issues.rs @@ -0,0 +1,176 @@ +// @generated by jacquard-lexicon. DO NOT EDIT. +// +// Lexicon: sh.tangled.repo.countIssues +// +// 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::deps::smol_str::SmolStr; +use jacquard_common::types::string::Did; +use jacquard_common::types::value::Data; +use jacquard_common::{BosStr, DefaultStr, FromStaticStr}; +use jacquard_derive::IntoStatic; +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct CountIssues { + pub subject: Did, +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct CountIssuesOutput { + ///Total number of matching records. + pub count: i64, + ///Number of distinct authors among the matching records. + pub distinct_authors: i64, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +/** Response marker for the `sh.tangled.repo.countIssues` query. + +Implements `jacquard_common::xrpc::XrpcResp`; successful bodies decode as `Self::Output`, which is `CountIssuesOutput` for this endpoint.*/ +pub struct CountIssuesResponse; +impl jacquard_common::xrpc::XrpcResp for CountIssuesResponse { + const NSID: &'static str = "sh.tangled.repo.countIssues"; + const ENCODING: &'static str = "application/json"; + type Output = CountIssuesOutput; + type Err = jacquard_common::xrpc::GenericError; +} + +impl jacquard_common::xrpc::XrpcRequest for CountIssues { + const NSID: &'static str = "sh.tangled.repo.countIssues"; + const METHOD: jacquard_common::xrpc::XrpcMethod = jacquard_common::xrpc::XrpcMethod::Query; + type Response = CountIssuesResponse; +} + +/** Endpoint marker for the `sh.tangled.repo.countIssues` query. + +Path: `/xrpc/sh.tangled.repo.countIssues`. The request payload type is `CountIssues`; send that request with `jacquard::Client` or use this marker through lower-level `XrpcEndpoint` APIs.*/ +pub struct CountIssuesRequest; +impl jacquard_common::xrpc::XrpcEndpoint for CountIssuesRequest { + const PATH: &'static str = "/xrpc/sh.tangled.repo.countIssues"; + const METHOD: jacquard_common::xrpc::XrpcMethod = jacquard_common::xrpc::XrpcMethod::Query; + type Request = CountIssues; + type Response = CountIssuesResponse; +} + +pub mod count_issues_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 Subject; + } + /// Empty state - all required fields are unset + pub struct Empty(()); + impl sealed::Sealed for Empty {} + impl State for Empty { + type Subject = Unset; + } + ///State transition - sets the `subject` field to Set + pub struct SetSubject(PhantomData St>); + impl sealed::Sealed for SetSubject {} + impl State for SetSubject { + type Subject = Set; + } + /// Marker types for field names + #[allow(non_camel_case_types)] + pub mod members { + ///Marker type for the `subject` field + pub struct subject(()); + } +} + +/// Builder for constructing an instance of this type. +pub struct CountIssuesBuilder { + _state: PhantomData St>, + _fields: (Option>,), + _type: PhantomData S>, +} + +impl CountIssues { + /// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed + pub fn new() -> CountIssuesBuilder { + CountIssuesBuilder::new() + } +} + +impl CountIssues { + /// Create a new builder for this type + pub fn builder() -> CountIssuesBuilder { + CountIssuesBuilder::builder() + } +} + +impl CountIssuesBuilder { + /// Create a new builder with all fields unset, using the default string type, if needed + pub fn new() -> Self { + CountIssuesBuilder { + _state: PhantomData, + _fields: (None,), + _type: PhantomData, + } + } +} + +impl CountIssuesBuilder { + /// Create a new builder with all fields unset + pub fn builder() -> Self { + CountIssuesBuilder { + _state: PhantomData, + _fields: (None,), + _type: PhantomData, + } + } +} + +impl CountIssuesBuilder +where + St: count_issues_state::State, + St::Subject: count_issues_state::IsUnset, +{ + /// Set the `subject` field (required) + pub fn subject( + mut self, + value: impl Into>, + ) -> CountIssuesBuilder, S> { + self._fields.0 = Option::Some(value.into()); + CountIssuesBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl CountIssuesBuilder +where + St: count_issues_state::State, + St::Subject: count_issues_state::IsSet, +{ + /// Build the final struct. + pub fn build(self) -> CountIssues { + CountIssues { + subject: self._fields.0.unwrap(), + } + } +} diff --git a/crates/jacquard-api/src/sh_tangled/repo/count_issues_by.rs b/crates/jacquard-api/src/sh_tangled/repo/count_issues_by.rs new file mode 100644 index 000000000..ff470a460 --- /dev/null +++ b/crates/jacquard-api/src/sh_tangled/repo/count_issues_by.rs @@ -0,0 +1,176 @@ +// @generated by jacquard-lexicon. DO NOT EDIT. +// +// Lexicon: sh.tangled.repo.countIssuesBy +// +// 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::deps::smol_str::SmolStr; +use jacquard_common::types::string::Did; +use jacquard_common::types::value::Data; +use jacquard_common::{BosStr, DefaultStr, FromStaticStr}; +use jacquard_derive::IntoStatic; +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct CountIssuesBy { + pub subject: Did, +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct CountIssuesByOutput { + ///Total number of matching records. + pub count: i64, + ///Number of distinct authors among the matching records. + pub distinct_authors: i64, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +/** Response marker for the `sh.tangled.repo.countIssuesBy` query. + +Implements `jacquard_common::xrpc::XrpcResp`; successful bodies decode as `Self::Output`, which is `CountIssuesByOutput` for this endpoint.*/ +pub struct CountIssuesByResponse; +impl jacquard_common::xrpc::XrpcResp for CountIssuesByResponse { + const NSID: &'static str = "sh.tangled.repo.countIssuesBy"; + const ENCODING: &'static str = "application/json"; + type Output = CountIssuesByOutput; + type Err = jacquard_common::xrpc::GenericError; +} + +impl jacquard_common::xrpc::XrpcRequest for CountIssuesBy { + const NSID: &'static str = "sh.tangled.repo.countIssuesBy"; + const METHOD: jacquard_common::xrpc::XrpcMethod = jacquard_common::xrpc::XrpcMethod::Query; + type Response = CountIssuesByResponse; +} + +/** Endpoint marker for the `sh.tangled.repo.countIssuesBy` query. + +Path: `/xrpc/sh.tangled.repo.countIssuesBy`. The request payload type is `CountIssuesBy`; send that request with `jacquard::Client` or use this marker through lower-level `XrpcEndpoint` APIs.*/ +pub struct CountIssuesByRequest; +impl jacquard_common::xrpc::XrpcEndpoint for CountIssuesByRequest { + const PATH: &'static str = "/xrpc/sh.tangled.repo.countIssuesBy"; + const METHOD: jacquard_common::xrpc::XrpcMethod = jacquard_common::xrpc::XrpcMethod::Query; + type Request = CountIssuesBy; + type Response = CountIssuesByResponse; +} + +pub mod count_issues_by_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 Subject; + } + /// Empty state - all required fields are unset + pub struct Empty(()); + impl sealed::Sealed for Empty {} + impl State for Empty { + type Subject = Unset; + } + ///State transition - sets the `subject` field to Set + pub struct SetSubject(PhantomData St>); + impl sealed::Sealed for SetSubject {} + impl State for SetSubject { + type Subject = Set; + } + /// Marker types for field names + #[allow(non_camel_case_types)] + pub mod members { + ///Marker type for the `subject` field + pub struct subject(()); + } +} + +/// Builder for constructing an instance of this type. +pub struct CountIssuesByBuilder { + _state: PhantomData St>, + _fields: (Option>,), + _type: PhantomData S>, +} + +impl CountIssuesBy { + /// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed + pub fn new() -> CountIssuesByBuilder { + CountIssuesByBuilder::new() + } +} + +impl CountIssuesBy { + /// Create a new builder for this type + pub fn builder() -> CountIssuesByBuilder { + CountIssuesByBuilder::builder() + } +} + +impl CountIssuesByBuilder { + /// Create a new builder with all fields unset, using the default string type, if needed + pub fn new() -> Self { + CountIssuesByBuilder { + _state: PhantomData, + _fields: (None,), + _type: PhantomData, + } + } +} + +impl CountIssuesByBuilder { + /// Create a new builder with all fields unset + pub fn builder() -> Self { + CountIssuesByBuilder { + _state: PhantomData, + _fields: (None,), + _type: PhantomData, + } + } +} + +impl CountIssuesByBuilder +where + St: count_issues_by_state::State, + St::Subject: count_issues_by_state::IsUnset, +{ + /// Set the `subject` field (required) + pub fn subject( + mut self, + value: impl Into>, + ) -> CountIssuesByBuilder, S> { + self._fields.0 = Option::Some(value.into()); + CountIssuesByBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl CountIssuesByBuilder +where + St: count_issues_by_state::State, + St::Subject: count_issues_by_state::IsSet, +{ + /// Build the final struct. + pub fn build(self) -> CountIssuesBy { + CountIssuesBy { + subject: self._fields.0.unwrap(), + } + } +} diff --git a/crates/jacquard-api/src/sh_tangled/repo/count_pulls.rs b/crates/jacquard-api/src/sh_tangled/repo/count_pulls.rs new file mode 100644 index 000000000..9b125f2b7 --- /dev/null +++ b/crates/jacquard-api/src/sh_tangled/repo/count_pulls.rs @@ -0,0 +1,176 @@ +// @generated by jacquard-lexicon. DO NOT EDIT. +// +// Lexicon: sh.tangled.repo.countPulls +// +// 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::deps::smol_str::SmolStr; +use jacquard_common::types::string::Did; +use jacquard_common::types::value::Data; +use jacquard_common::{BosStr, DefaultStr, FromStaticStr}; +use jacquard_derive::IntoStatic; +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct CountPulls { + pub subject: Did, +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct CountPullsOutput { + ///Total number of matching records. + pub count: i64, + ///Number of distinct authors among the matching records. + pub distinct_authors: i64, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +/** Response marker for the `sh.tangled.repo.countPulls` query. + +Implements `jacquard_common::xrpc::XrpcResp`; successful bodies decode as `Self::Output`, which is `CountPullsOutput` for this endpoint.*/ +pub struct CountPullsResponse; +impl jacquard_common::xrpc::XrpcResp for CountPullsResponse { + const NSID: &'static str = "sh.tangled.repo.countPulls"; + const ENCODING: &'static str = "application/json"; + type Output = CountPullsOutput; + type Err = jacquard_common::xrpc::GenericError; +} + +impl jacquard_common::xrpc::XrpcRequest for CountPulls { + const NSID: &'static str = "sh.tangled.repo.countPulls"; + const METHOD: jacquard_common::xrpc::XrpcMethod = jacquard_common::xrpc::XrpcMethod::Query; + type Response = CountPullsResponse; +} + +/** Endpoint marker for the `sh.tangled.repo.countPulls` query. + +Path: `/xrpc/sh.tangled.repo.countPulls`. The request payload type is `CountPulls`; send that request with `jacquard::Client` or use this marker through lower-level `XrpcEndpoint` APIs.*/ +pub struct CountPullsRequest; +impl jacquard_common::xrpc::XrpcEndpoint for CountPullsRequest { + const PATH: &'static str = "/xrpc/sh.tangled.repo.countPulls"; + const METHOD: jacquard_common::xrpc::XrpcMethod = jacquard_common::xrpc::XrpcMethod::Query; + type Request = CountPulls; + type Response = CountPullsResponse; +} + +pub mod count_pulls_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 Subject; + } + /// Empty state - all required fields are unset + pub struct Empty(()); + impl sealed::Sealed for Empty {} + impl State for Empty { + type Subject = Unset; + } + ///State transition - sets the `subject` field to Set + pub struct SetSubject(PhantomData St>); + impl sealed::Sealed for SetSubject {} + impl State for SetSubject { + type Subject = Set; + } + /// Marker types for field names + #[allow(non_camel_case_types)] + pub mod members { + ///Marker type for the `subject` field + pub struct subject(()); + } +} + +/// Builder for constructing an instance of this type. +pub struct CountPullsBuilder { + _state: PhantomData St>, + _fields: (Option>,), + _type: PhantomData S>, +} + +impl CountPulls { + /// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed + pub fn new() -> CountPullsBuilder { + CountPullsBuilder::new() + } +} + +impl CountPulls { + /// Create a new builder for this type + pub fn builder() -> CountPullsBuilder { + CountPullsBuilder::builder() + } +} + +impl CountPullsBuilder { + /// Create a new builder with all fields unset, using the default string type, if needed + pub fn new() -> Self { + CountPullsBuilder { + _state: PhantomData, + _fields: (None,), + _type: PhantomData, + } + } +} + +impl CountPullsBuilder { + /// Create a new builder with all fields unset + pub fn builder() -> Self { + CountPullsBuilder { + _state: PhantomData, + _fields: (None,), + _type: PhantomData, + } + } +} + +impl CountPullsBuilder +where + St: count_pulls_state::State, + St::Subject: count_pulls_state::IsUnset, +{ + /// Set the `subject` field (required) + pub fn subject( + mut self, + value: impl Into>, + ) -> CountPullsBuilder, S> { + self._fields.0 = Option::Some(value.into()); + CountPullsBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl CountPullsBuilder +where + St: count_pulls_state::State, + St::Subject: count_pulls_state::IsSet, +{ + /// Build the final struct. + pub fn build(self) -> CountPulls { + CountPulls { + subject: self._fields.0.unwrap(), + } + } +} diff --git a/crates/jacquard-api/src/sh_tangled/repo/count_pulls_by.rs b/crates/jacquard-api/src/sh_tangled/repo/count_pulls_by.rs new file mode 100644 index 000000000..d689cd20f --- /dev/null +++ b/crates/jacquard-api/src/sh_tangled/repo/count_pulls_by.rs @@ -0,0 +1,176 @@ +// @generated by jacquard-lexicon. DO NOT EDIT. +// +// Lexicon: sh.tangled.repo.countPullsBy +// +// 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::deps::smol_str::SmolStr; +use jacquard_common::types::string::Did; +use jacquard_common::types::value::Data; +use jacquard_common::{BosStr, DefaultStr, FromStaticStr}; +use jacquard_derive::IntoStatic; +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct CountPullsBy { + pub subject: Did, +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct CountPullsByOutput { + ///Total number of matching records. + pub count: i64, + ///Number of distinct authors among the matching records. + pub distinct_authors: i64, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +/** Response marker for the `sh.tangled.repo.countPullsBy` query. + +Implements `jacquard_common::xrpc::XrpcResp`; successful bodies decode as `Self::Output`, which is `CountPullsByOutput` for this endpoint.*/ +pub struct CountPullsByResponse; +impl jacquard_common::xrpc::XrpcResp for CountPullsByResponse { + const NSID: &'static str = "sh.tangled.repo.countPullsBy"; + const ENCODING: &'static str = "application/json"; + type Output = CountPullsByOutput; + type Err = jacquard_common::xrpc::GenericError; +} + +impl jacquard_common::xrpc::XrpcRequest for CountPullsBy { + const NSID: &'static str = "sh.tangled.repo.countPullsBy"; + const METHOD: jacquard_common::xrpc::XrpcMethod = jacquard_common::xrpc::XrpcMethod::Query; + type Response = CountPullsByResponse; +} + +/** Endpoint marker for the `sh.tangled.repo.countPullsBy` query. + +Path: `/xrpc/sh.tangled.repo.countPullsBy`. The request payload type is `CountPullsBy`; send that request with `jacquard::Client` or use this marker through lower-level `XrpcEndpoint` APIs.*/ +pub struct CountPullsByRequest; +impl jacquard_common::xrpc::XrpcEndpoint for CountPullsByRequest { + const PATH: &'static str = "/xrpc/sh.tangled.repo.countPullsBy"; + const METHOD: jacquard_common::xrpc::XrpcMethod = jacquard_common::xrpc::XrpcMethod::Query; + type Request = CountPullsBy; + type Response = CountPullsByResponse; +} + +pub mod count_pulls_by_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 Subject; + } + /// Empty state - all required fields are unset + pub struct Empty(()); + impl sealed::Sealed for Empty {} + impl State for Empty { + type Subject = Unset; + } + ///State transition - sets the `subject` field to Set + pub struct SetSubject(PhantomData St>); + impl sealed::Sealed for SetSubject {} + impl State for SetSubject { + type Subject = Set; + } + /// Marker types for field names + #[allow(non_camel_case_types)] + pub mod members { + ///Marker type for the `subject` field + pub struct subject(()); + } +} + +/// Builder for constructing an instance of this type. +pub struct CountPullsByBuilder { + _state: PhantomData St>, + _fields: (Option>,), + _type: PhantomData S>, +} + +impl CountPullsBy { + /// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed + pub fn new() -> CountPullsByBuilder { + CountPullsByBuilder::new() + } +} + +impl CountPullsBy { + /// Create a new builder for this type + pub fn builder() -> CountPullsByBuilder { + CountPullsByBuilder::builder() + } +} + +impl CountPullsByBuilder { + /// Create a new builder with all fields unset, using the default string type, if needed + pub fn new() -> Self { + CountPullsByBuilder { + _state: PhantomData, + _fields: (None,), + _type: PhantomData, + } + } +} + +impl CountPullsByBuilder { + /// Create a new builder with all fields unset + pub fn builder() -> Self { + CountPullsByBuilder { + _state: PhantomData, + _fields: (None,), + _type: PhantomData, + } + } +} + +impl CountPullsByBuilder +where + St: count_pulls_by_state::State, + St::Subject: count_pulls_by_state::IsUnset, +{ + /// Set the `subject` field (required) + pub fn subject( + mut self, + value: impl Into>, + ) -> CountPullsByBuilder, S> { + self._fields.0 = Option::Some(value.into()); + CountPullsByBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl CountPullsByBuilder +where + St: count_pulls_by_state::State, + St::Subject: count_pulls_by_state::IsSet, +{ + /// Build the final struct. + pub fn build(self) -> CountPullsBy { + CountPullsBy { + subject: self._fields.0.unwrap(), + } + } +} diff --git a/crates/jacquard-api/src/sh_tangled/repo/count_repos.rs b/crates/jacquard-api/src/sh_tangled/repo/count_repos.rs new file mode 100644 index 000000000..6369ae56c --- /dev/null +++ b/crates/jacquard-api/src/sh_tangled/repo/count_repos.rs @@ -0,0 +1,176 @@ +// @generated by jacquard-lexicon. DO NOT EDIT. +// +// Lexicon: sh.tangled.repo.countRepos +// +// 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::deps::smol_str::SmolStr; +use jacquard_common::types::string::Did; +use jacquard_common::types::value::Data; +use jacquard_common::{BosStr, DefaultStr, FromStaticStr}; +use jacquard_derive::IntoStatic; +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct CountRepos { + pub subject: Did, +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct CountReposOutput { + ///Total number of matching records. + pub count: i64, + ///Number of distinct authors among the matching records. + pub distinct_authors: i64, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +/** Response marker for the `sh.tangled.repo.countRepos` query. + +Implements `jacquard_common::xrpc::XrpcResp`; successful bodies decode as `Self::Output`, which is `CountReposOutput` for this endpoint.*/ +pub struct CountReposResponse; +impl jacquard_common::xrpc::XrpcResp for CountReposResponse { + const NSID: &'static str = "sh.tangled.repo.countRepos"; + const ENCODING: &'static str = "application/json"; + type Output = CountReposOutput; + type Err = jacquard_common::xrpc::GenericError; +} + +impl jacquard_common::xrpc::XrpcRequest for CountRepos { + const NSID: &'static str = "sh.tangled.repo.countRepos"; + const METHOD: jacquard_common::xrpc::XrpcMethod = jacquard_common::xrpc::XrpcMethod::Query; + type Response = CountReposResponse; +} + +/** Endpoint marker for the `sh.tangled.repo.countRepos` query. + +Path: `/xrpc/sh.tangled.repo.countRepos`. The request payload type is `CountRepos`; send that request with `jacquard::Client` or use this marker through lower-level `XrpcEndpoint` APIs.*/ +pub struct CountReposRequest; +impl jacquard_common::xrpc::XrpcEndpoint for CountReposRequest { + const PATH: &'static str = "/xrpc/sh.tangled.repo.countRepos"; + const METHOD: jacquard_common::xrpc::XrpcMethod = jacquard_common::xrpc::XrpcMethod::Query; + type Request = CountRepos; + type Response = CountReposResponse; +} + +pub mod count_repos_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 Subject; + } + /// Empty state - all required fields are unset + pub struct Empty(()); + impl sealed::Sealed for Empty {} + impl State for Empty { + type Subject = Unset; + } + ///State transition - sets the `subject` field to Set + pub struct SetSubject(PhantomData St>); + impl sealed::Sealed for SetSubject {} + impl State for SetSubject { + type Subject = Set; + } + /// Marker types for field names + #[allow(non_camel_case_types)] + pub mod members { + ///Marker type for the `subject` field + pub struct subject(()); + } +} + +/// Builder for constructing an instance of this type. +pub struct CountReposBuilder { + _state: PhantomData St>, + _fields: (Option>,), + _type: PhantomData S>, +} + +impl CountRepos { + /// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed + pub fn new() -> CountReposBuilder { + CountReposBuilder::new() + } +} + +impl CountRepos { + /// Create a new builder for this type + pub fn builder() -> CountReposBuilder { + CountReposBuilder::builder() + } +} + +impl CountReposBuilder { + /// Create a new builder with all fields unset, using the default string type, if needed + pub fn new() -> Self { + CountReposBuilder { + _state: PhantomData, + _fields: (None,), + _type: PhantomData, + } + } +} + +impl CountReposBuilder { + /// Create a new builder with all fields unset + pub fn builder() -> Self { + CountReposBuilder { + _state: PhantomData, + _fields: (None,), + _type: PhantomData, + } + } +} + +impl CountReposBuilder +where + St: count_repos_state::State, + St::Subject: count_repos_state::IsUnset, +{ + /// Set the `subject` field (required) + pub fn subject( + mut self, + value: impl Into>, + ) -> CountReposBuilder, S> { + self._fields.0 = Option::Some(value.into()); + CountReposBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl CountReposBuilder +where + St: count_repos_state::State, + St::Subject: count_repos_state::IsSet, +{ + /// Build the final struct. + pub fn build(self) -> CountRepos { + CountRepos { + subject: self._fields.0.unwrap(), + } + } +} diff --git a/crates/jacquard-api/src/sh_tangled/repo/create.rs b/crates/jacquard-api/src/sh_tangled/repo/create.rs index 93102bfd9..d8a525a02 100644 --- a/crates/jacquard-api/src/sh_tangled/repo/create.rs +++ b/crates/jacquard-api/src/sh_tangled/repo/create.rs @@ -11,13 +11,13 @@ use alloc::collections::BTreeMap; #[allow(unused_imports)] use core::marker::PhantomData; use jacquard_common::deps::smol_str::SmolStr; -use jacquard_common::types::string::Did; +use jacquard_common::types::string::{Did, RecordKey, Rkey}; use jacquard_common::types::value::Data; use jacquard_common::{BosStr, CowStr, DefaultStr, FromStaticStr}; use jacquard_derive::IntoStatic; use serde::{Deserialize, Serialize}; -#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic, Default)] +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] #[serde( rename_all = "camelCase", bound(deserialize = "S: Deserialize<'de> + BosStr") @@ -32,7 +32,7 @@ pub struct Create { #[serde(skip_serializing_if = "Option::is_none")] pub repo_did: Option>, ///Rkey of the repository record - pub rkey: S, + pub rkey: RecordKey>, ///A source URL to clone from, populate this when forking or importing a repository. #[serde(skip_serializing_if = "Option::is_none")] pub source: Option, @@ -46,6 +46,9 @@ pub struct Create { bound(deserialize = "S: Deserialize<'de> + BosStr") )] pub struct CreateOutput { + ///Multibase-encoded public signing key the knot holds for this repository + #[serde(skip_serializing_if = "Option::is_none")] + pub key: Option, #[serde(skip_serializing_if = "Option::is_none")] pub repo_did: Option>, #[serde(flatten, default, skip_serializing_if = "Option::is_none")] @@ -81,3 +84,200 @@ impl jacquard_common::xrpc::XrpcEndpoint for CreateRequest { type Request = Create; type Response = CreateResponse; } + +pub mod create_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 Name; + type Rkey; + } + /// Empty state - all required fields are unset + pub struct Empty(()); + impl sealed::Sealed for Empty {} + impl State for Empty { + type Name = Unset; + type Rkey = Unset; + } + ///State transition - sets the `name` field to Set + pub struct SetName(PhantomData St>); + impl sealed::Sealed for SetName {} + impl State for SetName { + type Name = Set; + type Rkey = St::Rkey; + } + ///State transition - sets the `rkey` field to Set + pub struct SetRkey(PhantomData St>); + impl sealed::Sealed for SetRkey {} + impl State for SetRkey { + type Name = St::Name; + type Rkey = Set; + } + /// Marker types for field names + #[allow(non_camel_case_types)] + pub mod members { + ///Marker type for the `name` field + pub struct name(()); + ///Marker type for the `rkey` field + pub struct rkey(()); + } +} + +/// Builder for constructing an instance of this type. +pub struct CreateBuilder { + _state: PhantomData St>, + _fields: ( + Option, + Option, + Option>, + Option>>, + Option, + ), + _type: PhantomData S>, +} + +impl Create { + /// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed + pub fn new() -> CreateBuilder { + CreateBuilder::new() + } +} + +impl Create { + /// Create a new builder for this type + pub fn builder() -> CreateBuilder { + CreateBuilder::builder() + } +} + +impl CreateBuilder { + /// Create a new builder with all fields unset, using the default string type, if needed + pub fn new() -> Self { + CreateBuilder { + _state: PhantomData, + _fields: (None, None, None, None, None), + _type: PhantomData, + } + } +} + +impl CreateBuilder { + /// Create a new builder with all fields unset + pub fn builder() -> Self { + CreateBuilder { + _state: PhantomData, + _fields: (None, None, None, None, None), + _type: PhantomData, + } + } +} + +impl CreateBuilder { + /// Set the `defaultBranch` field (optional) + pub fn default_branch(mut self, value: impl Into>) -> Self { + self._fields.0 = value.into(); + self + } + /// Set the `defaultBranch` field to an Option value (optional) + pub fn maybe_default_branch(mut self, value: Option) -> Self { + self._fields.0 = value; + self + } +} + +impl CreateBuilder +where + St: create_state::State, + St::Name: create_state::IsUnset, +{ + /// Set the `name` field (required) + pub fn name(mut self, value: impl Into) -> CreateBuilder, S> { + self._fields.1 = Option::Some(value.into()); + CreateBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl CreateBuilder { + /// Set the `repoDid` field (optional) + pub fn repo_did(mut self, value: impl Into>>) -> Self { + self._fields.2 = value.into(); + self + } + /// Set the `repoDid` field to an Option value (optional) + pub fn maybe_repo_did(mut self, value: Option>) -> Self { + self._fields.2 = value; + self + } +} + +impl CreateBuilder +where + St: create_state::State, + St::Rkey: create_state::IsUnset, +{ + /// Set the `rkey` field (required) + pub fn rkey( + mut self, + value: impl Into>>, + ) -> CreateBuilder, S> { + self._fields.3 = Option::Some(value.into()); + CreateBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl CreateBuilder { + /// Set the `source` field (optional) + pub fn source(mut self, value: impl Into>) -> Self { + self._fields.4 = value.into(); + self + } + /// Set the `source` field to an Option value (optional) + pub fn maybe_source(mut self, value: Option) -> Self { + self._fields.4 = value; + self + } +} + +impl CreateBuilder +where + St: create_state::State, + St::Name: create_state::IsSet, + St::Rkey: create_state::IsSet, +{ + /// Build the final struct. + pub fn build(self) -> Create { + Create { + default_branch: self._fields.0, + name: self._fields.1.unwrap(), + repo_did: self._fields.2, + rkey: self._fields.3.unwrap(), + source: self._fields.4, + extra_data: Default::default(), + } + } + /// Build the final struct with custom extra_data. + pub fn build_with_data(self, extra_data: BTreeMap>) -> Create { + Create { + default_branch: self._fields.0, + name: self._fields.1.unwrap(), + repo_did: self._fields.2, + rkey: self._fields.3.unwrap(), + source: self._fields.4, + extra_data: Some(extra_data), + } + } +} diff --git a/crates/jacquard-api/src/sh_tangled/repo/delete.rs b/crates/jacquard-api/src/sh_tangled/repo/delete.rs index 305455f69..0188aaaa2 100644 --- a/crates/jacquard-api/src/sh_tangled/repo/delete.rs +++ b/crates/jacquard-api/src/sh_tangled/repo/delete.rs @@ -11,7 +11,7 @@ use alloc::collections::BTreeMap; #[allow(unused_imports)] use core::marker::PhantomData; use jacquard_common::deps::smol_str::SmolStr; -use jacquard_common::types::string::Did; +use jacquard_common::types::string::{Did, RecordKey, Rkey}; use jacquard_common::types::value::Data; use jacquard_common::{BosStr, CowStr, DefaultStr, FromStaticStr}; use jacquard_derive::IntoStatic; @@ -23,12 +23,20 @@ use serde::{Deserialize, Serialize}; bound(deserialize = "S: Deserialize<'de> + BosStr") )] pub struct Delete { - ///DID of the repository owner - pub did: Did, - ///Name of the repository to delete - pub name: S, - ///Rkey of the repository record - pub rkey: S, + ///DID of the repository owner. A knot without the repo-did-input capability reads this and name in place of repo. + #[serde(skip_serializing_if = "Option::is_none")] + pub did: Option>, + ///Admin-only. Delete even though the repository record still exists on the owner's PDS. + #[serde(skip_serializing_if = "Option::is_none")] + pub force: Option, + ///Name of the repository to delete. A knot without the repo-did-input capability reads this and DID in place of repo. + #[serde(skip_serializing_if = "Option::is_none")] + pub name: Option, + ///DID of the repository to delete + pub repo: Did, + ///Rkey of the repository record. A knot without the repo-did-input capability checks this against the owner's PDS. + #[serde(skip_serializing_if = "Option::is_none")] + pub rkey: Option>>, #[serde(flatten, default, skip_serializing_if = "Option::is_none")] pub extra_data: Option>>, } @@ -73,58 +81,38 @@ pub mod delete_state { } /// State trait tracking which required fields have been set pub trait State: sealed::Sealed { - type Did; - type Name; - type Rkey; + type Repo; } /// Empty state - all required fields are unset pub struct Empty(()); impl sealed::Sealed for Empty {} impl State for Empty { - type Did = Unset; - type Name = Unset; - type Rkey = Unset; - } - ///State transition - sets the `did` field to Set - pub struct SetDid(PhantomData St>); - impl sealed::Sealed for SetDid {} - impl State for SetDid { - type Did = Set; - type Name = St::Name; - type Rkey = St::Rkey; - } - ///State transition - sets the `name` field to Set - pub struct SetName(PhantomData St>); - impl sealed::Sealed for SetName {} - impl State for SetName { - type Did = St::Did; - type Name = Set; - type Rkey = St::Rkey; - } - ///State transition - sets the `rkey` field to Set - pub struct SetRkey(PhantomData St>); - impl sealed::Sealed for SetRkey {} - impl State for SetRkey { - type Did = St::Did; - type Name = St::Name; - type Rkey = Set; + type Repo = Unset; + } + ///State transition - sets the `repo` field to Set + pub struct SetRepo(PhantomData St>); + impl sealed::Sealed for SetRepo {} + impl State for SetRepo { + type Repo = Set; } /// Marker types for field names #[allow(non_camel_case_types)] pub mod members { - ///Marker type for the `did` field - pub struct did(()); - ///Marker type for the `name` field - pub struct name(()); - ///Marker type for the `rkey` field - pub struct rkey(()); + ///Marker type for the `repo` field + pub struct repo(()); } } /// Builder for constructing an instance of this type. pub struct DeleteBuilder { _state: PhantomData St>, - _fields: (Option>, Option, Option), + _fields: ( + Option>, + Option, + Option, + Option>, + Option>>, + ), _type: PhantomData S>, } @@ -147,7 +135,7 @@ impl DeleteBuilder { pub fn new() -> Self { DeleteBuilder { _state: PhantomData, - _fields: (None, None, None), + _fields: (None, None, None, None, None), _type: PhantomData, } } @@ -158,52 +146,59 @@ impl DeleteBuilder { pub fn builder() -> Self { DeleteBuilder { _state: PhantomData, - _fields: (None, None, None), + _fields: (None, None, None, None, None), _type: PhantomData, } } } -impl DeleteBuilder -where - St: delete_state::State, - St::Did: delete_state::IsUnset, -{ - /// Set the `did` field (required) - pub fn did(mut self, value: impl Into>) -> DeleteBuilder, S> { - self._fields.0 = Option::Some(value.into()); - DeleteBuilder { - _state: PhantomData, - _fields: self._fields, - _type: PhantomData, - } +impl DeleteBuilder { + /// Set the `did` field (optional) + pub fn did(mut self, value: impl Into>>) -> Self { + self._fields.0 = value.into(); + self + } + /// Set the `did` field to an Option value (optional) + pub fn maybe_did(mut self, value: Option>) -> Self { + self._fields.0 = value; + self } } -impl DeleteBuilder -where - St: delete_state::State, - St::Name: delete_state::IsUnset, -{ - /// Set the `name` field (required) - pub fn name(mut self, value: impl Into) -> DeleteBuilder, S> { - self._fields.1 = Option::Some(value.into()); - DeleteBuilder { - _state: PhantomData, - _fields: self._fields, - _type: PhantomData, - } +impl DeleteBuilder { + /// Set the `force` field (optional) + pub fn force(mut self, value: impl Into>) -> Self { + self._fields.1 = value.into(); + self + } + /// Set the `force` field to an Option value (optional) + pub fn maybe_force(mut self, value: Option) -> Self { + self._fields.1 = value; + self + } +} + +impl DeleteBuilder { + /// Set the `name` field (optional) + pub fn name(mut self, value: impl Into>) -> Self { + self._fields.2 = value.into(); + self + } + /// Set the `name` field to an Option value (optional) + pub fn maybe_name(mut self, value: Option) -> Self { + self._fields.2 = value; + self } } impl DeleteBuilder where St: delete_state::State, - St::Rkey: delete_state::IsUnset, + St::Repo: delete_state::IsUnset, { - /// Set the `rkey` field (required) - pub fn rkey(mut self, value: impl Into) -> DeleteBuilder, S> { - self._fields.2 = Option::Some(value.into()); + /// Set the `repo` field (required) + pub fn repo(mut self, value: impl Into>) -> DeleteBuilder, S> { + self._fields.3 = Option::Some(value.into()); DeleteBuilder { _state: PhantomData, _fields: self._fields, @@ -212,28 +207,43 @@ where } } +impl DeleteBuilder { + /// Set the `rkey` field (optional) + pub fn rkey(mut self, value: impl Into>>>) -> Self { + self._fields.4 = value.into(); + self + } + /// Set the `rkey` field to an Option value (optional) + pub fn maybe_rkey(mut self, value: Option>>) -> Self { + self._fields.4 = value; + self + } +} + impl DeleteBuilder where St: delete_state::State, - St::Did: delete_state::IsSet, - St::Name: delete_state::IsSet, - St::Rkey: delete_state::IsSet, + St::Repo: delete_state::IsSet, { /// Build the final struct. pub fn build(self) -> Delete { Delete { - did: self._fields.0.unwrap(), - name: self._fields.1.unwrap(), - rkey: self._fields.2.unwrap(), + did: self._fields.0, + force: self._fields.1, + name: self._fields.2, + repo: self._fields.3.unwrap(), + rkey: self._fields.4, extra_data: Default::default(), } } /// Build the final struct with custom extra_data. pub fn build_with_data(self, extra_data: BTreeMap>) -> Delete { Delete { - did: self._fields.0.unwrap(), - name: self._fields.1.unwrap(), - rkey: self._fields.2.unwrap(), + did: self._fields.0, + force: self._fields.1, + name: self._fields.2, + repo: self._fields.3.unwrap(), + rkey: self._fields.4, extra_data: Some(extra_data), } } diff --git a/crates/jacquard-api/src/sh_tangled/repo/delete_branch.rs b/crates/jacquard-api/src/sh_tangled/repo/delete_branch.rs index 3d25c8799..93311e05b 100644 --- a/crates/jacquard-api/src/sh_tangled/repo/delete_branch.rs +++ b/crates/jacquard-api/src/sh_tangled/repo/delete_branch.rs @@ -11,7 +11,7 @@ use alloc::collections::BTreeMap; #[allow(unused_imports)] use core::marker::PhantomData; use jacquard_common::deps::smol_str::SmolStr; -use jacquard_common::types::string::AtUri; +use jacquard_common::types::string::Did; use jacquard_common::types::value::Data; use jacquard_common::{BosStr, CowStr, DefaultStr, FromStaticStr}; use jacquard_derive::IntoStatic; @@ -24,7 +24,8 @@ use serde::{Deserialize, Serialize}; )] pub struct DeleteBranch { pub branch: S, - pub repo: AtUri, + ///DID of the repository + pub repo: Did, #[serde(flatten, default, skip_serializing_if = "Option::is_none")] pub extra_data: Option>>, } @@ -106,7 +107,7 @@ pub mod delete_branch_state { /// Builder for constructing an instance of this type. pub struct DeleteBranchBuilder { _state: PhantomData St>, - _fields: (Option, Option>), + _fields: (Option, Option>), _type: PhantomData S>, } @@ -173,7 +174,7 @@ where /// Set the `repo` field (required) pub fn repo( mut self, - value: impl Into>, + value: impl Into>, ) -> DeleteBranchBuilder, S> { self._fields.1 = Option::Some(value.into()); DeleteBranchBuilder { diff --git a/crates/jacquard-api/src/sh_tangled/repo/fork_sync.rs b/crates/jacquard-api/src/sh_tangled/repo/fork_sync.rs index 0d0666364..b5ac8ad01 100644 --- a/crates/jacquard-api/src/sh_tangled/repo/fork_sync.rs +++ b/crates/jacquard-api/src/sh_tangled/repo/fork_sync.rs @@ -25,12 +25,17 @@ use serde::{Deserialize, Serialize}; pub struct ForkSync { ///Branch to sync pub branch: S, - ///DID of the fork owner - pub did: Did, - ///Name of the forked repository - pub name: S, - ///AT-URI of the source repository - pub source: AtUri, + ///DID of the fork owner. A knot without the repo-did-input capability reads this and name in place of repo. + #[serde(skip_serializing_if = "Option::is_none")] + pub did: Option>, + ///Name of the forked repository. A knot without the repo-did-input capability reads this and DID in place of repo. + #[serde(skip_serializing_if = "Option::is_none")] + pub name: Option, + ///DID of the fork to sync + pub repo: Did, + ///AT-URI of the source repository. A knot without the repo-did-input capability requires this field without reading it. + #[serde(skip_serializing_if = "Option::is_none")] + pub source: Option>, #[serde(flatten, default, skip_serializing_if = "Option::is_none")] pub extra_data: Option>>, } @@ -76,73 +81,49 @@ pub mod fork_sync_state { /// State trait tracking which required fields have been set pub trait State: sealed::Sealed { type Branch; - type Did; - type Name; - type Source; + type Repo; } /// Empty state - all required fields are unset pub struct Empty(()); impl sealed::Sealed for Empty {} impl State for Empty { type Branch = Unset; - type Did = Unset; - type Name = Unset; - type Source = Unset; + type Repo = Unset; } ///State transition - sets the `branch` field to Set pub struct SetBranch(PhantomData St>); impl sealed::Sealed for SetBranch {} impl State for SetBranch { type Branch = Set; - type Did = St::Did; - type Name = St::Name; - type Source = St::Source; + type Repo = St::Repo; } - ///State transition - sets the `did` field to Set - pub struct SetDid(PhantomData St>); - impl sealed::Sealed for SetDid {} - impl State for SetDid { + ///State transition - sets the `repo` field to Set + pub struct SetRepo(PhantomData St>); + impl sealed::Sealed for SetRepo {} + impl State for SetRepo { type Branch = St::Branch; - type Did = Set; - type Name = St::Name; - type Source = St::Source; - } - ///State transition - sets the `name` field to Set - pub struct SetName(PhantomData St>); - impl sealed::Sealed for SetName {} - impl State for SetName { - type Branch = St::Branch; - type Did = St::Did; - type Name = Set; - type Source = St::Source; - } - ///State transition - sets the `source` field to Set - pub struct SetSource(PhantomData St>); - impl sealed::Sealed for SetSource {} - impl State for SetSource { - type Branch = St::Branch; - type Did = St::Did; - type Name = St::Name; - type Source = Set; + type Repo = Set; } /// Marker types for field names #[allow(non_camel_case_types)] pub mod members { ///Marker type for the `branch` field pub struct branch(()); - ///Marker type for the `did` field - pub struct did(()); - ///Marker type for the `name` field - pub struct name(()); - ///Marker type for the `source` field - pub struct source(()); + ///Marker type for the `repo` field + pub struct repo(()); } } /// Builder for constructing an instance of this type. pub struct ForkSyncBuilder { _state: PhantomData St>, - _fields: (Option, Option>, Option, Option>), + _fields: ( + Option, + Option>, + Option, + Option>, + Option>, + ), _type: PhantomData S>, } @@ -165,7 +146,7 @@ impl ForkSyncBuilder { pub fn new() -> Self { ForkSyncBuilder { _state: PhantomData, - _fields: (None, None, None, None), + _fields: (None, None, None, None, None), _type: PhantomData, } } @@ -176,7 +157,7 @@ impl ForkSyncBuilder { pub fn builder() -> Self { ForkSyncBuilder { _state: PhantomData, - _fields: (None, None, None, None), + _fields: (None, None, None, None, None), _type: PhantomData, } } @@ -201,51 +182,42 @@ where } } -impl ForkSyncBuilder -where - St: fork_sync_state::State, - St::Did: fork_sync_state::IsUnset, -{ - /// Set the `did` field (required) - pub fn did( - mut self, - value: impl Into>, - ) -> ForkSyncBuilder, S> { - self._fields.1 = Option::Some(value.into()); - ForkSyncBuilder { - _state: PhantomData, - _fields: self._fields, - _type: PhantomData, - } +impl ForkSyncBuilder { + /// Set the `did` field (optional) + pub fn did(mut self, value: impl Into>>) -> Self { + self._fields.1 = value.into(); + self + } + /// Set the `did` field to an Option value (optional) + pub fn maybe_did(mut self, value: Option>) -> Self { + self._fields.1 = value; + self } } -impl ForkSyncBuilder -where - St: fork_sync_state::State, - St::Name: fork_sync_state::IsUnset, -{ - /// Set the `name` field (required) - pub fn name(mut self, value: impl Into) -> ForkSyncBuilder, S> { - self._fields.2 = Option::Some(value.into()); - ForkSyncBuilder { - _state: PhantomData, - _fields: self._fields, - _type: PhantomData, - } +impl ForkSyncBuilder { + /// Set the `name` field (optional) + pub fn name(mut self, value: impl Into>) -> Self { + self._fields.2 = value.into(); + self + } + /// Set the `name` field to an Option value (optional) + pub fn maybe_name(mut self, value: Option) -> Self { + self._fields.2 = value; + self } } impl ForkSyncBuilder where St: fork_sync_state::State, - St::Source: fork_sync_state::IsUnset, + St::Repo: fork_sync_state::IsUnset, { - /// Set the `source` field (required) - pub fn source( + /// Set the `repo` field (required) + pub fn repo( mut self, - value: impl Into>, - ) -> ForkSyncBuilder, S> { + value: impl Into>, + ) -> ForkSyncBuilder, S> { self._fields.3 = Option::Some(value.into()); ForkSyncBuilder { _state: PhantomData, @@ -255,21 +227,33 @@ where } } +impl ForkSyncBuilder { + /// Set the `source` field (optional) + pub fn source(mut self, value: impl Into>>) -> Self { + self._fields.4 = value.into(); + self + } + /// Set the `source` field to an Option value (optional) + pub fn maybe_source(mut self, value: Option>) -> Self { + self._fields.4 = value; + self + } +} + impl ForkSyncBuilder where St: fork_sync_state::State, St::Branch: fork_sync_state::IsSet, - St::Did: fork_sync_state::IsSet, - St::Name: fork_sync_state::IsSet, - St::Source: fork_sync_state::IsSet, + St::Repo: fork_sync_state::IsSet, { /// Build the final struct. pub fn build(self) -> ForkSync { ForkSync { branch: self._fields.0.unwrap(), - did: self._fields.1.unwrap(), - name: self._fields.2.unwrap(), - source: self._fields.3.unwrap(), + did: self._fields.1, + name: self._fields.2, + repo: self._fields.3.unwrap(), + source: self._fields.4, extra_data: Default::default(), } } @@ -277,9 +261,10 @@ where pub fn build_with_data(self, extra_data: BTreeMap>) -> ForkSync { ForkSync { branch: self._fields.0.unwrap(), - did: self._fields.1.unwrap(), - name: self._fields.2.unwrap(), - source: self._fields.3.unwrap(), + did: self._fields.1, + name: self._fields.2, + repo: self._fields.3.unwrap(), + source: self._fields.4, extra_data: Some(extra_data), } } diff --git a/crates/jacquard-api/src/sh_tangled/repo/get_issue.rs b/crates/jacquard-api/src/sh_tangled/repo/get_issue.rs new file mode 100644 index 000000000..17188382c --- /dev/null +++ b/crates/jacquard-api/src/sh_tangled/repo/get_issue.rs @@ -0,0 +1,177 @@ +// @generated by jacquard-lexicon. DO NOT EDIT. +// +// Lexicon: sh.tangled.repo.getIssue +// +// 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::deps::smol_str::SmolStr; +use jacquard_common::types::string::{AtUri, Cid}; +use jacquard_common::types::value::Data; +use jacquard_common::{BosStr, DefaultStr, FromStaticStr}; +use jacquard_derive::IntoStatic; +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct GetIssue { + pub issue: AtUri, +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct GetIssueOutput { + #[serde(skip_serializing_if = "Option::is_none")] + pub cid: Option>, + pub uri: AtUri, + ///Embedded sh.tangled.repo.issue record. + pub value: Data, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +/** Response marker for the `sh.tangled.repo.getIssue` query. + +Implements `jacquard_common::xrpc::XrpcResp`; successful bodies decode as `Self::Output`, which is `GetIssueOutput` for this endpoint.*/ +pub struct GetIssueResponse; +impl jacquard_common::xrpc::XrpcResp for GetIssueResponse { + const NSID: &'static str = "sh.tangled.repo.getIssue"; + const ENCODING: &'static str = "application/json"; + type Output = GetIssueOutput; + type Err = jacquard_common::xrpc::GenericError; +} + +impl jacquard_common::xrpc::XrpcRequest for GetIssue { + const NSID: &'static str = "sh.tangled.repo.getIssue"; + const METHOD: jacquard_common::xrpc::XrpcMethod = jacquard_common::xrpc::XrpcMethod::Query; + type Response = GetIssueResponse; +} + +/** Endpoint marker for the `sh.tangled.repo.getIssue` query. + +Path: `/xrpc/sh.tangled.repo.getIssue`. The request payload type is `GetIssue`; send that request with `jacquard::Client` or use this marker through lower-level `XrpcEndpoint` APIs.*/ +pub struct GetIssueRequest; +impl jacquard_common::xrpc::XrpcEndpoint for GetIssueRequest { + const PATH: &'static str = "/xrpc/sh.tangled.repo.getIssue"; + const METHOD: jacquard_common::xrpc::XrpcMethod = jacquard_common::xrpc::XrpcMethod::Query; + type Request = GetIssue; + type Response = GetIssueResponse; +} + +pub mod get_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 Issue; + } + /// Empty state - all required fields are unset + pub struct Empty(()); + impl sealed::Sealed for Empty {} + impl State for Empty { + type Issue = Unset; + } + ///State transition - sets the `issue` field to Set + pub struct SetIssue(PhantomData St>); + impl sealed::Sealed for SetIssue {} + impl State for SetIssue { + type Issue = Set; + } + /// Marker types for field names + #[allow(non_camel_case_types)] + pub mod members { + ///Marker type for the `issue` field + pub struct issue(()); + } +} + +/// Builder for constructing an instance of this type. +pub struct GetIssueBuilder { + _state: PhantomData St>, + _fields: (Option>,), + _type: PhantomData S>, +} + +impl GetIssue { + /// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed + pub fn new() -> GetIssueBuilder { + GetIssueBuilder::new() + } +} + +impl GetIssue { + /// Create a new builder for this type + pub fn builder() -> GetIssueBuilder { + GetIssueBuilder::builder() + } +} + +impl GetIssueBuilder { + /// Create a new builder with all fields unset, using the default string type, if needed + pub fn new() -> Self { + GetIssueBuilder { + _state: PhantomData, + _fields: (None,), + _type: PhantomData, + } + } +} + +impl GetIssueBuilder { + /// Create a new builder with all fields unset + pub fn builder() -> Self { + GetIssueBuilder { + _state: PhantomData, + _fields: (None,), + _type: PhantomData, + } + } +} + +impl GetIssueBuilder +where + St: get_issue_state::State, + St::Issue: get_issue_state::IsUnset, +{ + /// Set the `issue` field (required) + pub fn issue( + mut self, + value: impl Into>, + ) -> GetIssueBuilder, S> { + self._fields.0 = Option::Some(value.into()); + GetIssueBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl GetIssueBuilder +where + St: get_issue_state::State, + St::Issue: get_issue_state::IsSet, +{ + /// Build the final struct. + pub fn build(self) -> GetIssue { + GetIssue { + issue: self._fields.0.unwrap(), + } + } +} diff --git a/crates/jacquard-api/src/sh_tangled/repo/get_issues.rs b/crates/jacquard-api/src/sh_tangled/repo/get_issues.rs new file mode 100644 index 000000000..9be9d97c5 --- /dev/null +++ b/crates/jacquard-api/src/sh_tangled/repo/get_issues.rs @@ -0,0 +1,453 @@ +// @generated by jacquard-lexicon. DO NOT EDIT. +// +// Lexicon: sh.tangled.repo.getIssues +// +// 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, DefaultStr, FromStaticStr}; + +#[allow(unused_imports)] +use jacquard_common::deps::codegen::unicode_segmentation::UnicodeSegmentation; +use jacquard_common::deps::smol_str::SmolStr; +use jacquard_common::types::string::{AtUri, Cid}; +use jacquard_common::types::value::Data; +use jacquard_derive::IntoStatic; +use jacquard_lexicon::lexicon::LexiconDoc; +use jacquard_lexicon::schema::LexiconSchema; + +use crate::sh_tangled::repo::get_issues; +#[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", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct GetIssues { + pub issues: Vec>, +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct GetIssuesOutput { + pub items: Vec>, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct RecordView { + #[serde(skip_serializing_if = "Option::is_none")] + pub cid: Option>, + pub uri: AtUri, + ///Embedded sh.tangled.repo.issue record. + pub value: Data, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +/** Response marker for the `sh.tangled.repo.getIssues` query. + +Implements `jacquard_common::xrpc::XrpcResp`; successful bodies decode as `Self::Output`, which is `GetIssuesOutput` for this endpoint.*/ +pub struct GetIssuesResponse; +impl jacquard_common::xrpc::XrpcResp for GetIssuesResponse { + const NSID: &'static str = "sh.tangled.repo.getIssues"; + const ENCODING: &'static str = "application/json"; + type Output = GetIssuesOutput; + type Err = jacquard_common::xrpc::GenericError; +} + +impl jacquard_common::xrpc::XrpcRequest for GetIssues { + const NSID: &'static str = "sh.tangled.repo.getIssues"; + const METHOD: jacquard_common::xrpc::XrpcMethod = jacquard_common::xrpc::XrpcMethod::Query; + type Response = GetIssuesResponse; +} + +/** Endpoint marker for the `sh.tangled.repo.getIssues` query. + +Path: `/xrpc/sh.tangled.repo.getIssues`. The request payload type is `GetIssues`; send that request with `jacquard::Client` or use this marker through lower-level `XrpcEndpoint` APIs.*/ +pub struct GetIssuesRequest; +impl jacquard_common::xrpc::XrpcEndpoint for GetIssuesRequest { + const PATH: &'static str = "/xrpc/sh.tangled.repo.getIssues"; + const METHOD: jacquard_common::xrpc::XrpcMethod = jacquard_common::xrpc::XrpcMethod::Query; + type Request = GetIssues; + type Response = GetIssuesResponse; +} + +impl LexiconSchema for RecordView { + fn nsid() -> &'static str { + "sh.tangled.repo.getIssues" + } + fn def_name() -> &'static str { + "recordView" + } + fn lexicon_doc() -> LexiconDoc<'static> { + lexicon_doc_sh_tangled_repo_getIssues() + } + fn validate(&self) -> Result<(), ConstraintError> { + Ok(()) + } +} + +pub mod get_issues_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 Issues; + } + /// Empty state - all required fields are unset + pub struct Empty(()); + impl sealed::Sealed for Empty {} + impl State for Empty { + type Issues = Unset; + } + ///State transition - sets the `issues` field to Set + pub struct SetIssues(PhantomData St>); + impl sealed::Sealed for SetIssues {} + impl State for SetIssues { + type Issues = Set; + } + /// Marker types for field names + #[allow(non_camel_case_types)] + pub mod members { + ///Marker type for the `issues` field + pub struct issues(()); + } +} + +/// Builder for constructing an instance of this type. +pub struct GetIssuesBuilder { + _state: PhantomData St>, + _fields: (Option>>,), + _type: PhantomData S>, +} + +impl GetIssues { + /// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed + pub fn new() -> GetIssuesBuilder { + GetIssuesBuilder::new() + } +} + +impl GetIssues { + /// Create a new builder for this type + pub fn builder() -> GetIssuesBuilder { + GetIssuesBuilder::builder() + } +} + +impl GetIssuesBuilder { + /// Create a new builder with all fields unset, using the default string type, if needed + pub fn new() -> Self { + GetIssuesBuilder { + _state: PhantomData, + _fields: (None,), + _type: PhantomData, + } + } +} + +impl GetIssuesBuilder { + /// Create a new builder with all fields unset + pub fn builder() -> Self { + GetIssuesBuilder { + _state: PhantomData, + _fields: (None,), + _type: PhantomData, + } + } +} + +impl GetIssuesBuilder +where + St: get_issues_state::State, + St::Issues: get_issues_state::IsUnset, +{ + /// Set the `issues` field (required) + pub fn issues( + mut self, + value: impl Into>>, + ) -> GetIssuesBuilder, S> { + self._fields.0 = Option::Some(value.into()); + GetIssuesBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl GetIssuesBuilder +where + St: get_issues_state::State, + St::Issues: get_issues_state::IsSet, +{ + /// Build the final struct. + pub fn build(self) -> GetIssues { + GetIssues { + issues: self._fields.0.unwrap(), + } + } +} + +pub mod record_view_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 Uri; + type Value; + } + /// Empty state - all required fields are unset + pub struct Empty(()); + impl sealed::Sealed for Empty {} + impl State for Empty { + type Uri = Unset; + type Value = Unset; + } + ///State transition - sets the `uri` field to Set + pub struct SetUri(PhantomData St>); + impl sealed::Sealed for SetUri {} + impl State for SetUri { + type Uri = Set; + type Value = St::Value; + } + ///State transition - sets the `value` field to Set + pub struct SetValue(PhantomData St>); + impl sealed::Sealed for SetValue {} + impl State for SetValue { + type Uri = St::Uri; + type Value = Set; + } + /// Marker types for field names + #[allow(non_camel_case_types)] + pub mod members { + ///Marker type for the `uri` field + pub struct uri(()); + ///Marker type for the `value` field + pub struct value(()); + } +} + +/// Builder for constructing an instance of this type. +pub struct RecordViewBuilder { + _state: PhantomData St>, + _fields: (Option>, Option>, Option>), + _type: PhantomData S>, +} + +impl RecordView { + /// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed + pub fn new() -> RecordViewBuilder { + RecordViewBuilder::new() + } +} + +impl RecordView { + /// Create a new builder for this type + pub fn builder() -> RecordViewBuilder { + RecordViewBuilder::builder() + } +} + +impl RecordViewBuilder { + /// Create a new builder with all fields unset, using the default string type, if needed + pub fn new() -> Self { + RecordViewBuilder { + _state: PhantomData, + _fields: (None, None, None), + _type: PhantomData, + } + } +} + +impl RecordViewBuilder { + /// Create a new builder with all fields unset + pub fn builder() -> Self { + RecordViewBuilder { + _state: PhantomData, + _fields: (None, None, None), + _type: PhantomData, + } + } +} + +impl RecordViewBuilder { + /// Set the `cid` field (optional) + pub fn cid(mut self, value: impl Into>>) -> Self { + self._fields.0 = value.into(); + self + } + /// Set the `cid` field to an Option value (optional) + pub fn maybe_cid(mut self, value: Option>) -> Self { + self._fields.0 = value; + self + } +} + +impl RecordViewBuilder +where + St: record_view_state::State, + St::Uri: record_view_state::IsUnset, +{ + /// Set the `uri` field (required) + pub fn uri( + mut self, + value: impl Into>, + ) -> RecordViewBuilder, S> { + self._fields.1 = Option::Some(value.into()); + RecordViewBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl RecordViewBuilder +where + St: record_view_state::State, + St::Value: record_view_state::IsUnset, +{ + /// Set the `value` field (required) + pub fn value( + mut self, + value: impl Into>, + ) -> RecordViewBuilder, S> { + self._fields.2 = Option::Some(value.into()); + RecordViewBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl RecordViewBuilder +where + St: record_view_state::State, + St::Uri: record_view_state::IsSet, + St::Value: record_view_state::IsSet, +{ + /// Build the final struct. + pub fn build(self) -> RecordView { + RecordView { + cid: self._fields.0, + uri: self._fields.1.unwrap(), + value: 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>) -> RecordView { + RecordView { + cid: self._fields.0, + uri: self._fields.1.unwrap(), + value: self._fields.2.unwrap(), + extra_data: Some(extra_data), + } + } +} + +fn lexicon_doc_sh_tangled_repo_getIssues() -> 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.getIssues"), + defs: { + let mut map = BTreeMap::new(); + map.insert( + SmolStr::new_static("main"), + LexUserType::XrpcQuery(LexXrpcQuery { + parameters: Some(LexXrpcQueryParameter::Params(LexXrpcParameters { + required: Some(vec![SmolStr::new_static("issues")]), + properties: { + #[allow(unused_mut)] + let mut map = BTreeMap::new(); + map.insert( + SmolStr::new_static("issues"), + LexXrpcParametersProperty::Array(LexPrimitiveArray { + items: LexPrimitiveArrayItem::String(LexString { + format: Some(LexStringFormat::AtUri), + ..Default::default() + }), + max_length: Some(50usize), + ..Default::default() + }), + ); + map + }, + ..Default::default() + })), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("recordView"), + LexUserType::Object(LexObject { + required: Some(vec![ + SmolStr::new_static("uri"), + SmolStr::new_static("value"), + ]), + properties: { + #[allow(unused_mut)] + let mut map = BTreeMap::new(); + map.insert( + SmolStr::new_static("cid"), + LexObjectProperty::String(LexString { + format: Some(LexStringFormat::Cid), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("uri"), + LexObjectProperty::String(LexString { + format: Some(LexStringFormat::AtUri), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("value"), + LexObjectProperty::Unknown(LexUnknown { + ..Default::default() + }), + ); + map + }, + ..Default::default() + }), + ); + map + }, + ..Default::default() + } +} diff --git a/crates/jacquard-api/src/sh_tangled/repo/get_pull.rs b/crates/jacquard-api/src/sh_tangled/repo/get_pull.rs new file mode 100644 index 000000000..4f9431ca4 --- /dev/null +++ b/crates/jacquard-api/src/sh_tangled/repo/get_pull.rs @@ -0,0 +1,177 @@ +// @generated by jacquard-lexicon. DO NOT EDIT. +// +// Lexicon: sh.tangled.repo.getPull +// +// 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::deps::smol_str::SmolStr; +use jacquard_common::types::string::{AtUri, Cid}; +use jacquard_common::types::value::Data; +use jacquard_common::{BosStr, DefaultStr, FromStaticStr}; +use jacquard_derive::IntoStatic; +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct GetPull { + pub pull: AtUri, +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct GetPullOutput { + #[serde(skip_serializing_if = "Option::is_none")] + pub cid: Option>, + pub uri: AtUri, + ///Embedded sh.tangled.repo.pull record. + pub value: Data, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +/** Response marker for the `sh.tangled.repo.getPull` query. + +Implements `jacquard_common::xrpc::XrpcResp`; successful bodies decode as `Self::Output`, which is `GetPullOutput` for this endpoint.*/ +pub struct GetPullResponse; +impl jacquard_common::xrpc::XrpcResp for GetPullResponse { + const NSID: &'static str = "sh.tangled.repo.getPull"; + const ENCODING: &'static str = "application/json"; + type Output = GetPullOutput; + type Err = jacquard_common::xrpc::GenericError; +} + +impl jacquard_common::xrpc::XrpcRequest for GetPull { + const NSID: &'static str = "sh.tangled.repo.getPull"; + const METHOD: jacquard_common::xrpc::XrpcMethod = jacquard_common::xrpc::XrpcMethod::Query; + type Response = GetPullResponse; +} + +/** Endpoint marker for the `sh.tangled.repo.getPull` query. + +Path: `/xrpc/sh.tangled.repo.getPull`. The request payload type is `GetPull`; send that request with `jacquard::Client` or use this marker through lower-level `XrpcEndpoint` APIs.*/ +pub struct GetPullRequest; +impl jacquard_common::xrpc::XrpcEndpoint for GetPullRequest { + const PATH: &'static str = "/xrpc/sh.tangled.repo.getPull"; + const METHOD: jacquard_common::xrpc::XrpcMethod = jacquard_common::xrpc::XrpcMethod::Query; + type Request = GetPull; + type Response = GetPullResponse; +} + +pub mod get_pull_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 Pull; + } + /// Empty state - all required fields are unset + pub struct Empty(()); + impl sealed::Sealed for Empty {} + impl State for Empty { + type Pull = Unset; + } + ///State transition - sets the `pull` field to Set + pub struct SetPull(PhantomData St>); + impl sealed::Sealed for SetPull {} + impl State for SetPull { + type Pull = Set; + } + /// Marker types for field names + #[allow(non_camel_case_types)] + pub mod members { + ///Marker type for the `pull` field + pub struct pull(()); + } +} + +/// Builder for constructing an instance of this type. +pub struct GetPullBuilder { + _state: PhantomData St>, + _fields: (Option>,), + _type: PhantomData S>, +} + +impl GetPull { + /// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed + pub fn new() -> GetPullBuilder { + GetPullBuilder::new() + } +} + +impl GetPull { + /// Create a new builder for this type + pub fn builder() -> GetPullBuilder { + GetPullBuilder::builder() + } +} + +impl GetPullBuilder { + /// Create a new builder with all fields unset, using the default string type, if needed + pub fn new() -> Self { + GetPullBuilder { + _state: PhantomData, + _fields: (None,), + _type: PhantomData, + } + } +} + +impl GetPullBuilder { + /// Create a new builder with all fields unset + pub fn builder() -> Self { + GetPullBuilder { + _state: PhantomData, + _fields: (None,), + _type: PhantomData, + } + } +} + +impl GetPullBuilder +where + St: get_pull_state::State, + St::Pull: get_pull_state::IsUnset, +{ + /// Set the `pull` field (required) + pub fn pull( + mut self, + value: impl Into>, + ) -> GetPullBuilder, S> { + self._fields.0 = Option::Some(value.into()); + GetPullBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl GetPullBuilder +where + St: get_pull_state::State, + St::Pull: get_pull_state::IsSet, +{ + /// Build the final struct. + pub fn build(self) -> GetPull { + GetPull { + pull: self._fields.0.unwrap(), + } + } +} diff --git a/crates/jacquard-api/src/sh_tangled/repo/get_pulls.rs b/crates/jacquard-api/src/sh_tangled/repo/get_pulls.rs new file mode 100644 index 000000000..66227f77c --- /dev/null +++ b/crates/jacquard-api/src/sh_tangled/repo/get_pulls.rs @@ -0,0 +1,453 @@ +// @generated by jacquard-lexicon. DO NOT EDIT. +// +// Lexicon: sh.tangled.repo.getPulls +// +// 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, DefaultStr, FromStaticStr}; + +#[allow(unused_imports)] +use jacquard_common::deps::codegen::unicode_segmentation::UnicodeSegmentation; +use jacquard_common::deps::smol_str::SmolStr; +use jacquard_common::types::string::{AtUri, Cid}; +use jacquard_common::types::value::Data; +use jacquard_derive::IntoStatic; +use jacquard_lexicon::lexicon::LexiconDoc; +use jacquard_lexicon::schema::LexiconSchema; + +use crate::sh_tangled::repo::get_pulls; +#[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", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct GetPulls { + pub pulls: Vec>, +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct GetPullsOutput { + pub items: Vec>, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct RecordView { + #[serde(skip_serializing_if = "Option::is_none")] + pub cid: Option>, + pub uri: AtUri, + ///Embedded sh.tangled.repo.pull record. + pub value: Data, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +/** Response marker for the `sh.tangled.repo.getPulls` query. + +Implements `jacquard_common::xrpc::XrpcResp`; successful bodies decode as `Self::Output`, which is `GetPullsOutput` for this endpoint.*/ +pub struct GetPullsResponse; +impl jacquard_common::xrpc::XrpcResp for GetPullsResponse { + const NSID: &'static str = "sh.tangled.repo.getPulls"; + const ENCODING: &'static str = "application/json"; + type Output = GetPullsOutput; + type Err = jacquard_common::xrpc::GenericError; +} + +impl jacquard_common::xrpc::XrpcRequest for GetPulls { + const NSID: &'static str = "sh.tangled.repo.getPulls"; + const METHOD: jacquard_common::xrpc::XrpcMethod = jacquard_common::xrpc::XrpcMethod::Query; + type Response = GetPullsResponse; +} + +/** Endpoint marker for the `sh.tangled.repo.getPulls` query. + +Path: `/xrpc/sh.tangled.repo.getPulls`. The request payload type is `GetPulls`; send that request with `jacquard::Client` or use this marker through lower-level `XrpcEndpoint` APIs.*/ +pub struct GetPullsRequest; +impl jacquard_common::xrpc::XrpcEndpoint for GetPullsRequest { + const PATH: &'static str = "/xrpc/sh.tangled.repo.getPulls"; + const METHOD: jacquard_common::xrpc::XrpcMethod = jacquard_common::xrpc::XrpcMethod::Query; + type Request = GetPulls; + type Response = GetPullsResponse; +} + +impl LexiconSchema for RecordView { + fn nsid() -> &'static str { + "sh.tangled.repo.getPulls" + } + fn def_name() -> &'static str { + "recordView" + } + fn lexicon_doc() -> LexiconDoc<'static> { + lexicon_doc_sh_tangled_repo_getPulls() + } + fn validate(&self) -> Result<(), ConstraintError> { + Ok(()) + } +} + +pub mod get_pulls_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 Pulls; + } + /// Empty state - all required fields are unset + pub struct Empty(()); + impl sealed::Sealed for Empty {} + impl State for Empty { + type Pulls = Unset; + } + ///State transition - sets the `pulls` field to Set + pub struct SetPulls(PhantomData St>); + impl sealed::Sealed for SetPulls {} + impl State for SetPulls { + type Pulls = Set; + } + /// Marker types for field names + #[allow(non_camel_case_types)] + pub mod members { + ///Marker type for the `pulls` field + pub struct pulls(()); + } +} + +/// Builder for constructing an instance of this type. +pub struct GetPullsBuilder { + _state: PhantomData St>, + _fields: (Option>>,), + _type: PhantomData S>, +} + +impl GetPulls { + /// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed + pub fn new() -> GetPullsBuilder { + GetPullsBuilder::new() + } +} + +impl GetPulls { + /// Create a new builder for this type + pub fn builder() -> GetPullsBuilder { + GetPullsBuilder::builder() + } +} + +impl GetPullsBuilder { + /// Create a new builder with all fields unset, using the default string type, if needed + pub fn new() -> Self { + GetPullsBuilder { + _state: PhantomData, + _fields: (None,), + _type: PhantomData, + } + } +} + +impl GetPullsBuilder { + /// Create a new builder with all fields unset + pub fn builder() -> Self { + GetPullsBuilder { + _state: PhantomData, + _fields: (None,), + _type: PhantomData, + } + } +} + +impl GetPullsBuilder +where + St: get_pulls_state::State, + St::Pulls: get_pulls_state::IsUnset, +{ + /// Set the `pulls` field (required) + pub fn pulls( + mut self, + value: impl Into>>, + ) -> GetPullsBuilder, S> { + self._fields.0 = Option::Some(value.into()); + GetPullsBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl GetPullsBuilder +where + St: get_pulls_state::State, + St::Pulls: get_pulls_state::IsSet, +{ + /// Build the final struct. + pub fn build(self) -> GetPulls { + GetPulls { + pulls: self._fields.0.unwrap(), + } + } +} + +pub mod record_view_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 Uri; + type Value; + } + /// Empty state - all required fields are unset + pub struct Empty(()); + impl sealed::Sealed for Empty {} + impl State for Empty { + type Uri = Unset; + type Value = Unset; + } + ///State transition - sets the `uri` field to Set + pub struct SetUri(PhantomData St>); + impl sealed::Sealed for SetUri {} + impl State for SetUri { + type Uri = Set; + type Value = St::Value; + } + ///State transition - sets the `value` field to Set + pub struct SetValue(PhantomData St>); + impl sealed::Sealed for SetValue {} + impl State for SetValue { + type Uri = St::Uri; + type Value = Set; + } + /// Marker types for field names + #[allow(non_camel_case_types)] + pub mod members { + ///Marker type for the `uri` field + pub struct uri(()); + ///Marker type for the `value` field + pub struct value(()); + } +} + +/// Builder for constructing an instance of this type. +pub struct RecordViewBuilder { + _state: PhantomData St>, + _fields: (Option>, Option>, Option>), + _type: PhantomData S>, +} + +impl RecordView { + /// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed + pub fn new() -> RecordViewBuilder { + RecordViewBuilder::new() + } +} + +impl RecordView { + /// Create a new builder for this type + pub fn builder() -> RecordViewBuilder { + RecordViewBuilder::builder() + } +} + +impl RecordViewBuilder { + /// Create a new builder with all fields unset, using the default string type, if needed + pub fn new() -> Self { + RecordViewBuilder { + _state: PhantomData, + _fields: (None, None, None), + _type: PhantomData, + } + } +} + +impl RecordViewBuilder { + /// Create a new builder with all fields unset + pub fn builder() -> Self { + RecordViewBuilder { + _state: PhantomData, + _fields: (None, None, None), + _type: PhantomData, + } + } +} + +impl RecordViewBuilder { + /// Set the `cid` field (optional) + pub fn cid(mut self, value: impl Into>>) -> Self { + self._fields.0 = value.into(); + self + } + /// Set the `cid` field to an Option value (optional) + pub fn maybe_cid(mut self, value: Option>) -> Self { + self._fields.0 = value; + self + } +} + +impl RecordViewBuilder +where + St: record_view_state::State, + St::Uri: record_view_state::IsUnset, +{ + /// Set the `uri` field (required) + pub fn uri( + mut self, + value: impl Into>, + ) -> RecordViewBuilder, S> { + self._fields.1 = Option::Some(value.into()); + RecordViewBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl RecordViewBuilder +where + St: record_view_state::State, + St::Value: record_view_state::IsUnset, +{ + /// Set the `value` field (required) + pub fn value( + mut self, + value: impl Into>, + ) -> RecordViewBuilder, S> { + self._fields.2 = Option::Some(value.into()); + RecordViewBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl RecordViewBuilder +where + St: record_view_state::State, + St::Uri: record_view_state::IsSet, + St::Value: record_view_state::IsSet, +{ + /// Build the final struct. + pub fn build(self) -> RecordView { + RecordView { + cid: self._fields.0, + uri: self._fields.1.unwrap(), + value: 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>) -> RecordView { + RecordView { + cid: self._fields.0, + uri: self._fields.1.unwrap(), + value: self._fields.2.unwrap(), + extra_data: Some(extra_data), + } + } +} + +fn lexicon_doc_sh_tangled_repo_getPulls() -> 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.getPulls"), + defs: { + let mut map = BTreeMap::new(); + map.insert( + SmolStr::new_static("main"), + LexUserType::XrpcQuery(LexXrpcQuery { + parameters: Some(LexXrpcQueryParameter::Params(LexXrpcParameters { + required: Some(vec![SmolStr::new_static("pulls")]), + properties: { + #[allow(unused_mut)] + let mut map = BTreeMap::new(); + map.insert( + SmolStr::new_static("pulls"), + LexXrpcParametersProperty::Array(LexPrimitiveArray { + items: LexPrimitiveArrayItem::String(LexString { + format: Some(LexStringFormat::AtUri), + ..Default::default() + }), + max_length: Some(50usize), + ..Default::default() + }), + ); + map + }, + ..Default::default() + })), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("recordView"), + LexUserType::Object(LexObject { + required: Some(vec![ + SmolStr::new_static("uri"), + SmolStr::new_static("value"), + ]), + properties: { + #[allow(unused_mut)] + let mut map = BTreeMap::new(); + map.insert( + SmolStr::new_static("cid"), + LexObjectProperty::String(LexString { + format: Some(LexStringFormat::Cid), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("uri"), + LexObjectProperty::String(LexString { + format: Some(LexStringFormat::AtUri), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("value"), + LexObjectProperty::Unknown(LexUnknown { + ..Default::default() + }), + ); + map + }, + ..Default::default() + }), + ); + map + }, + ..Default::default() + } +} diff --git a/crates/jacquard-api/src/sh_tangled/repo/get_repo.rs b/crates/jacquard-api/src/sh_tangled/repo/get_repo.rs new file mode 100644 index 000000000..29b77d187 --- /dev/null +++ b/crates/jacquard-api/src/sh_tangled/repo/get_repo.rs @@ -0,0 +1,177 @@ +// @generated by jacquard-lexicon. DO NOT EDIT. +// +// Lexicon: sh.tangled.repo.getRepo +// +// 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::deps::smol_str::SmolStr; +use jacquard_common::types::string::{AtUri, Cid}; +use jacquard_common::types::value::Data; +use jacquard_common::{BosStr, DefaultStr, FromStaticStr}; +use jacquard_derive::IntoStatic; +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct GetRepo { + pub repo: AtUri, +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct GetRepoOutput { + #[serde(skip_serializing_if = "Option::is_none")] + pub cid: Option>, + pub uri: AtUri, + ///Embedded sh.tangled.repo record. + pub value: Data, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +/** Response marker for the `sh.tangled.repo.getRepo` query. + +Implements `jacquard_common::xrpc::XrpcResp`; successful bodies decode as `Self::Output`, which is `GetRepoOutput` for this endpoint.*/ +pub struct GetRepoResponse; +impl jacquard_common::xrpc::XrpcResp for GetRepoResponse { + const NSID: &'static str = "sh.tangled.repo.getRepo"; + const ENCODING: &'static str = "application/json"; + type Output = GetRepoOutput; + type Err = jacquard_common::xrpc::GenericError; +} + +impl jacquard_common::xrpc::XrpcRequest for GetRepo { + const NSID: &'static str = "sh.tangled.repo.getRepo"; + const METHOD: jacquard_common::xrpc::XrpcMethod = jacquard_common::xrpc::XrpcMethod::Query; + type Response = GetRepoResponse; +} + +/** Endpoint marker for the `sh.tangled.repo.getRepo` query. + +Path: `/xrpc/sh.tangled.repo.getRepo`. The request payload type is `GetRepo`; send that request with `jacquard::Client` or use this marker through lower-level `XrpcEndpoint` APIs.*/ +pub struct GetRepoRequest; +impl jacquard_common::xrpc::XrpcEndpoint for GetRepoRequest { + const PATH: &'static str = "/xrpc/sh.tangled.repo.getRepo"; + const METHOD: jacquard_common::xrpc::XrpcMethod = jacquard_common::xrpc::XrpcMethod::Query; + type Request = GetRepo; + type Response = GetRepoResponse; +} + +pub mod get_repo_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 Repo; + } + /// Empty state - all required fields are unset + pub struct Empty(()); + impl sealed::Sealed for Empty {} + impl State for Empty { + type Repo = Unset; + } + ///State transition - sets the `repo` field to Set + pub struct SetRepo(PhantomData St>); + impl sealed::Sealed for SetRepo {} + impl State for SetRepo { + type Repo = Set; + } + /// Marker types for field names + #[allow(non_camel_case_types)] + pub mod members { + ///Marker type for the `repo` field + pub struct repo(()); + } +} + +/// Builder for constructing an instance of this type. +pub struct GetRepoBuilder { + _state: PhantomData St>, + _fields: (Option>,), + _type: PhantomData S>, +} + +impl GetRepo { + /// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed + pub fn new() -> GetRepoBuilder { + GetRepoBuilder::new() + } +} + +impl GetRepo { + /// Create a new builder for this type + pub fn builder() -> GetRepoBuilder { + GetRepoBuilder::builder() + } +} + +impl GetRepoBuilder { + /// Create a new builder with all fields unset, using the default string type, if needed + pub fn new() -> Self { + GetRepoBuilder { + _state: PhantomData, + _fields: (None,), + _type: PhantomData, + } + } +} + +impl GetRepoBuilder { + /// Create a new builder with all fields unset + pub fn builder() -> Self { + GetRepoBuilder { + _state: PhantomData, + _fields: (None,), + _type: PhantomData, + } + } +} + +impl GetRepoBuilder +where + St: get_repo_state::State, + St::Repo: get_repo_state::IsUnset, +{ + /// Set the `repo` field (required) + pub fn repo( + mut self, + value: impl Into>, + ) -> GetRepoBuilder, S> { + self._fields.0 = Option::Some(value.into()); + GetRepoBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl GetRepoBuilder +where + St: get_repo_state::State, + St::Repo: get_repo_state::IsSet, +{ + /// Build the final struct. + pub fn build(self) -> GetRepo { + GetRepo { + repo: self._fields.0.unwrap(), + } + } +} diff --git a/crates/jacquard-api/src/sh_tangled/repo/get_repo_by_repo_did.rs b/crates/jacquard-api/src/sh_tangled/repo/get_repo_by_repo_did.rs new file mode 100644 index 000000000..f61cc0cb4 --- /dev/null +++ b/crates/jacquard-api/src/sh_tangled/repo/get_repo_by_repo_did.rs @@ -0,0 +1,177 @@ +// @generated by jacquard-lexicon. DO NOT EDIT. +// +// Lexicon: sh.tangled.repo.getRepoByRepoDid +// +// 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::deps::smol_str::SmolStr; +use jacquard_common::types::string::{AtUri, Cid, Did}; +use jacquard_common::types::value::Data; +use jacquard_common::{BosStr, DefaultStr, FromStaticStr}; +use jacquard_derive::IntoStatic; +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct GetRepoByRepoDid { + pub repo_did: Did, +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct GetRepoByRepoDidOutput { + #[serde(skip_serializing_if = "Option::is_none")] + pub cid: Option>, + pub uri: AtUri, + ///Embedded sh.tangled.repo record. + pub value: Data, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +/** Response marker for the `sh.tangled.repo.getRepoByRepoDid` query. + +Implements `jacquard_common::xrpc::XrpcResp`; successful bodies decode as `Self::Output`, which is `GetRepoByRepoDidOutput` for this endpoint.*/ +pub struct GetRepoByRepoDidResponse; +impl jacquard_common::xrpc::XrpcResp for GetRepoByRepoDidResponse { + const NSID: &'static str = "sh.tangled.repo.getRepoByRepoDid"; + const ENCODING: &'static str = "application/json"; + type Output = GetRepoByRepoDidOutput; + type Err = jacquard_common::xrpc::GenericError; +} + +impl jacquard_common::xrpc::XrpcRequest for GetRepoByRepoDid { + const NSID: &'static str = "sh.tangled.repo.getRepoByRepoDid"; + const METHOD: jacquard_common::xrpc::XrpcMethod = jacquard_common::xrpc::XrpcMethod::Query; + type Response = GetRepoByRepoDidResponse; +} + +/** Endpoint marker for the `sh.tangled.repo.getRepoByRepoDid` query. + +Path: `/xrpc/sh.tangled.repo.getRepoByRepoDid`. The request payload type is `GetRepoByRepoDid`; send that request with `jacquard::Client` or use this marker through lower-level `XrpcEndpoint` APIs.*/ +pub struct GetRepoByRepoDidRequest; +impl jacquard_common::xrpc::XrpcEndpoint for GetRepoByRepoDidRequest { + const PATH: &'static str = "/xrpc/sh.tangled.repo.getRepoByRepoDid"; + const METHOD: jacquard_common::xrpc::XrpcMethod = jacquard_common::xrpc::XrpcMethod::Query; + type Request = GetRepoByRepoDid; + type Response = GetRepoByRepoDidResponse; +} + +pub mod get_repo_by_repo_did_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 RepoDid; + } + /// Empty state - all required fields are unset + pub struct Empty(()); + impl sealed::Sealed for Empty {} + impl State for Empty { + type RepoDid = Unset; + } + ///State transition - sets the `repo_did` field to Set + pub struct SetRepoDid(PhantomData St>); + impl sealed::Sealed for SetRepoDid {} + impl State for SetRepoDid { + type RepoDid = Set; + } + /// Marker types for field names + #[allow(non_camel_case_types)] + pub mod members { + ///Marker type for the `repo_did` field + pub struct repo_did(()); + } +} + +/// Builder for constructing an instance of this type. +pub struct GetRepoByRepoDidBuilder { + _state: PhantomData St>, + _fields: (Option>,), + _type: PhantomData S>, +} + +impl GetRepoByRepoDid { + /// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed + pub fn new() -> GetRepoByRepoDidBuilder { + GetRepoByRepoDidBuilder::new() + } +} + +impl GetRepoByRepoDid { + /// Create a new builder for this type + pub fn builder() -> GetRepoByRepoDidBuilder { + GetRepoByRepoDidBuilder::builder() + } +} + +impl GetRepoByRepoDidBuilder { + /// Create a new builder with all fields unset, using the default string type, if needed + pub fn new() -> Self { + GetRepoByRepoDidBuilder { + _state: PhantomData, + _fields: (None,), + _type: PhantomData, + } + } +} + +impl GetRepoByRepoDidBuilder { + /// Create a new builder with all fields unset + pub fn builder() -> Self { + GetRepoByRepoDidBuilder { + _state: PhantomData, + _fields: (None,), + _type: PhantomData, + } + } +} + +impl GetRepoByRepoDidBuilder +where + St: get_repo_by_repo_did_state::State, + St::RepoDid: get_repo_by_repo_did_state::IsUnset, +{ + /// Set the `repoDid` field (required) + pub fn repo_did( + mut self, + value: impl Into>, + ) -> GetRepoByRepoDidBuilder, S> { + self._fields.0 = Option::Some(value.into()); + GetRepoByRepoDidBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl GetRepoByRepoDidBuilder +where + St: get_repo_by_repo_did_state::State, + St::RepoDid: get_repo_by_repo_did_state::IsSet, +{ + /// Build the final struct. + pub fn build(self) -> GetRepoByRepoDid { + GetRepoByRepoDid { + repo_did: self._fields.0.unwrap(), + } + } +} diff --git a/crates/jacquard-api/src/sh_tangled/repo/get_repos.rs b/crates/jacquard-api/src/sh_tangled/repo/get_repos.rs new file mode 100644 index 000000000..0a5dfb772 --- /dev/null +++ b/crates/jacquard-api/src/sh_tangled/repo/get_repos.rs @@ -0,0 +1,453 @@ +// @generated by jacquard-lexicon. DO NOT EDIT. +// +// Lexicon: sh.tangled.repo.getRepos +// +// 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, DefaultStr, FromStaticStr}; + +#[allow(unused_imports)] +use jacquard_common::deps::codegen::unicode_segmentation::UnicodeSegmentation; +use jacquard_common::deps::smol_str::SmolStr; +use jacquard_common::types::string::{AtUri, Cid}; +use jacquard_common::types::value::Data; +use jacquard_derive::IntoStatic; +use jacquard_lexicon::lexicon::LexiconDoc; +use jacquard_lexicon::schema::LexiconSchema; + +use crate::sh_tangled::repo::get_repos; +#[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", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct GetRepos { + pub repos: Vec>, +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct GetReposOutput { + pub items: Vec>, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct RecordView { + #[serde(skip_serializing_if = "Option::is_none")] + pub cid: Option>, + pub uri: AtUri, + ///Embedded sh.tangled.repo record. + pub value: Data, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +/** Response marker for the `sh.tangled.repo.getRepos` query. + +Implements `jacquard_common::xrpc::XrpcResp`; successful bodies decode as `Self::Output`, which is `GetReposOutput` for this endpoint.*/ +pub struct GetReposResponse; +impl jacquard_common::xrpc::XrpcResp for GetReposResponse { + const NSID: &'static str = "sh.tangled.repo.getRepos"; + const ENCODING: &'static str = "application/json"; + type Output = GetReposOutput; + type Err = jacquard_common::xrpc::GenericError; +} + +impl jacquard_common::xrpc::XrpcRequest for GetRepos { + const NSID: &'static str = "sh.tangled.repo.getRepos"; + const METHOD: jacquard_common::xrpc::XrpcMethod = jacquard_common::xrpc::XrpcMethod::Query; + type Response = GetReposResponse; +} + +/** Endpoint marker for the `sh.tangled.repo.getRepos` query. + +Path: `/xrpc/sh.tangled.repo.getRepos`. The request payload type is `GetRepos`; send that request with `jacquard::Client` or use this marker through lower-level `XrpcEndpoint` APIs.*/ +pub struct GetReposRequest; +impl jacquard_common::xrpc::XrpcEndpoint for GetReposRequest { + const PATH: &'static str = "/xrpc/sh.tangled.repo.getRepos"; + const METHOD: jacquard_common::xrpc::XrpcMethod = jacquard_common::xrpc::XrpcMethod::Query; + type Request = GetRepos; + type Response = GetReposResponse; +} + +impl LexiconSchema for RecordView { + fn nsid() -> &'static str { + "sh.tangled.repo.getRepos" + } + fn def_name() -> &'static str { + "recordView" + } + fn lexicon_doc() -> LexiconDoc<'static> { + lexicon_doc_sh_tangled_repo_getRepos() + } + fn validate(&self) -> Result<(), ConstraintError> { + Ok(()) + } +} + +pub mod get_repos_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 Repos; + } + /// Empty state - all required fields are unset + pub struct Empty(()); + impl sealed::Sealed for Empty {} + impl State for Empty { + type Repos = Unset; + } + ///State transition - sets the `repos` field to Set + pub struct SetRepos(PhantomData St>); + impl sealed::Sealed for SetRepos {} + impl State for SetRepos { + type Repos = Set; + } + /// Marker types for field names + #[allow(non_camel_case_types)] + pub mod members { + ///Marker type for the `repos` field + pub struct repos(()); + } +} + +/// Builder for constructing an instance of this type. +pub struct GetReposBuilder { + _state: PhantomData St>, + _fields: (Option>>,), + _type: PhantomData S>, +} + +impl GetRepos { + /// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed + pub fn new() -> GetReposBuilder { + GetReposBuilder::new() + } +} + +impl GetRepos { + /// Create a new builder for this type + pub fn builder() -> GetReposBuilder { + GetReposBuilder::builder() + } +} + +impl GetReposBuilder { + /// Create a new builder with all fields unset, using the default string type, if needed + pub fn new() -> Self { + GetReposBuilder { + _state: PhantomData, + _fields: (None,), + _type: PhantomData, + } + } +} + +impl GetReposBuilder { + /// Create a new builder with all fields unset + pub fn builder() -> Self { + GetReposBuilder { + _state: PhantomData, + _fields: (None,), + _type: PhantomData, + } + } +} + +impl GetReposBuilder +where + St: get_repos_state::State, + St::Repos: get_repos_state::IsUnset, +{ + /// Set the `repos` field (required) + pub fn repos( + mut self, + value: impl Into>>, + ) -> GetReposBuilder, S> { + self._fields.0 = Option::Some(value.into()); + GetReposBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl GetReposBuilder +where + St: get_repos_state::State, + St::Repos: get_repos_state::IsSet, +{ + /// Build the final struct. + pub fn build(self) -> GetRepos { + GetRepos { + repos: self._fields.0.unwrap(), + } + } +} + +pub mod record_view_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 Uri; + type Value; + } + /// Empty state - all required fields are unset + pub struct Empty(()); + impl sealed::Sealed for Empty {} + impl State for Empty { + type Uri = Unset; + type Value = Unset; + } + ///State transition - sets the `uri` field to Set + pub struct SetUri(PhantomData St>); + impl sealed::Sealed for SetUri {} + impl State for SetUri { + type Uri = Set; + type Value = St::Value; + } + ///State transition - sets the `value` field to Set + pub struct SetValue(PhantomData St>); + impl sealed::Sealed for SetValue {} + impl State for SetValue { + type Uri = St::Uri; + type Value = Set; + } + /// Marker types for field names + #[allow(non_camel_case_types)] + pub mod members { + ///Marker type for the `uri` field + pub struct uri(()); + ///Marker type for the `value` field + pub struct value(()); + } +} + +/// Builder for constructing an instance of this type. +pub struct RecordViewBuilder { + _state: PhantomData St>, + _fields: (Option>, Option>, Option>), + _type: PhantomData S>, +} + +impl RecordView { + /// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed + pub fn new() -> RecordViewBuilder { + RecordViewBuilder::new() + } +} + +impl RecordView { + /// Create a new builder for this type + pub fn builder() -> RecordViewBuilder { + RecordViewBuilder::builder() + } +} + +impl RecordViewBuilder { + /// Create a new builder with all fields unset, using the default string type, if needed + pub fn new() -> Self { + RecordViewBuilder { + _state: PhantomData, + _fields: (None, None, None), + _type: PhantomData, + } + } +} + +impl RecordViewBuilder { + /// Create a new builder with all fields unset + pub fn builder() -> Self { + RecordViewBuilder { + _state: PhantomData, + _fields: (None, None, None), + _type: PhantomData, + } + } +} + +impl RecordViewBuilder { + /// Set the `cid` field (optional) + pub fn cid(mut self, value: impl Into>>) -> Self { + self._fields.0 = value.into(); + self + } + /// Set the `cid` field to an Option value (optional) + pub fn maybe_cid(mut self, value: Option>) -> Self { + self._fields.0 = value; + self + } +} + +impl RecordViewBuilder +where + St: record_view_state::State, + St::Uri: record_view_state::IsUnset, +{ + /// Set the `uri` field (required) + pub fn uri( + mut self, + value: impl Into>, + ) -> RecordViewBuilder, S> { + self._fields.1 = Option::Some(value.into()); + RecordViewBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl RecordViewBuilder +where + St: record_view_state::State, + St::Value: record_view_state::IsUnset, +{ + /// Set the `value` field (required) + pub fn value( + mut self, + value: impl Into>, + ) -> RecordViewBuilder, S> { + self._fields.2 = Option::Some(value.into()); + RecordViewBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl RecordViewBuilder +where + St: record_view_state::State, + St::Uri: record_view_state::IsSet, + St::Value: record_view_state::IsSet, +{ + /// Build the final struct. + pub fn build(self) -> RecordView { + RecordView { + cid: self._fields.0, + uri: self._fields.1.unwrap(), + value: 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>) -> RecordView { + RecordView { + cid: self._fields.0, + uri: self._fields.1.unwrap(), + value: self._fields.2.unwrap(), + extra_data: Some(extra_data), + } + } +} + +fn lexicon_doc_sh_tangled_repo_getRepos() -> 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.getRepos"), + defs: { + let mut map = BTreeMap::new(); + map.insert( + SmolStr::new_static("main"), + LexUserType::XrpcQuery(LexXrpcQuery { + parameters: Some(LexXrpcQueryParameter::Params(LexXrpcParameters { + required: Some(vec![SmolStr::new_static("repos")]), + properties: { + #[allow(unused_mut)] + let mut map = BTreeMap::new(); + map.insert( + SmolStr::new_static("repos"), + LexXrpcParametersProperty::Array(LexPrimitiveArray { + items: LexPrimitiveArrayItem::String(LexString { + format: Some(LexStringFormat::AtUri), + ..Default::default() + }), + max_length: Some(50usize), + ..Default::default() + }), + ); + map + }, + ..Default::default() + })), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("recordView"), + LexUserType::Object(LexObject { + required: Some(vec![ + SmolStr::new_static("uri"), + SmolStr::new_static("value"), + ]), + properties: { + #[allow(unused_mut)] + let mut map = BTreeMap::new(); + map.insert( + SmolStr::new_static("cid"), + LexObjectProperty::String(LexString { + format: Some(LexStringFormat::Cid), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("uri"), + LexObjectProperty::String(LexString { + format: Some(LexStringFormat::AtUri), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("value"), + LexObjectProperty::Unknown(LexUnknown { + ..Default::default() + }), + ); + map + }, + ..Default::default() + }), + ); + map + }, + ..Default::default() + } +} diff --git a/crates/jacquard-api/src/sh_tangled/repo/hidden_ref.rs b/crates/jacquard-api/src/sh_tangled/repo/hidden_ref.rs index 32b1a8681..f05c90786 100644 --- a/crates/jacquard-api/src/sh_tangled/repo/hidden_ref.rs +++ b/crates/jacquard-api/src/sh_tangled/repo/hidden_ref.rs @@ -11,7 +11,7 @@ use alloc::collections::BTreeMap; #[allow(unused_imports)] use core::marker::PhantomData; use jacquard_common::deps::smol_str::SmolStr; -use jacquard_common::types::string::AtUri; +use jacquard_common::types::string::Did; use jacquard_common::types::value::Data; use jacquard_common::{BosStr, CowStr, DefaultStr, FromStaticStr}; use jacquard_derive::IntoStatic; @@ -27,8 +27,8 @@ pub struct HiddenRef { pub fork_ref: S, ///Remote reference name pub remote_ref: S, - ///AT-URI of the repository - pub repo: AtUri, + ///DID of the fork that the hidden ref belongs to + pub repo: Did, #[serde(flatten, default, skip_serializing_if = "Option::is_none")] pub extra_data: Option>>, } @@ -142,7 +142,7 @@ pub mod hidden_ref_state { /// Builder for constructing an instance of this type. pub struct HiddenRefBuilder { _state: PhantomData St>, - _fields: (Option, Option, Option>), + _fields: (Option, Option, Option>), _type: PhantomData S>, } @@ -228,7 +228,7 @@ where /// Set the `repo` field (required) pub fn repo( mut self, - value: impl Into>, + value: impl Into>, ) -> HiddenRefBuilder, S> { self._fields.2 = Option::Some(value.into()); HiddenRefBuilder { diff --git a/crates/jacquard-api/src/sh_tangled/repo/issue.rs b/crates/jacquard-api/src/sh_tangled/repo/issue.rs index 23b9e4915..7bddf6f08 100644 --- a/crates/jacquard-api/src/sh_tangled/repo/issue.rs +++ b/crates/jacquard-api/src/sh_tangled/repo/issue.rs @@ -7,6 +7,8 @@ //! Generated bindings for the `sh.tangled.repo.issue` Lexicon namespace/module. pub mod comment; +pub mod count_states; +pub mod count_states_by; pub mod list_states; pub mod list_states_by; pub mod state; @@ -21,6 +23,7 @@ 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}; @@ -42,6 +45,8 @@ use serde::{Deserialize, Serialize}; 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, @@ -176,6 +181,7 @@ pub mod issue_state { pub struct IssueBuilder { _state: PhantomData St>, _fields: ( + Option>>, Option, Option, Option>>, @@ -205,7 +211,7 @@ impl IssueBuilder { pub fn new() -> Self { IssueBuilder { _state: PhantomData, - _fields: (None, None, None, None, None, None), + _fields: (None, None, None, None, None, None, None), _type: PhantomData, } } @@ -216,21 +222,34 @@ impl IssueBuilder { pub fn builder() -> Self { IssueBuilder { _state: PhantomData, - _fields: (None, None, None, None, None, None), + _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.0 = value.into(); + 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.0 = value; + self._fields.1 = value; self } } @@ -245,7 +264,7 @@ where mut self, value: impl Into, ) -> IssueBuilder, S> { - self._fields.1 = Option::Some(value.into()); + self._fields.2 = Option::Some(value.into()); IssueBuilder { _state: PhantomData, _fields: self._fields, @@ -257,12 +276,12 @@ where impl IssueBuilder { /// Set the `mentions` field (optional) pub fn mentions(mut self, value: impl Into>>>) -> Self { - self._fields.2 = value.into(); + 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.2 = value; + self._fields.3 = value; self } } @@ -270,12 +289,12 @@ impl IssueBuilder { impl IssueBuilder { /// Set the `references` field (optional) pub fn references(mut self, value: impl Into>>>) -> Self { - self._fields.3 = value.into(); + 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.3 = value; + self._fields.4 = value; self } } @@ -287,7 +306,7 @@ where { /// Set the `repo` field (required) pub fn repo(mut self, value: impl Into>) -> IssueBuilder, S> { - self._fields.4 = Option::Some(value.into()); + self._fields.5 = Option::Some(value.into()); IssueBuilder { _state: PhantomData, _fields: self._fields, @@ -303,7 +322,7 @@ where { /// Set the `title` field (required) pub fn title(mut self, value: impl Into) -> IssueBuilder, S> { - self._fields.5 = Option::Some(value.into()); + self._fields.6 = Option::Some(value.into()); IssueBuilder { _state: PhantomData, _fields: self._fields, @@ -322,24 +341,26 @@ where /// Build the final struct. pub fn build(self) -> Issue { Issue { - body: self._fields.0, - created_at: self._fields.1.unwrap(), - mentions: self._fields.2, - references: self._fields.3, - repo: self._fields.4.unwrap(), - title: self._fields.5.unwrap(), + 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 { - body: self._fields.0, - created_at: self._fields.1.unwrap(), - mentions: self._fields.2, - references: self._fields.3, - repo: self._fields.4.unwrap(), - title: self._fields.5.unwrap(), + 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), } } @@ -368,6 +389,15 @@ fn lexicon_doc_sh_tangled_repo_issue() -> LexiconDoc<'static> { 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 { diff --git a/crates/jacquard-api/src/sh_tangled/repo/issue/count_states.rs b/crates/jacquard-api/src/sh_tangled/repo/issue/count_states.rs new file mode 100644 index 000000000..46cb0f507 --- /dev/null +++ b/crates/jacquard-api/src/sh_tangled/repo/issue/count_states.rs @@ -0,0 +1,176 @@ +// @generated by jacquard-lexicon. DO NOT EDIT. +// +// Lexicon: sh.tangled.repo.issue.countStates +// +// 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::deps::smol_str::SmolStr; +use jacquard_common::types::string::AtUri; +use jacquard_common::types::value::Data; +use jacquard_common::{BosStr, DefaultStr, FromStaticStr}; +use jacquard_derive::IntoStatic; +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct CountStates { + pub subject: AtUri, +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct CountStatesOutput { + ///Total number of matching records. + pub count: i64, + ///Number of distinct authors among the matching records. + pub distinct_authors: i64, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +/** Response marker for the `sh.tangled.repo.issue.countStates` query. + +Implements `jacquard_common::xrpc::XrpcResp`; successful bodies decode as `Self::Output`, which is `CountStatesOutput` for this endpoint.*/ +pub struct CountStatesResponse; +impl jacquard_common::xrpc::XrpcResp for CountStatesResponse { + const NSID: &'static str = "sh.tangled.repo.issue.countStates"; + const ENCODING: &'static str = "application/json"; + type Output = CountStatesOutput; + type Err = jacquard_common::xrpc::GenericError; +} + +impl jacquard_common::xrpc::XrpcRequest for CountStates { + const NSID: &'static str = "sh.tangled.repo.issue.countStates"; + const METHOD: jacquard_common::xrpc::XrpcMethod = jacquard_common::xrpc::XrpcMethod::Query; + type Response = CountStatesResponse; +} + +/** Endpoint marker for the `sh.tangled.repo.issue.countStates` query. + +Path: `/xrpc/sh.tangled.repo.issue.countStates`. The request payload type is `CountStates`; send that request with `jacquard::Client` or use this marker through lower-level `XrpcEndpoint` APIs.*/ +pub struct CountStatesRequest; +impl jacquard_common::xrpc::XrpcEndpoint for CountStatesRequest { + const PATH: &'static str = "/xrpc/sh.tangled.repo.issue.countStates"; + const METHOD: jacquard_common::xrpc::XrpcMethod = jacquard_common::xrpc::XrpcMethod::Query; + type Request = CountStates; + type Response = CountStatesResponse; +} + +pub mod count_states_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 Subject; + } + /// Empty state - all required fields are unset + pub struct Empty(()); + impl sealed::Sealed for Empty {} + impl State for Empty { + type Subject = Unset; + } + ///State transition - sets the `subject` field to Set + pub struct SetSubject(PhantomData St>); + impl sealed::Sealed for SetSubject {} + impl State for SetSubject { + type Subject = Set; + } + /// Marker types for field names + #[allow(non_camel_case_types)] + pub mod members { + ///Marker type for the `subject` field + pub struct subject(()); + } +} + +/// Builder for constructing an instance of this type. +pub struct CountStatesBuilder { + _state: PhantomData St>, + _fields: (Option>,), + _type: PhantomData S>, +} + +impl CountStates { + /// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed + pub fn new() -> CountStatesBuilder { + CountStatesBuilder::new() + } +} + +impl CountStates { + /// Create a new builder for this type + pub fn builder() -> CountStatesBuilder { + CountStatesBuilder::builder() + } +} + +impl CountStatesBuilder { + /// Create a new builder with all fields unset, using the default string type, if needed + pub fn new() -> Self { + CountStatesBuilder { + _state: PhantomData, + _fields: (None,), + _type: PhantomData, + } + } +} + +impl CountStatesBuilder { + /// Create a new builder with all fields unset + pub fn builder() -> Self { + CountStatesBuilder { + _state: PhantomData, + _fields: (None,), + _type: PhantomData, + } + } +} + +impl CountStatesBuilder +where + St: count_states_state::State, + St::Subject: count_states_state::IsUnset, +{ + /// Set the `subject` field (required) + pub fn subject( + mut self, + value: impl Into>, + ) -> CountStatesBuilder, S> { + self._fields.0 = Option::Some(value.into()); + CountStatesBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl CountStatesBuilder +where + St: count_states_state::State, + St::Subject: count_states_state::IsSet, +{ + /// Build the final struct. + pub fn build(self) -> CountStates { + CountStates { + subject: self._fields.0.unwrap(), + } + } +} diff --git a/crates/jacquard-api/src/sh_tangled/repo/issue/count_states_by.rs b/crates/jacquard-api/src/sh_tangled/repo/issue/count_states_by.rs new file mode 100644 index 000000000..4376107f0 --- /dev/null +++ b/crates/jacquard-api/src/sh_tangled/repo/issue/count_states_by.rs @@ -0,0 +1,176 @@ +// @generated by jacquard-lexicon. DO NOT EDIT. +// +// Lexicon: sh.tangled.repo.issue.countStatesBy +// +// 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::deps::smol_str::SmolStr; +use jacquard_common::types::string::Did; +use jacquard_common::types::value::Data; +use jacquard_common::{BosStr, DefaultStr, FromStaticStr}; +use jacquard_derive::IntoStatic; +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct CountStatesBy { + pub subject: Did, +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct CountStatesByOutput { + ///Total number of matching records. + pub count: i64, + ///Number of distinct authors among the matching records. + pub distinct_authors: i64, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +/** Response marker for the `sh.tangled.repo.issue.countStatesBy` query. + +Implements `jacquard_common::xrpc::XrpcResp`; successful bodies decode as `Self::Output`, which is `CountStatesByOutput` for this endpoint.*/ +pub struct CountStatesByResponse; +impl jacquard_common::xrpc::XrpcResp for CountStatesByResponse { + const NSID: &'static str = "sh.tangled.repo.issue.countStatesBy"; + const ENCODING: &'static str = "application/json"; + type Output = CountStatesByOutput; + type Err = jacquard_common::xrpc::GenericError; +} + +impl jacquard_common::xrpc::XrpcRequest for CountStatesBy { + const NSID: &'static str = "sh.tangled.repo.issue.countStatesBy"; + const METHOD: jacquard_common::xrpc::XrpcMethod = jacquard_common::xrpc::XrpcMethod::Query; + type Response = CountStatesByResponse; +} + +/** Endpoint marker for the `sh.tangled.repo.issue.countStatesBy` query. + +Path: `/xrpc/sh.tangled.repo.issue.countStatesBy`. The request payload type is `CountStatesBy`; send that request with `jacquard::Client` or use this marker through lower-level `XrpcEndpoint` APIs.*/ +pub struct CountStatesByRequest; +impl jacquard_common::xrpc::XrpcEndpoint for CountStatesByRequest { + const PATH: &'static str = "/xrpc/sh.tangled.repo.issue.countStatesBy"; + const METHOD: jacquard_common::xrpc::XrpcMethod = jacquard_common::xrpc::XrpcMethod::Query; + type Request = CountStatesBy; + type Response = CountStatesByResponse; +} + +pub mod count_states_by_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 Subject; + } + /// Empty state - all required fields are unset + pub struct Empty(()); + impl sealed::Sealed for Empty {} + impl State for Empty { + type Subject = Unset; + } + ///State transition - sets the `subject` field to Set + pub struct SetSubject(PhantomData St>); + impl sealed::Sealed for SetSubject {} + impl State for SetSubject { + type Subject = Set; + } + /// Marker types for field names + #[allow(non_camel_case_types)] + pub mod members { + ///Marker type for the `subject` field + pub struct subject(()); + } +} + +/// Builder for constructing an instance of this type. +pub struct CountStatesByBuilder { + _state: PhantomData St>, + _fields: (Option>,), + _type: PhantomData S>, +} + +impl CountStatesBy { + /// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed + pub fn new() -> CountStatesByBuilder { + CountStatesByBuilder::new() + } +} + +impl CountStatesBy { + /// Create a new builder for this type + pub fn builder() -> CountStatesByBuilder { + CountStatesByBuilder::builder() + } +} + +impl CountStatesByBuilder { + /// Create a new builder with all fields unset, using the default string type, if needed + pub fn new() -> Self { + CountStatesByBuilder { + _state: PhantomData, + _fields: (None,), + _type: PhantomData, + } + } +} + +impl CountStatesByBuilder { + /// Create a new builder with all fields unset + pub fn builder() -> Self { + CountStatesByBuilder { + _state: PhantomData, + _fields: (None,), + _type: PhantomData, + } + } +} + +impl CountStatesByBuilder +where + St: count_states_by_state::State, + St::Subject: count_states_by_state::IsUnset, +{ + /// Set the `subject` field (required) + pub fn subject( + mut self, + value: impl Into>, + ) -> CountStatesByBuilder, S> { + self._fields.0 = Option::Some(value.into()); + CountStatesByBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl CountStatesByBuilder +where + St: count_states_by_state::State, + St::Subject: count_states_by_state::IsSet, +{ + /// Build the final struct. + pub fn build(self) -> CountStatesBy { + CountStatesBy { + subject: self._fields.0.unwrap(), + } + } +} diff --git a/crates/jacquard-api/src/sh_tangled/repo/issue/state.rs b/crates/jacquard-api/src/sh_tangled/repo/issue/state.rs index 25b00197c..6f322a26c 100644 --- a/crates/jacquard-api/src/sh_tangled/repo/issue/state.rs +++ b/crates/jacquard-api/src/sh_tangled/repo/issue/state.rs @@ -20,7 +20,7 @@ use jacquard_common::{BosStr, CowStr, DefaultStr, FromStaticStr}; 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}; +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; @@ -40,6 +40,7 @@ use serde::{Deserialize, Serialize}; bound(deserialize = "S: Deserialize<'de> + BosStr") )] pub struct State { + pub created_at: Datetime, pub issue: AtUri, ///state of the issue pub state: StateState, @@ -195,6 +196,7 @@ pub mod state_state { } /// State trait tracking which required fields have been set pub trait State: sealed::Sealed { + type CreatedAt; type Issue; type State; } @@ -202,13 +204,23 @@ pub mod state_state { 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; } @@ -216,12 +228,15 @@ pub mod state_state { 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 @@ -232,7 +247,7 @@ pub mod state_state { /// Builder for constructing an instance of this type. pub struct StateBuilder { _state: PhantomData St>, - _fields: (Option>, Option>), + _fields: (Option, Option>, Option>), _type: PhantomData S>, } @@ -255,7 +270,7 @@ impl StateBuilder { pub fn new() -> Self { StateBuilder { _state: PhantomData, - _fields: (None, None), + _fields: (None, None, None), _type: PhantomData, } } @@ -266,7 +281,26 @@ impl StateBuilder { pub fn builder() -> Self { StateBuilder { _state: PhantomData, - _fields: (None, None), + _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, } } @@ -282,7 +316,7 @@ where mut self, value: impl Into>, ) -> StateBuilder, S> { - self._fields.0 = Option::Some(value.into()); + self._fields.1 = Option::Some(value.into()); StateBuilder { _state: PhantomData, _fields: self._fields, @@ -301,7 +335,7 @@ where mut self, value: impl Into>, ) -> StateBuilder, S> { - self._fields.1 = Option::Some(value.into()); + self._fields.2 = Option::Some(value.into()); StateBuilder { _state: PhantomData, _fields: self._fields, @@ -313,22 +347,25 @@ where 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 { - issue: self._fields.0.unwrap(), - state: self._fields.1.unwrap(), + 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 { - issue: self._fields.0.unwrap(), - state: self._fields.1.unwrap(), + created_at: self._fields.0.unwrap(), + issue: self._fields.1.unwrap(), + state: self._fields.2.unwrap(), extra_data: Some(extra_data), } } @@ -352,10 +389,18 @@ fn lexicon_doc_sh_tangled_repo_issue_state() -> LexiconDoc<'static> { 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 { diff --git a/crates/jacquard-api/src/sh_tangled/repo/languages.rs b/crates/jacquard-api/src/sh_tangled/repo/languages.rs index d8bada792..9f8cf8281 100644 --- a/crates/jacquard-api/src/sh_tangled/repo/languages.rs +++ b/crates/jacquard-api/src/sh_tangled/repo/languages.rs @@ -69,7 +69,8 @@ pub struct Languages { bound(deserialize = "S: Deserialize<'de> + BosStr") )] pub struct LanguagesOutput { - pub languages: Vec>, + #[serde(skip_serializing_if = "Option::is_none")] + pub languages: Option>>, ///The git reference used pub r#ref: S, ///Total number of files analyzed diff --git a/crates/jacquard-api/src/sh_tangled/repo/list_secrets.rs b/crates/jacquard-api/src/sh_tangled/repo/list_secrets.rs index 967606ef9..18cbc49fd 100644 --- a/crates/jacquard-api/src/sh_tangled/repo/list_secrets.rs +++ b/crates/jacquard-api/src/sh_tangled/repo/list_secrets.rs @@ -41,7 +41,8 @@ pub struct ListSecrets { bound(deserialize = "S: Deserialize<'de> + BosStr") )] pub struct ListSecretsOutput { - pub secrets: Vec>, + #[serde(skip_serializing_if = "Option::is_none")] + pub secrets: Option>>, #[serde(flatten, default, skip_serializing_if = "Option::is_none")] pub extra_data: Option>>, } diff --git a/crates/jacquard-api/src/sh_tangled/repo/merge.rs b/crates/jacquard-api/src/sh_tangled/repo/merge.rs index d0a8fc1e1..fdf3cbcfa 100644 --- a/crates/jacquard-api/src/sh_tangled/repo/merge.rs +++ b/crates/jacquard-api/src/sh_tangled/repo/merge.rs @@ -37,12 +37,16 @@ pub struct Merge { ///Merge commit message #[serde(skip_serializing_if = "Option::is_none")] pub commit_message: Option, - ///DID of the repository owner - pub did: Did, - ///Name of the repository - pub name: S, + ///DID of the repository owner. A knot without the repo-did-input capability reads this and name in place of repo. + #[serde(skip_serializing_if = "Option::is_none")] + pub did: Option>, + ///Name of the repository. A knot without the repo-did-input capability reads this and DID in place of repo. + #[serde(skip_serializing_if = "Option::is_none")] + pub name: Option, ///Patch content to merge pub patch: S, + ///DID of the repository + pub repo: Did, #[serde(flatten, default, skip_serializing_if = "Option::is_none")] pub extra_data: Option>>, } @@ -88,66 +92,50 @@ pub mod merge_state { /// State trait tracking which required fields have been set pub trait State: sealed::Sealed { type Branch; - type Did; - type Name; type Patch; + type Repo; } /// Empty state - all required fields are unset pub struct Empty(()); impl sealed::Sealed for Empty {} impl State for Empty { type Branch = Unset; - type Did = Unset; - type Name = Unset; type Patch = Unset; + type Repo = Unset; } ///State transition - sets the `branch` field to Set pub struct SetBranch(PhantomData St>); impl sealed::Sealed for SetBranch {} impl State for SetBranch { type Branch = Set; - type Did = St::Did; - type Name = St::Name; - type Patch = St::Patch; - } - ///State transition - sets the `did` field to Set - pub struct SetDid(PhantomData St>); - impl sealed::Sealed for SetDid {} - impl State for SetDid { - type Branch = St::Branch; - type Did = Set; - type Name = St::Name; - type Patch = St::Patch; - } - ///State transition - sets the `name` field to Set - pub struct SetName(PhantomData St>); - impl sealed::Sealed for SetName {} - impl State for SetName { - type Branch = St::Branch; - type Did = St::Did; - type Name = Set; type Patch = St::Patch; + type Repo = St::Repo; } ///State transition - sets the `patch` field to Set pub struct SetPatch(PhantomData St>); impl sealed::Sealed for SetPatch {} impl State for SetPatch { type Branch = St::Branch; - type Did = St::Did; - type Name = St::Name; type Patch = Set; + type Repo = St::Repo; + } + ///State transition - sets the `repo` field to Set + pub struct SetRepo(PhantomData St>); + impl sealed::Sealed for SetRepo {} + impl State for SetRepo { + type Branch = St::Branch; + type Patch = St::Patch; + type Repo = Set; } /// Marker types for field names #[allow(non_camel_case_types)] pub mod members { ///Marker type for the `branch` field pub struct branch(()); - ///Marker type for the `did` field - pub struct did(()); - ///Marker type for the `name` field - pub struct name(()); ///Marker type for the `patch` field pub struct patch(()); + ///Marker type for the `repo` field + pub struct repo(()); } } @@ -163,6 +151,7 @@ pub struct MergeBuilder { Option>, Option, Option, + Option>, ), _type: PhantomData S>, } @@ -186,7 +175,7 @@ impl MergeBuilder { pub fn new() -> Self { MergeBuilder { _state: PhantomData, - _fields: (None, None, None, None, None, None, None, None), + _fields: (None, None, None, None, None, None, None, None, None), _type: PhantomData, } } @@ -197,7 +186,7 @@ impl MergeBuilder { pub fn builder() -> Self { MergeBuilder { _state: PhantomData, - _fields: (None, None, None, None, None, None, None, None), + _fields: (None, None, None, None, None, None, None, None, None), _type: PhantomData, } } @@ -271,30 +260,40 @@ impl MergeBuilder { } } -impl MergeBuilder -where - St: merge_state::State, - St::Did: merge_state::IsUnset, -{ - /// Set the `did` field (required) - pub fn did(mut self, value: impl Into>) -> MergeBuilder, S> { - self._fields.5 = Option::Some(value.into()); - MergeBuilder { - _state: PhantomData, - _fields: self._fields, - _type: PhantomData, - } +impl MergeBuilder { + /// Set the `did` field (optional) + pub fn did(mut self, value: impl Into>>) -> Self { + self._fields.5 = value.into(); + self + } + /// Set the `did` field to an Option value (optional) + pub fn maybe_did(mut self, value: Option>) -> Self { + self._fields.5 = value; + self + } +} + +impl MergeBuilder { + /// Set the `name` field (optional) + pub fn name(mut self, value: impl Into>) -> Self { + self._fields.6 = value.into(); + self + } + /// Set the `name` field to an Option value (optional) + pub fn maybe_name(mut self, value: Option) -> Self { + self._fields.6 = value; + self } } impl MergeBuilder where St: merge_state::State, - St::Name: merge_state::IsUnset, + St::Patch: merge_state::IsUnset, { - /// Set the `name` field (required) - pub fn name(mut self, value: impl Into) -> MergeBuilder, S> { - self._fields.6 = Option::Some(value.into()); + /// Set the `patch` field (required) + pub fn patch(mut self, value: impl Into) -> MergeBuilder, S> { + self._fields.7 = Option::Some(value.into()); MergeBuilder { _state: PhantomData, _fields: self._fields, @@ -306,11 +305,11 @@ where impl MergeBuilder where St: merge_state::State, - St::Patch: merge_state::IsUnset, + St::Repo: merge_state::IsUnset, { - /// Set the `patch` field (required) - pub fn patch(mut self, value: impl Into) -> MergeBuilder, S> { - self._fields.7 = Option::Some(value.into()); + /// Set the `repo` field (required) + pub fn repo(mut self, value: impl Into>) -> MergeBuilder, S> { + self._fields.8 = Option::Some(value.into()); MergeBuilder { _state: PhantomData, _fields: self._fields, @@ -323,9 +322,8 @@ impl MergeBuilder where St: merge_state::State, St::Branch: merge_state::IsSet, - St::Did: merge_state::IsSet, - St::Name: merge_state::IsSet, St::Patch: merge_state::IsSet, + St::Repo: merge_state::IsSet, { /// Build the final struct. pub fn build(self) -> Merge { @@ -335,9 +333,10 @@ where branch: self._fields.2.unwrap(), commit_body: self._fields.3, commit_message: self._fields.4, - did: self._fields.5.unwrap(), - name: self._fields.6.unwrap(), + did: self._fields.5, + name: self._fields.6, patch: self._fields.7.unwrap(), + repo: self._fields.8.unwrap(), extra_data: Default::default(), } } @@ -349,9 +348,10 @@ where branch: self._fields.2.unwrap(), commit_body: self._fields.3, commit_message: self._fields.4, - did: self._fields.5.unwrap(), - name: self._fields.6.unwrap(), + did: self._fields.5, + name: self._fields.6, patch: self._fields.7.unwrap(), + repo: self._fields.8.unwrap(), extra_data: Some(extra_data), } } diff --git a/crates/jacquard-api/src/sh_tangled/repo/merge_check.rs b/crates/jacquard-api/src/sh_tangled/repo/merge_check.rs index 5f27c84f0..56ff8512c 100644 --- a/crates/jacquard-api/src/sh_tangled/repo/merge_check.rs +++ b/crates/jacquard-api/src/sh_tangled/repo/merge_check.rs @@ -48,12 +48,16 @@ pub struct ConflictInfo { pub struct MergeCheck { ///Target branch to merge into pub branch: S, - ///DID of the repository owner - pub did: Did, - ///Name of the repository - pub name: S, + ///DID of the repository owner. A knot without the repo-did-input capability reads this and name in place of repo. + #[serde(skip_serializing_if = "Option::is_none")] + pub did: Option>, + ///Name of the repository. A knot without the repo-did-input capability reads this and DID in place of repo. + #[serde(skip_serializing_if = "Option::is_none")] + pub name: Option, ///Patch or pull request to check for merge conflicts pub patch: S, + ///DID of the repository + pub repo: Did, #[serde(flatten, default, skip_serializing_if = "Option::is_none")] pub extra_data: Option>>, } @@ -170,57 +174,75 @@ fn lexicon_doc_sh_tangled_repo_mergeCheck() -> LexiconDoc<'static> { LexUserType::XrpcProcedure(LexXrpcProcedure { input: Some(LexXrpcBody { encoding: CowStr::new_static("application/json"), - schema: Some(LexXrpcBodySchema::Object(LexObject { - required: Some(vec![ - SmolStr::new_static("did"), - SmolStr::new_static("name"), - SmolStr::new_static("patch"), - SmolStr::new_static("branch"), - ]), - properties: { - #[allow(unused_mut)] - let mut map = BTreeMap::new(); - map.insert( - SmolStr::new_static("branch"), - LexObjectProperty::String(LexString { - description: Some(CowStr::new_static( - "Target branch to merge into", - )), - ..Default::default() - }), - ); - map.insert( - SmolStr::new_static("did"), - LexObjectProperty::String(LexString { - description: Some(CowStr::new_static( - "DID of the repository owner", - )), - format: Some(LexStringFormat::Did), - ..Default::default() - }), - ); - map.insert( - SmolStr::new_static("name"), - LexObjectProperty::String(LexString { - description: Some(CowStr::new_static( - "Name of the repository", - )), - ..Default::default() - }), - ); - map.insert( - SmolStr::new_static("patch"), - LexObjectProperty::String(LexString { - description: Some(CowStr::new_static( - "Patch or pull request to check for merge conflicts", - )), - ..Default::default() - }), - ); - map - }, - ..Default::default() - })), + schema: Some( + LexXrpcBodySchema::Object(LexObject { + required: Some( + vec![ + SmolStr::new_static("repo"), SmolStr::new_static("patch"), + SmolStr::new_static("branch") + ], + ), + properties: { + #[allow(unused_mut)] + let mut map = BTreeMap::new(); + map.insert( + SmolStr::new_static("branch"), + LexObjectProperty::String(LexString { + description: Some( + CowStr::new_static("Target branch to merge into"), + ), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("did"), + LexObjectProperty::String(LexString { + description: Some( + CowStr::new_static( + "DID of the repository owner. A knot without the repo-did-input capability reads this and name in place of repo.", + ), + ), + format: Some(LexStringFormat::Did), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("name"), + LexObjectProperty::String(LexString { + description: Some( + CowStr::new_static( + "Name of the repository. A knot without the repo-did-input capability reads this and DID in place of repo.", + ), + ), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("patch"), + LexObjectProperty::String(LexString { + description: Some( + CowStr::new_static( + "Patch or pull request to check for merge conflicts", + ), + ), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("repo"), + LexObjectProperty::String(LexString { + description: Some( + CowStr::new_static("DID of the repository"), + ), + format: Some(LexStringFormat::Did), + ..Default::default() + }), + ); + map + }, + ..Default::default() + }), + ), ..Default::default() }), ..Default::default() @@ -243,73 +265,63 @@ pub mod merge_check_state { /// State trait tracking which required fields have been set pub trait State: sealed::Sealed { type Branch; - type Did; - type Name; type Patch; + type Repo; } /// Empty state - all required fields are unset pub struct Empty(()); impl sealed::Sealed for Empty {} impl State for Empty { type Branch = Unset; - type Did = Unset; - type Name = Unset; type Patch = Unset; + type Repo = Unset; } ///State transition - sets the `branch` field to Set pub struct SetBranch(PhantomData St>); impl sealed::Sealed for SetBranch {} impl State for SetBranch { type Branch = Set; - type Did = St::Did; - type Name = St::Name; - type Patch = St::Patch; - } - ///State transition - sets the `did` field to Set - pub struct SetDid(PhantomData St>); - impl sealed::Sealed for SetDid {} - impl State for SetDid { - type Branch = St::Branch; - type Did = Set; - type Name = St::Name; - type Patch = St::Patch; - } - ///State transition - sets the `name` field to Set - pub struct SetName(PhantomData St>); - impl sealed::Sealed for SetName {} - impl State for SetName { - type Branch = St::Branch; - type Did = St::Did; - type Name = Set; type Patch = St::Patch; + type Repo = St::Repo; } ///State transition - sets the `patch` field to Set pub struct SetPatch(PhantomData St>); impl sealed::Sealed for SetPatch {} impl State for SetPatch { type Branch = St::Branch; - type Did = St::Did; - type Name = St::Name; type Patch = Set; + type Repo = St::Repo; + } + ///State transition - sets the `repo` field to Set + pub struct SetRepo(PhantomData St>); + impl sealed::Sealed for SetRepo {} + impl State for SetRepo { + type Branch = St::Branch; + type Patch = St::Patch; + type Repo = Set; } /// Marker types for field names #[allow(non_camel_case_types)] pub mod members { ///Marker type for the `branch` field pub struct branch(()); - ///Marker type for the `did` field - pub struct did(()); - ///Marker type for the `name` field - pub struct name(()); ///Marker type for the `patch` field pub struct patch(()); + ///Marker type for the `repo` field + pub struct repo(()); } } /// Builder for constructing an instance of this type. pub struct MergeCheckBuilder { _state: PhantomData St>, - _fields: (Option, Option>, Option, Option), + _fields: ( + Option, + Option>, + Option, + Option, + Option>, + ), _type: PhantomData S>, } @@ -332,7 +344,7 @@ impl MergeCheckBuilder { pub fn new() -> Self { MergeCheckBuilder { _state: PhantomData, - _fields: (None, None, None, None), + _fields: (None, None, None, None, None), _type: PhantomData, } } @@ -343,7 +355,7 @@ impl MergeCheckBuilder { pub fn builder() -> Self { MergeCheckBuilder { _state: PhantomData, - _fields: (None, None, None, None), + _fields: (None, None, None, None, None), _type: PhantomData, } } @@ -368,36 +380,43 @@ where } } -impl MergeCheckBuilder -where - St: merge_check_state::State, - St::Did: merge_check_state::IsUnset, -{ - /// Set the `did` field (required) - pub fn did( - mut self, - value: impl Into>, - ) -> MergeCheckBuilder, S> { - self._fields.1 = Option::Some(value.into()); - MergeCheckBuilder { - _state: PhantomData, - _fields: self._fields, - _type: PhantomData, - } +impl MergeCheckBuilder { + /// Set the `did` field (optional) + pub fn did(mut self, value: impl Into>>) -> Self { + self._fields.1 = value.into(); + self + } + /// Set the `did` field to an Option value (optional) + pub fn maybe_did(mut self, value: Option>) -> Self { + self._fields.1 = value; + self + } +} + +impl MergeCheckBuilder { + /// Set the `name` field (optional) + pub fn name(mut self, value: impl Into>) -> Self { + self._fields.2 = value.into(); + self + } + /// Set the `name` field to an Option value (optional) + pub fn maybe_name(mut self, value: Option) -> Self { + self._fields.2 = value; + self } } impl MergeCheckBuilder where St: merge_check_state::State, - St::Name: merge_check_state::IsUnset, + St::Patch: merge_check_state::IsUnset, { - /// Set the `name` field (required) - pub fn name( + /// Set the `patch` field (required) + pub fn patch( mut self, value: impl Into, - ) -> MergeCheckBuilder, S> { - self._fields.2 = Option::Some(value.into()); + ) -> MergeCheckBuilder, S> { + self._fields.3 = Option::Some(value.into()); MergeCheckBuilder { _state: PhantomData, _fields: self._fields, @@ -409,14 +428,14 @@ where impl MergeCheckBuilder where St: merge_check_state::State, - St::Patch: merge_check_state::IsUnset, + St::Repo: merge_check_state::IsUnset, { - /// Set the `patch` field (required) - pub fn patch( + /// Set the `repo` field (required) + pub fn repo( mut self, - value: impl Into, - ) -> MergeCheckBuilder, S> { - self._fields.3 = Option::Some(value.into()); + value: impl Into>, + ) -> MergeCheckBuilder, S> { + self._fields.4 = Option::Some(value.into()); MergeCheckBuilder { _state: PhantomData, _fields: self._fields, @@ -429,17 +448,17 @@ impl MergeCheckBuilder where St: merge_check_state::State, St::Branch: merge_check_state::IsSet, - St::Did: merge_check_state::IsSet, - St::Name: merge_check_state::IsSet, St::Patch: merge_check_state::IsSet, + St::Repo: merge_check_state::IsSet, { /// Build the final struct. pub fn build(self) -> MergeCheck { MergeCheck { branch: self._fields.0.unwrap(), - did: self._fields.1.unwrap(), - name: self._fields.2.unwrap(), + did: self._fields.1, + name: self._fields.2, patch: self._fields.3.unwrap(), + repo: self._fields.4.unwrap(), extra_data: Default::default(), } } @@ -447,9 +466,10 @@ where pub fn build_with_data(self, extra_data: BTreeMap>) -> MergeCheck { MergeCheck { branch: self._fields.0.unwrap(), - did: self._fields.1.unwrap(), - name: self._fields.2.unwrap(), + did: self._fields.1, + name: self._fields.2, patch: self._fields.3.unwrap(), + repo: self._fields.4.unwrap(), extra_data: Some(extra_data), } } diff --git a/crates/jacquard-api/src/sh_tangled/repo/pull.rs b/crates/jacquard-api/src/sh_tangled/repo/pull.rs index 2d03cb521..617a8c782 100644 --- a/crates/jacquard-api/src/sh_tangled/repo/pull.rs +++ b/crates/jacquard-api/src/sh_tangled/repo/pull.rs @@ -7,6 +7,8 @@ //! Generated bindings for the `sh.tangled.repo.pull` Lexicon namespace/module. pub mod comment; +pub mod count_statuses; +pub mod count_statuses_by; pub mod list_statuses; pub mod list_statuses_by; pub mod status; @@ -44,6 +46,8 @@ use serde::{Deserialize, Serialize}; bound(deserialize = "S: Deserialize<'de> + BosStr") )] pub struct Pull { + #[serde(skip_serializing_if = "Option::is_none")] + pub blobs: Option>>, #[serde(skip_serializing_if = "Option::is_none")] pub body: Option, pub created_at: Datetime, @@ -307,6 +311,7 @@ pub mod pull_state { pub struct PullBuilder { _state: PhantomData St>, _fields: ( + Option>>, Option, Option, Option>, @@ -339,7 +344,7 @@ impl PullBuilder { pub fn new() -> Self { PullBuilder { _state: PhantomData, - _fields: (None, None, None, None, None, None, None, None, None), + _fields: (None, None, None, None, None, None, None, None, None, None), _type: PhantomData, } } @@ -350,21 +355,34 @@ impl PullBuilder { pub fn builder() -> Self { PullBuilder { _state: PhantomData, - _fields: (None, None, None, None, None, None, None, None, None), + _fields: (None, None, None, None, None, None, None, None, None, None), _type: PhantomData, } } } +impl PullBuilder { + /// 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 PullBuilder { /// Set the `body` field (optional) pub fn body(mut self, value: impl Into>) -> Self { - self._fields.0 = value.into(); + 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.0 = value; + self._fields.1 = value; self } } @@ -379,7 +397,7 @@ where mut self, value: impl Into, ) -> PullBuilder, S> { - self._fields.1 = Option::Some(value.into()); + self._fields.2 = Option::Some(value.into()); PullBuilder { _state: PhantomData, _fields: self._fields, @@ -391,12 +409,12 @@ where impl PullBuilder { /// Set the `dependentOn` field (optional) pub fn dependent_on(mut self, value: impl Into>>) -> Self { - self._fields.2 = value.into(); + self._fields.3 = value.into(); self } /// Set the `dependentOn` field to an Option value (optional) pub fn maybe_dependent_on(mut self, value: Option>) -> Self { - self._fields.2 = value; + self._fields.3 = value; self } } @@ -404,12 +422,12 @@ impl PullBuilder { impl PullBuilder { /// Set the `mentions` field (optional) pub fn mentions(mut self, value: impl Into>>>) -> Self { - self._fields.3 = value.into(); + self._fields.4 = 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._fields.4 = value; self } } @@ -417,12 +435,12 @@ impl PullBuilder { impl PullBuilder { /// Set the `references` field (optional) pub fn references(mut self, value: impl Into>>>) -> Self { - self._fields.4 = value.into(); + self._fields.5 = 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._fields.5 = value; self } } @@ -437,7 +455,7 @@ where mut self, value: impl Into>>, ) -> PullBuilder, S> { - self._fields.5 = Option::Some(value.into()); + self._fields.6 = Option::Some(value.into()); PullBuilder { _state: PhantomData, _fields: self._fields, @@ -449,12 +467,12 @@ where impl PullBuilder { /// Set the `source` field (optional) pub fn source(mut self, value: impl Into>>) -> Self { - self._fields.6 = value.into(); + self._fields.7 = value.into(); self } /// Set the `source` field to an Option value (optional) pub fn maybe_source(mut self, value: Option>) -> Self { - self._fields.6 = value; + self._fields.7 = value; self } } @@ -469,7 +487,7 @@ where mut self, value: impl Into>, ) -> PullBuilder, S> { - self._fields.7 = Option::Some(value.into()); + self._fields.8 = Option::Some(value.into()); PullBuilder { _state: PhantomData, _fields: self._fields, @@ -485,7 +503,7 @@ where { /// Set the `title` field (required) pub fn title(mut self, value: impl Into) -> PullBuilder, S> { - self._fields.8 = Option::Some(value.into()); + self._fields.9 = Option::Some(value.into()); PullBuilder { _state: PhantomData, _fields: self._fields, @@ -505,30 +523,32 @@ where /// Build the final struct. pub fn build(self) -> Pull { Pull { - body: self._fields.0, - created_at: self._fields.1.unwrap(), - dependent_on: self._fields.2, - mentions: self._fields.3, - references: self._fields.4, - rounds: self._fields.5.unwrap(), - source: self._fields.6, - target: self._fields.7.unwrap(), - title: self._fields.8.unwrap(), + blobs: self._fields.0, + body: self._fields.1, + created_at: self._fields.2.unwrap(), + dependent_on: self._fields.3, + mentions: self._fields.4, + references: self._fields.5, + rounds: self._fields.6.unwrap(), + source: self._fields.7, + target: self._fields.8.unwrap(), + title: self._fields.9.unwrap(), extra_data: Default::default(), } } /// Build the final struct with custom extra_data. pub fn build_with_data(self, extra_data: BTreeMap>) -> Pull { Pull { - body: self._fields.0, - created_at: self._fields.1.unwrap(), - dependent_on: self._fields.2, - mentions: self._fields.3, - references: self._fields.4, - rounds: self._fields.5.unwrap(), - source: self._fields.6, - target: self._fields.7.unwrap(), - title: self._fields.8.unwrap(), + blobs: self._fields.0, + body: self._fields.1, + created_at: self._fields.2.unwrap(), + dependent_on: self._fields.3, + mentions: self._fields.4, + references: self._fields.5, + rounds: self._fields.6.unwrap(), + source: self._fields.7, + target: self._fields.8.unwrap(), + title: self._fields.9.unwrap(), extra_data: Some(extra_data), } } @@ -558,6 +578,15 @@ fn lexicon_doc_sh_tangled_repo_pull() -> LexiconDoc<'static> { 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 { diff --git a/crates/jacquard-api/src/sh_tangled/repo/pull/count_statuses.rs b/crates/jacquard-api/src/sh_tangled/repo/pull/count_statuses.rs new file mode 100644 index 000000000..fc8337ac2 --- /dev/null +++ b/crates/jacquard-api/src/sh_tangled/repo/pull/count_statuses.rs @@ -0,0 +1,176 @@ +// @generated by jacquard-lexicon. DO NOT EDIT. +// +// Lexicon: sh.tangled.repo.pull.countStatuses +// +// 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::deps::smol_str::SmolStr; +use jacquard_common::types::string::AtUri; +use jacquard_common::types::value::Data; +use jacquard_common::{BosStr, DefaultStr, FromStaticStr}; +use jacquard_derive::IntoStatic; +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct CountStatuses { + pub subject: AtUri, +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct CountStatusesOutput { + ///Total number of matching records. + pub count: i64, + ///Number of distinct authors among the matching records. + pub distinct_authors: i64, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +/** Response marker for the `sh.tangled.repo.pull.countStatuses` query. + +Implements `jacquard_common::xrpc::XrpcResp`; successful bodies decode as `Self::Output`, which is `CountStatusesOutput` for this endpoint.*/ +pub struct CountStatusesResponse; +impl jacquard_common::xrpc::XrpcResp for CountStatusesResponse { + const NSID: &'static str = "sh.tangled.repo.pull.countStatuses"; + const ENCODING: &'static str = "application/json"; + type Output = CountStatusesOutput; + type Err = jacquard_common::xrpc::GenericError; +} + +impl jacquard_common::xrpc::XrpcRequest for CountStatuses { + const NSID: &'static str = "sh.tangled.repo.pull.countStatuses"; + const METHOD: jacquard_common::xrpc::XrpcMethod = jacquard_common::xrpc::XrpcMethod::Query; + type Response = CountStatusesResponse; +} + +/** Endpoint marker for the `sh.tangled.repo.pull.countStatuses` query. + +Path: `/xrpc/sh.tangled.repo.pull.countStatuses`. The request payload type is `CountStatuses`; send that request with `jacquard::Client` or use this marker through lower-level `XrpcEndpoint` APIs.*/ +pub struct CountStatusesRequest; +impl jacquard_common::xrpc::XrpcEndpoint for CountStatusesRequest { + const PATH: &'static str = "/xrpc/sh.tangled.repo.pull.countStatuses"; + const METHOD: jacquard_common::xrpc::XrpcMethod = jacquard_common::xrpc::XrpcMethod::Query; + type Request = CountStatuses; + type Response = CountStatusesResponse; +} + +pub mod count_statuses_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 Subject; + } + /// Empty state - all required fields are unset + pub struct Empty(()); + impl sealed::Sealed for Empty {} + impl State for Empty { + type Subject = Unset; + } + ///State transition - sets the `subject` field to Set + pub struct SetSubject(PhantomData St>); + impl sealed::Sealed for SetSubject {} + impl State for SetSubject { + type Subject = Set; + } + /// Marker types for field names + #[allow(non_camel_case_types)] + pub mod members { + ///Marker type for the `subject` field + pub struct subject(()); + } +} + +/// Builder for constructing an instance of this type. +pub struct CountStatusesBuilder { + _state: PhantomData St>, + _fields: (Option>,), + _type: PhantomData S>, +} + +impl CountStatuses { + /// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed + pub fn new() -> CountStatusesBuilder { + CountStatusesBuilder::new() + } +} + +impl CountStatuses { + /// Create a new builder for this type + pub fn builder() -> CountStatusesBuilder { + CountStatusesBuilder::builder() + } +} + +impl CountStatusesBuilder { + /// Create a new builder with all fields unset, using the default string type, if needed + pub fn new() -> Self { + CountStatusesBuilder { + _state: PhantomData, + _fields: (None,), + _type: PhantomData, + } + } +} + +impl CountStatusesBuilder { + /// Create a new builder with all fields unset + pub fn builder() -> Self { + CountStatusesBuilder { + _state: PhantomData, + _fields: (None,), + _type: PhantomData, + } + } +} + +impl CountStatusesBuilder +where + St: count_statuses_state::State, + St::Subject: count_statuses_state::IsUnset, +{ + /// Set the `subject` field (required) + pub fn subject( + mut self, + value: impl Into>, + ) -> CountStatusesBuilder, S> { + self._fields.0 = Option::Some(value.into()); + CountStatusesBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl CountStatusesBuilder +where + St: count_statuses_state::State, + St::Subject: count_statuses_state::IsSet, +{ + /// Build the final struct. + pub fn build(self) -> CountStatuses { + CountStatuses { + subject: self._fields.0.unwrap(), + } + } +} diff --git a/crates/jacquard-api/src/sh_tangled/repo/pull/count_statuses_by.rs b/crates/jacquard-api/src/sh_tangled/repo/pull/count_statuses_by.rs new file mode 100644 index 000000000..3eb4fadcb --- /dev/null +++ b/crates/jacquard-api/src/sh_tangled/repo/pull/count_statuses_by.rs @@ -0,0 +1,176 @@ +// @generated by jacquard-lexicon. DO NOT EDIT. +// +// Lexicon: sh.tangled.repo.pull.countStatusesBy +// +// 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::deps::smol_str::SmolStr; +use jacquard_common::types::string::Did; +use jacquard_common::types::value::Data; +use jacquard_common::{BosStr, DefaultStr, FromStaticStr}; +use jacquard_derive::IntoStatic; +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct CountStatusesBy { + pub subject: Did, +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct CountStatusesByOutput { + ///Total number of matching records. + pub count: i64, + ///Number of distinct authors among the matching records. + pub distinct_authors: i64, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +/** Response marker for the `sh.tangled.repo.pull.countStatusesBy` query. + +Implements `jacquard_common::xrpc::XrpcResp`; successful bodies decode as `Self::Output`, which is `CountStatusesByOutput` for this endpoint.*/ +pub struct CountStatusesByResponse; +impl jacquard_common::xrpc::XrpcResp for CountStatusesByResponse { + const NSID: &'static str = "sh.tangled.repo.pull.countStatusesBy"; + const ENCODING: &'static str = "application/json"; + type Output = CountStatusesByOutput; + type Err = jacquard_common::xrpc::GenericError; +} + +impl jacquard_common::xrpc::XrpcRequest for CountStatusesBy { + const NSID: &'static str = "sh.tangled.repo.pull.countStatusesBy"; + const METHOD: jacquard_common::xrpc::XrpcMethod = jacquard_common::xrpc::XrpcMethod::Query; + type Response = CountStatusesByResponse; +} + +/** Endpoint marker for the `sh.tangled.repo.pull.countStatusesBy` query. + +Path: `/xrpc/sh.tangled.repo.pull.countStatusesBy`. The request payload type is `CountStatusesBy`; send that request with `jacquard::Client` or use this marker through lower-level `XrpcEndpoint` APIs.*/ +pub struct CountStatusesByRequest; +impl jacquard_common::xrpc::XrpcEndpoint for CountStatusesByRequest { + const PATH: &'static str = "/xrpc/sh.tangled.repo.pull.countStatusesBy"; + const METHOD: jacquard_common::xrpc::XrpcMethod = jacquard_common::xrpc::XrpcMethod::Query; + type Request = CountStatusesBy; + type Response = CountStatusesByResponse; +} + +pub mod count_statuses_by_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 Subject; + } + /// Empty state - all required fields are unset + pub struct Empty(()); + impl sealed::Sealed for Empty {} + impl State for Empty { + type Subject = Unset; + } + ///State transition - sets the `subject` field to Set + pub struct SetSubject(PhantomData St>); + impl sealed::Sealed for SetSubject {} + impl State for SetSubject { + type Subject = Set; + } + /// Marker types for field names + #[allow(non_camel_case_types)] + pub mod members { + ///Marker type for the `subject` field + pub struct subject(()); + } +} + +/// Builder for constructing an instance of this type. +pub struct CountStatusesByBuilder { + _state: PhantomData St>, + _fields: (Option>,), + _type: PhantomData S>, +} + +impl CountStatusesBy { + /// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed + pub fn new() -> CountStatusesByBuilder { + CountStatusesByBuilder::new() + } +} + +impl CountStatusesBy { + /// Create a new builder for this type + pub fn builder() -> CountStatusesByBuilder { + CountStatusesByBuilder::builder() + } +} + +impl CountStatusesByBuilder { + /// Create a new builder with all fields unset, using the default string type, if needed + pub fn new() -> Self { + CountStatusesByBuilder { + _state: PhantomData, + _fields: (None,), + _type: PhantomData, + } + } +} + +impl CountStatusesByBuilder { + /// Create a new builder with all fields unset + pub fn builder() -> Self { + CountStatusesByBuilder { + _state: PhantomData, + _fields: (None,), + _type: PhantomData, + } + } +} + +impl CountStatusesByBuilder +where + St: count_statuses_by_state::State, + St::Subject: count_statuses_by_state::IsUnset, +{ + /// Set the `subject` field (required) + pub fn subject( + mut self, + value: impl Into>, + ) -> CountStatusesByBuilder, S> { + self._fields.0 = Option::Some(value.into()); + CountStatusesByBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl CountStatusesByBuilder +where + St: count_statuses_by_state::State, + St::Subject: count_statuses_by_state::IsSet, +{ + /// Build the final struct. + pub fn build(self) -> CountStatusesBy { + CountStatusesBy { + subject: self._fields.0.unwrap(), + } + } +} diff --git a/crates/jacquard-api/src/sh_tangled/repo/pull/status.rs b/crates/jacquard-api/src/sh_tangled/repo/pull/status.rs index 3764bc787..3d3e81df8 100644 --- a/crates/jacquard-api/src/sh_tangled/repo/pull/status.rs +++ b/crates/jacquard-api/src/sh_tangled/repo/pull/status.rs @@ -21,7 +21,7 @@ use jacquard_common::{BosStr, CowStr, DefaultStr, FromStaticStr}; 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}; +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; @@ -41,6 +41,7 @@ use serde::{Deserialize, Serialize}; bound(deserialize = "S: Deserialize<'de> + BosStr") )] pub struct Status { + pub created_at: Datetime, pub pull: AtUri, ///status of the pull request pub status: StatusStatus, @@ -204,6 +205,7 @@ pub mod status_state { } /// State trait tracking which required fields have been set pub trait State: sealed::Sealed { + type CreatedAt; type Pull; type Status; } @@ -211,13 +213,23 @@ pub mod status_state { pub struct Empty(()); impl sealed::Sealed for Empty {} impl State for Empty { + type CreatedAt = Unset; type Pull = Unset; type Status = 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 Pull = St::Pull; + type Status = St::Status; + } ///State transition - sets the `pull` field to Set pub struct SetPull(PhantomData St>); impl sealed::Sealed for SetPull {} impl State for SetPull { + type CreatedAt = St::CreatedAt; type Pull = Set; type Status = St::Status; } @@ -225,12 +237,15 @@ pub mod status_state { pub struct SetStatus(PhantomData St>); impl sealed::Sealed for SetStatus {} impl State for SetStatus { + type CreatedAt = St::CreatedAt; type Pull = St::Pull; type Status = 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 `pull` field pub struct pull(()); ///Marker type for the `status` field @@ -241,7 +256,7 @@ pub mod status_state { /// Builder for constructing an instance of this type. pub struct StatusBuilder { _state: PhantomData St>, - _fields: (Option>, Option>), + _fields: (Option, Option>, Option>), _type: PhantomData S>, } @@ -264,7 +279,7 @@ impl StatusBuilder { pub fn new() -> Self { StatusBuilder { _state: PhantomData, - _fields: (None, None), + _fields: (None, None, None), _type: PhantomData, } } @@ -275,7 +290,26 @@ impl StatusBuilder { pub fn builder() -> Self { StatusBuilder { _state: PhantomData, - _fields: (None, None), + _fields: (None, None, None), + _type: PhantomData, + } + } +} + +impl StatusBuilder +where + St: status_state::State, + St::CreatedAt: status_state::IsUnset, +{ + /// Set the `createdAt` field (required) + pub fn created_at( + mut self, + value: impl Into, + ) -> StatusBuilder, S> { + self._fields.0 = Option::Some(value.into()); + StatusBuilder { + _state: PhantomData, + _fields: self._fields, _type: PhantomData, } } @@ -291,7 +325,7 @@ where mut self, value: impl Into>, ) -> StatusBuilder, S> { - self._fields.0 = Option::Some(value.into()); + self._fields.1 = Option::Some(value.into()); StatusBuilder { _state: PhantomData, _fields: self._fields, @@ -310,7 +344,7 @@ where mut self, value: impl Into>, ) -> StatusBuilder, S> { - self._fields.1 = Option::Some(value.into()); + self._fields.2 = Option::Some(value.into()); StatusBuilder { _state: PhantomData, _fields: self._fields, @@ -322,22 +356,25 @@ where impl StatusBuilder where St: status_state::State, + St::CreatedAt: status_state::IsSet, St::Pull: status_state::IsSet, St::Status: status_state::IsSet, { /// Build the final struct. pub fn build(self) -> Status { Status { - pull: self._fields.0.unwrap(), - status: self._fields.1.unwrap(), + created_at: self._fields.0.unwrap(), + pull: self._fields.1.unwrap(), + status: 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>) -> Status { Status { - pull: self._fields.0.unwrap(), - status: self._fields.1.unwrap(), + created_at: self._fields.0.unwrap(), + pull: self._fields.1.unwrap(), + status: self._fields.2.unwrap(), extra_data: Some(extra_data), } } @@ -361,10 +398,18 @@ fn lexicon_doc_sh_tangled_repo_pull_status() -> LexiconDoc<'static> { required: Some(vec![ SmolStr::new_static("pull"), SmolStr::new_static("status"), + 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("pull"), LexObjectProperty::String(LexString { diff --git a/crates/jacquard-api/src/sh_tangled/repo/push.rs b/crates/jacquard-api/src/sh_tangled/repo/push.rs new file mode 100644 index 000000000..c6e67a297 --- /dev/null +++ b/crates/jacquard-api/src/sh_tangled/repo/push.rs @@ -0,0 +1,52 @@ +// @generated by jacquard-lexicon. DO NOT EDIT. +// +// Lexicon: sh.tangled.repo.push +// +// 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::deps::smol_str::SmolStr; +use jacquard_common::types::value::Data; +use jacquard_common::{BosStr, DefaultStr, FromStaticStr}; +use jacquard_derive::IntoStatic; +use serde::{Deserialize, Serialize}; +/** Request marker for the `sh.tangled.repo.push` procedure. + +This endpoint has no request parameters or input body; send this marker with `jacquard::Client`.*/ + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic, Copy)] +pub struct Push; +/** Response marker for the `sh.tangled.repo.push` procedure. + +Implements `jacquard_common::xrpc::XrpcResp`; successful bodies decode as `Self::Output`, which is `()` for this endpoint.*/ +pub struct PushResponse; +impl jacquard_common::xrpc::XrpcResp for PushResponse { + const NSID: &'static str = "sh.tangled.repo.push"; + const ENCODING: &'static str = "application/json"; + type Output = (); + type Err = jacquard_common::xrpc::GenericError; +} + +impl jacquard_common::xrpc::XrpcRequest for Push { + const NSID: &'static str = "sh.tangled.repo.push"; + const METHOD: jacquard_common::xrpc::XrpcMethod = + jacquard_common::xrpc::XrpcMethod::Procedure("application/json"); + type Response = PushResponse; +} + +/** Endpoint marker for the `sh.tangled.repo.push` procedure. + +Path: `/xrpc/sh.tangled.repo.push`. The request payload type is `Push`; use this marker with lower-level `XrpcEndpoint` APIs when you need endpoint metadata.*/ +pub struct PushRequest; +impl jacquard_common::xrpc::XrpcEndpoint for PushRequest { + const PATH: &'static str = "/xrpc/sh.tangled.repo.push"; + const METHOD: jacquard_common::xrpc::XrpcMethod = + jacquard_common::xrpc::XrpcMethod::Procedure("application/json"); + type Request = Push; + type Response = PushResponse; +} diff --git a/crates/jacquard-api/src/sh_tangled/repo/rename.rs b/crates/jacquard-api/src/sh_tangled/repo/rename.rs new file mode 100644 index 000000000..dd628f630 --- /dev/null +++ b/crates/jacquard-api/src/sh_tangled/repo/rename.rs @@ -0,0 +1,243 @@ +// @generated by jacquard-lexicon. DO NOT EDIT. +// +// Lexicon: sh.tangled.repo.rename +// +// 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::deps::smol_str::SmolStr; +use jacquard_common::types::string::{Did, RecordKey, Rkey}; +use jacquard_common::types::value::Data; +use jacquard_common::{BosStr, CowStr, DefaultStr, FromStaticStr}; +use jacquard_derive::IntoStatic; +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct Rename { + ///New display name of the repository + pub name: S, + ///DID of the repository to rename + pub repo: Did, + ///Rkey of the sh.tangled.repo record written for the new name + pub rkey: RecordKey>, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +/** Response marker for the `sh.tangled.repo.rename` procedure. + +Implements `jacquard_common::xrpc::XrpcResp`; successful bodies decode as `Self::Output`, which is `()` for this endpoint.*/ +pub struct RenameResponse; +impl jacquard_common::xrpc::XrpcResp for RenameResponse { + const NSID: &'static str = "sh.tangled.repo.rename"; + const ENCODING: &'static str = "application/json"; + type Output = (); + type Err = jacquard_common::xrpc::GenericError; +} + +impl jacquard_common::xrpc::XrpcRequest for Rename { + const NSID: &'static str = "sh.tangled.repo.rename"; + const METHOD: jacquard_common::xrpc::XrpcMethod = + jacquard_common::xrpc::XrpcMethod::Procedure("application/json"); + type Response = RenameResponse; +} + +/** Endpoint marker for the `sh.tangled.repo.rename` procedure. + +Path: `/xrpc/sh.tangled.repo.rename`. The request payload type is `Rename`; send that request with `jacquard::Client` or use this marker through lower-level `XrpcEndpoint` APIs.*/ +pub struct RenameRequest; +impl jacquard_common::xrpc::XrpcEndpoint for RenameRequest { + const PATH: &'static str = "/xrpc/sh.tangled.repo.rename"; + const METHOD: jacquard_common::xrpc::XrpcMethod = + jacquard_common::xrpc::XrpcMethod::Procedure("application/json"); + type Request = Rename; + type Response = RenameResponse; +} + +pub mod rename_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 Name; + type Repo; + type Rkey; + } + /// Empty state - all required fields are unset + pub struct Empty(()); + impl sealed::Sealed for Empty {} + impl State for Empty { + type Name = Unset; + type Repo = Unset; + type Rkey = Unset; + } + ///State transition - sets the `name` field to Set + pub struct SetName(PhantomData St>); + impl sealed::Sealed for SetName {} + impl State for SetName { + type Name = Set; + type Repo = St::Repo; + type Rkey = St::Rkey; + } + ///State transition - sets the `repo` field to Set + pub struct SetRepo(PhantomData St>); + impl sealed::Sealed for SetRepo {} + impl State for SetRepo { + type Name = St::Name; + type Repo = Set; + type Rkey = St::Rkey; + } + ///State transition - sets the `rkey` field to Set + pub struct SetRkey(PhantomData St>); + impl sealed::Sealed for SetRkey {} + impl State for SetRkey { + type Name = St::Name; + type Repo = St::Repo; + type Rkey = Set; + } + /// Marker types for field names + #[allow(non_camel_case_types)] + pub mod members { + ///Marker type for the `name` field + pub struct name(()); + ///Marker type for the `repo` field + pub struct repo(()); + ///Marker type for the `rkey` field + pub struct rkey(()); + } +} + +/// Builder for constructing an instance of this type. +pub struct RenameBuilder { + _state: PhantomData St>, + _fields: (Option, Option>, Option>>), + _type: PhantomData S>, +} + +impl Rename { + /// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed + pub fn new() -> RenameBuilder { + RenameBuilder::new() + } +} + +impl Rename { + /// Create a new builder for this type + pub fn builder() -> RenameBuilder { + RenameBuilder::builder() + } +} + +impl RenameBuilder { + /// Create a new builder with all fields unset, using the default string type, if needed + pub fn new() -> Self { + RenameBuilder { + _state: PhantomData, + _fields: (None, None, None), + _type: PhantomData, + } + } +} + +impl RenameBuilder { + /// Create a new builder with all fields unset + pub fn builder() -> Self { + RenameBuilder { + _state: PhantomData, + _fields: (None, None, None), + _type: PhantomData, + } + } +} + +impl RenameBuilder +where + St: rename_state::State, + St::Name: rename_state::IsUnset, +{ + /// Set the `name` field (required) + pub fn name(mut self, value: impl Into) -> RenameBuilder, S> { + self._fields.0 = Option::Some(value.into()); + RenameBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl RenameBuilder +where + St: rename_state::State, + St::Repo: rename_state::IsUnset, +{ + /// Set the `repo` field (required) + pub fn repo(mut self, value: impl Into>) -> RenameBuilder, S> { + self._fields.1 = Option::Some(value.into()); + RenameBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl RenameBuilder +where + St: rename_state::State, + St::Rkey: rename_state::IsUnset, +{ + /// Set the `rkey` field (required) + pub fn rkey( + mut self, + value: impl Into>>, + ) -> RenameBuilder, S> { + self._fields.2 = Option::Some(value.into()); + RenameBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl RenameBuilder +where + St: rename_state::State, + St::Name: rename_state::IsSet, + St::Repo: rename_state::IsSet, + St::Rkey: rename_state::IsSet, +{ + /// Build the final struct. + pub fn build(self) -> Rename { + Rename { + name: self._fields.0.unwrap(), + repo: self._fields.1.unwrap(), + rkey: 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>) -> Rename { + Rename { + name: self._fields.0.unwrap(), + repo: self._fields.1.unwrap(), + rkey: self._fields.2.unwrap(), + extra_data: Some(extra_data), + } + } +} diff --git a/crates/jacquard-api/src/sh_tangled/repo/reserve_key.rs b/crates/jacquard-api/src/sh_tangled/repo/reserve_key.rs new file mode 100644 index 000000000..4b7e2e2b5 --- /dev/null +++ b/crates/jacquard-api/src/sh_tangled/repo/reserve_key.rs @@ -0,0 +1,188 @@ +// @generated by jacquard-lexicon. DO NOT EDIT. +// +// Lexicon: sh.tangled.repo.reserveKey +// +// 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::deps::smol_str::SmolStr; +use jacquard_common::types::string::Did; +use jacquard_common::types::value::Data; +use jacquard_common::{BosStr, CowStr, DefaultStr, FromStaticStr}; +use jacquard_derive::IntoStatic; +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct ReserveKey { + ///The did:web identity the repository will use. + pub repo_did: Did, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct ReserveKeyOutput { + ///Multibase-encoded public key to publish in the did:web document. + pub key: S, + pub repo_did: Did, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +/** Response marker for the `sh.tangled.repo.reserveKey` procedure. + +Implements `jacquard_common::xrpc::XrpcResp`; successful bodies decode as `Self::Output`, which is `ReserveKeyOutput` for this endpoint.*/ +pub struct ReserveKeyResponse; +impl jacquard_common::xrpc::XrpcResp for ReserveKeyResponse { + const NSID: &'static str = "sh.tangled.repo.reserveKey"; + const ENCODING: &'static str = "application/json"; + type Output = ReserveKeyOutput; + type Err = jacquard_common::xrpc::GenericError; +} + +impl jacquard_common::xrpc::XrpcRequest for ReserveKey { + const NSID: &'static str = "sh.tangled.repo.reserveKey"; + const METHOD: jacquard_common::xrpc::XrpcMethod = + jacquard_common::xrpc::XrpcMethod::Procedure("application/json"); + type Response = ReserveKeyResponse; +} + +/** Endpoint marker for the `sh.tangled.repo.reserveKey` procedure. + +Path: `/xrpc/sh.tangled.repo.reserveKey`. The request payload type is `ReserveKey`; send that request with `jacquard::Client` or use this marker through lower-level `XrpcEndpoint` APIs.*/ +pub struct ReserveKeyRequest; +impl jacquard_common::xrpc::XrpcEndpoint for ReserveKeyRequest { + const PATH: &'static str = "/xrpc/sh.tangled.repo.reserveKey"; + const METHOD: jacquard_common::xrpc::XrpcMethod = + jacquard_common::xrpc::XrpcMethod::Procedure("application/json"); + type Request = ReserveKey; + type Response = ReserveKeyResponse; +} + +pub mod reserve_key_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 RepoDid; + } + /// Empty state - all required fields are unset + pub struct Empty(()); + impl sealed::Sealed for Empty {} + impl State for Empty { + type RepoDid = Unset; + } + ///State transition - sets the `repo_did` field to Set + pub struct SetRepoDid(PhantomData St>); + impl sealed::Sealed for SetRepoDid {} + impl State for SetRepoDid { + type RepoDid = Set; + } + /// Marker types for field names + #[allow(non_camel_case_types)] + pub mod members { + ///Marker type for the `repo_did` field + pub struct repo_did(()); + } +} + +/// Builder for constructing an instance of this type. +pub struct ReserveKeyBuilder { + _state: PhantomData St>, + _fields: (Option>,), + _type: PhantomData S>, +} + +impl ReserveKey { + /// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed + pub fn new() -> ReserveKeyBuilder { + ReserveKeyBuilder::new() + } +} + +impl ReserveKey { + /// Create a new builder for this type + pub fn builder() -> ReserveKeyBuilder { + ReserveKeyBuilder::builder() + } +} + +impl ReserveKeyBuilder { + /// Create a new builder with all fields unset, using the default string type, if needed + pub fn new() -> Self { + ReserveKeyBuilder { + _state: PhantomData, + _fields: (None,), + _type: PhantomData, + } + } +} + +impl ReserveKeyBuilder { + /// Create a new builder with all fields unset + pub fn builder() -> Self { + ReserveKeyBuilder { + _state: PhantomData, + _fields: (None,), + _type: PhantomData, + } + } +} + +impl ReserveKeyBuilder +where + St: reserve_key_state::State, + St::RepoDid: reserve_key_state::IsUnset, +{ + /// Set the `repoDid` field (required) + pub fn repo_did( + mut self, + value: impl Into>, + ) -> ReserveKeyBuilder, S> { + self._fields.0 = Option::Some(value.into()); + ReserveKeyBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl ReserveKeyBuilder +where + St: reserve_key_state::State, + St::RepoDid: reserve_key_state::IsSet, +{ + /// Build the final struct. + pub fn build(self) -> ReserveKey { + ReserveKey { + repo_did: self._fields.0.unwrap(), + extra_data: Default::default(), + } + } + /// Build the final struct with custom extra_data. + pub fn build_with_data(self, extra_data: BTreeMap>) -> ReserveKey { + ReserveKey { + repo_did: self._fields.0.unwrap(), + extra_data: Some(extra_data), + } + } +} diff --git a/crates/jacquard-api/src/sh_tangled/repo/set_default_branch.rs b/crates/jacquard-api/src/sh_tangled/repo/set_default_branch.rs index 763db05b2..08c9082a5 100644 --- a/crates/jacquard-api/src/sh_tangled/repo/set_default_branch.rs +++ b/crates/jacquard-api/src/sh_tangled/repo/set_default_branch.rs @@ -11,7 +11,7 @@ use alloc::collections::BTreeMap; #[allow(unused_imports)] use core::marker::PhantomData; use jacquard_common::deps::smol_str::SmolStr; -use jacquard_common::types::string::AtUri; +use jacquard_common::types::string::Did; use jacquard_common::types::value::Data; use jacquard_common::{BosStr, CowStr, DefaultStr, FromStaticStr}; use jacquard_derive::IntoStatic; @@ -24,7 +24,8 @@ use serde::{Deserialize, Serialize}; )] pub struct SetDefaultBranch { pub default_branch: S, - pub repo: AtUri, + ///DID of the repository + pub repo: Did, #[serde(flatten, default, skip_serializing_if = "Option::is_none")] pub extra_data: Option>>, } @@ -106,7 +107,7 @@ pub mod set_default_branch_state { /// Builder for constructing an instance of this type. pub struct SetDefaultBranchBuilder { _state: PhantomData St>, - _fields: (Option, Option>), + _fields: (Option, Option>), _type: PhantomData S>, } @@ -173,7 +174,7 @@ where /// Set the `repo` field (required) pub fn repo( mut self, - value: impl Into>, + value: impl Into>, ) -> SetDefaultBranchBuilder, S> { self._fields.1 = Option::Some(value.into()); SetDefaultBranchBuilder { diff --git a/crates/jacquard-api/src/sh_tangled/search.rs b/crates/jacquard-api/src/sh_tangled/search.rs new file mode 100644 index 000000000..a0a31919c --- /dev/null +++ b/crates/jacquard-api/src/sh_tangled/search.rs @@ -0,0 +1,7 @@ +// @generated by jacquard-lexicon. DO NOT EDIT. +// +// This file was automatically generated from Lexicon schemas. +// Any manual changes will be overwritten on the next regeneration. + +//! Generated bindings for the `sh.tangled.search` Lexicon namespace/module. +pub mod query; diff --git a/crates/jacquard-api/src/sh_tangled/search/query.rs b/crates/jacquard-api/src/sh_tangled/search/query.rs new file mode 100644 index 000000000..1ea68df28 --- /dev/null +++ b/crates/jacquard-api/src/sh_tangled/search/query.rs @@ -0,0 +1,731 @@ +// @generated by jacquard-lexicon. DO NOT EDIT. +// +// Lexicon: sh.tangled.search.query +// +// 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::string::{AtUri, Cid, Datetime, Did, Nsid}; +use jacquard_common::types::value::Data; +use jacquard_derive::IntoStatic; +use jacquard_lexicon::lexicon::LexiconDoc; +use jacquard_lexicon::schema::LexiconSchema; + +use crate::sh_tangled::search::query; +#[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", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct Hit { + #[serde(skip_serializing_if = "Option::is_none")] + pub cid: Option>, + ///Collection of the matched record. + pub nsid: Nsid, + ///Relevance score of the hit, a floating-point number where higher ranks first. + pub score: Data, + pub uri: AtUri, + ///Embedded matched record. + pub value: Data, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct Query { + #[serde(skip_serializing_if = "Option::is_none")] + pub author: Option>, + #[serde(skip_serializing_if = "Option::is_none")] + pub cursor: Option, + /// Defaults to `50`. Min: 1. Max: 1000. + #[serde(default = "_default_limit")] + #[serde(skip_serializing_if = "Option::is_none")] + pub limit: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub nsid: Option>, + pub q: S, + #[serde(skip_serializing_if = "Option::is_none")] + pub repo: Option>, + #[serde(skip_serializing_if = "Option::is_none")] + pub since: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub until: Option, +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct QueryOutput { + #[serde(skip_serializing_if = "Option::is_none")] + pub cursor: Option, + pub hits: Vec>, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +impl LexiconSchema for Hit { + fn nsid() -> &'static str { + "sh.tangled.search.query" + } + fn def_name() -> &'static str { + "hit" + } + fn lexicon_doc() -> LexiconDoc<'static> { + lexicon_doc_sh_tangled_search_query() + } + fn validate(&self) -> Result<(), ConstraintError> { + Ok(()) + } +} + +/** Response marker for the `sh.tangled.search.query` query. + +Implements `jacquard_common::xrpc::XrpcResp`; successful bodies decode as `Self::Output`, which is `QueryOutput` for this endpoint.*/ +pub struct QueryResponse; +impl jacquard_common::xrpc::XrpcResp for QueryResponse { + const NSID: &'static str = "sh.tangled.search.query"; + const ENCODING: &'static str = "application/json"; + type Output = QueryOutput; + type Err = jacquard_common::xrpc::GenericError; +} + +impl jacquard_common::xrpc::XrpcRequest for Query { + const NSID: &'static str = "sh.tangled.search.query"; + const METHOD: jacquard_common::xrpc::XrpcMethod = jacquard_common::xrpc::XrpcMethod::Query; + type Response = QueryResponse; +} + +/** Endpoint marker for the `sh.tangled.search.query` query. + +Path: `/xrpc/sh.tangled.search.query`. The request payload type is `Query`; send that request with `jacquard::Client` or use this marker through lower-level `XrpcEndpoint` APIs.*/ +pub struct QueryRequest; +impl jacquard_common::xrpc::XrpcEndpoint for QueryRequest { + const PATH: &'static str = "/xrpc/sh.tangled.search.query"; + const METHOD: jacquard_common::xrpc::XrpcMethod = jacquard_common::xrpc::XrpcMethod::Query; + type Request = Query; + type Response = QueryResponse; +} + +pub mod hit_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 Nsid; + type Score; + type Uri; + type Value; + } + /// Empty state - all required fields are unset + pub struct Empty(()); + impl sealed::Sealed for Empty {} + impl State for Empty { + type Nsid = Unset; + type Score = Unset; + type Uri = Unset; + type Value = Unset; + } + ///State transition - sets the `nsid` field to Set + pub struct SetNsid(PhantomData St>); + impl sealed::Sealed for SetNsid {} + impl State for SetNsid { + type Nsid = Set; + type Score = St::Score; + type Uri = St::Uri; + type Value = St::Value; + } + ///State transition - sets the `score` field to Set + pub struct SetScore(PhantomData St>); + impl sealed::Sealed for SetScore {} + impl State for SetScore { + type Nsid = St::Nsid; + type Score = Set; + type Uri = St::Uri; + type Value = St::Value; + } + ///State transition - sets the `uri` field to Set + pub struct SetUri(PhantomData St>); + impl sealed::Sealed for SetUri {} + impl State for SetUri { + type Nsid = St::Nsid; + type Score = St::Score; + type Uri = Set; + type Value = St::Value; + } + ///State transition - sets the `value` field to Set + pub struct SetValue(PhantomData St>); + impl sealed::Sealed for SetValue {} + impl State for SetValue { + type Nsid = St::Nsid; + type Score = St::Score; + type Uri = St::Uri; + type Value = Set; + } + /// Marker types for field names + #[allow(non_camel_case_types)] + pub mod members { + ///Marker type for the `nsid` field + pub struct nsid(()); + ///Marker type for the `score` field + pub struct score(()); + ///Marker type for the `uri` field + pub struct uri(()); + ///Marker type for the `value` field + pub struct value(()); + } +} + +/// Builder for constructing an instance of this type. +pub struct HitBuilder { + _state: PhantomData St>, + _fields: ( + Option>, + Option>, + Option>, + Option>, + Option>, + ), + _type: PhantomData S>, +} + +impl Hit { + /// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed + pub fn new() -> HitBuilder { + HitBuilder::new() + } +} + +impl Hit { + /// Create a new builder for this type + pub fn builder() -> HitBuilder { + HitBuilder::builder() + } +} + +impl HitBuilder { + /// Create a new builder with all fields unset, using the default string type, if needed + pub fn new() -> Self { + HitBuilder { + _state: PhantomData, + _fields: (None, None, None, None, None), + _type: PhantomData, + } + } +} + +impl HitBuilder { + /// Create a new builder with all fields unset + pub fn builder() -> Self { + HitBuilder { + _state: PhantomData, + _fields: (None, None, None, None, None), + _type: PhantomData, + } + } +} + +impl HitBuilder { + /// Set the `cid` field (optional) + pub fn cid(mut self, value: impl Into>>) -> Self { + self._fields.0 = value.into(); + self + } + /// Set the `cid` field to an Option value (optional) + pub fn maybe_cid(mut self, value: Option>) -> Self { + self._fields.0 = value; + self + } +} + +impl HitBuilder +where + St: hit_state::State, + St::Nsid: hit_state::IsUnset, +{ + /// Set the `nsid` field (required) + pub fn nsid(mut self, value: impl Into>) -> HitBuilder, S> { + self._fields.1 = Option::Some(value.into()); + HitBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl HitBuilder +where + St: hit_state::State, + St::Score: hit_state::IsUnset, +{ + /// Set the `score` field (required) + pub fn score(mut self, value: impl Into>) -> HitBuilder, S> { + self._fields.2 = Option::Some(value.into()); + HitBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl HitBuilder +where + St: hit_state::State, + St::Uri: hit_state::IsUnset, +{ + /// Set the `uri` field (required) + pub fn uri(mut self, value: impl Into>) -> HitBuilder, S> { + self._fields.3 = Option::Some(value.into()); + HitBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl HitBuilder +where + St: hit_state::State, + St::Value: hit_state::IsUnset, +{ + /// Set the `value` field (required) + pub fn value(mut self, value: impl Into>) -> HitBuilder, S> { + self._fields.4 = Option::Some(value.into()); + HitBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl HitBuilder +where + St: hit_state::State, + St::Nsid: hit_state::IsSet, + St::Score: hit_state::IsSet, + St::Uri: hit_state::IsSet, + St::Value: hit_state::IsSet, +{ + /// Build the final struct. + pub fn build(self) -> Hit { + Hit { + cid: self._fields.0, + nsid: self._fields.1.unwrap(), + score: self._fields.2.unwrap(), + uri: self._fields.3.unwrap(), + value: self._fields.4.unwrap(), + extra_data: Default::default(), + } + } + /// Build the final struct with custom extra_data. + pub fn build_with_data(self, extra_data: BTreeMap>) -> Hit { + Hit { + cid: self._fields.0, + nsid: self._fields.1.unwrap(), + score: self._fields.2.unwrap(), + uri: self._fields.3.unwrap(), + value: self._fields.4.unwrap(), + extra_data: Some(extra_data), + } + } +} + +fn lexicon_doc_sh_tangled_search_query() -> 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.search.query"), + defs: { + let mut map = BTreeMap::new(); + map.insert( + SmolStr::new_static("hit"), + LexUserType::Object(LexObject { + required: Some(vec![ + SmolStr::new_static("uri"), + SmolStr::new_static("nsid"), + SmolStr::new_static("score"), + SmolStr::new_static("value"), + ]), + properties: { + #[allow(unused_mut)] + let mut map = BTreeMap::new(); + map.insert( + SmolStr::new_static("cid"), + LexObjectProperty::String(LexString { + format: Some(LexStringFormat::Cid), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("nsid"), + LexObjectProperty::String(LexString { + description: Some(CowStr::new_static( + "Collection of the matched record.", + )), + format: Some(LexStringFormat::Nsid), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("score"), + LexObjectProperty::Unknown(LexUnknown { + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("uri"), + LexObjectProperty::String(LexString { + format: Some(LexStringFormat::AtUri), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("value"), + LexObjectProperty::Unknown(LexUnknown { + ..Default::default() + }), + ); + map + }, + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("main"), + LexUserType::XrpcQuery(LexXrpcQuery { + parameters: Some(LexXrpcQueryParameter::Params(LexXrpcParameters { + required: Some(vec![SmolStr::new_static("q")]), + properties: { + #[allow(unused_mut)] + let mut map = BTreeMap::new(); + map.insert( + SmolStr::new_static("author"), + LexXrpcParametersProperty::String(LexString { + description: Some(CowStr::new_static( + "Restrict to records authored by this DID.", + )), + format: Some(LexStringFormat::Did), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("cursor"), + LexXrpcParametersProperty::String(LexString { + description: Some(CowStr::new_static("Pagination cursor")), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("limit"), + LexXrpcParametersProperty::Integer(LexInteger { + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("nsid"), + LexXrpcParametersProperty::String(LexString { + description: Some(CowStr::new_static( + "Restrict to records of this collection.", + )), + format: Some(LexStringFormat::Nsid), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("q"), + LexXrpcParametersProperty::String(LexString { + description: Some(CowStr::new_static( + "Full-text search query.", + )), + min_length: Some(1usize), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("repo"), + LexXrpcParametersProperty::String(LexString { + description: Some(CowStr::new_static( + "Restrict to records under this repo DID.", + )), + format: Some(LexStringFormat::Did), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("since"), + LexXrpcParametersProperty::String(LexString { + description: Some(CowStr::new_static( + "Restrict to records created at or after this time.", + )), + format: Some(LexStringFormat::Datetime), + ..Default::default() + }), + ); + map.insert( + SmolStr::new_static("until"), + LexXrpcParametersProperty::String(LexString { + description: Some(CowStr::new_static( + "Restrict to records created at or before this time.", + )), + format: Some(LexStringFormat::Datetime), + ..Default::default() + }), + ); + map + }, + ..Default::default() + })), + ..Default::default() + }), + ); + map + }, + ..Default::default() + } +} + +fn _default_limit() -> Option { + Some(50i64) +} + +pub mod query_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 Q; + } + /// Empty state - all required fields are unset + pub struct Empty(()); + impl sealed::Sealed for Empty {} + impl State for Empty { + type Q = Unset; + } + ///State transition - sets the `q` field to Set + pub struct SetQ(PhantomData St>); + impl sealed::Sealed for SetQ {} + impl State for SetQ { + type Q = Set; + } + /// Marker types for field names + #[allow(non_camel_case_types)] + pub mod members { + ///Marker type for the `q` field + pub struct q(()); + } +} + +/// Builder for constructing an instance of this type. +pub struct QueryBuilder { + _state: PhantomData St>, + _fields: ( + Option>, + Option, + Option, + Option>, + Option, + Option>, + Option, + Option, + ), + _type: PhantomData S>, +} + +impl Query { + /// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed + pub fn new() -> QueryBuilder { + QueryBuilder::new() + } +} + +impl Query { + /// Create a new builder for this type + pub fn builder() -> QueryBuilder { + QueryBuilder::builder() + } +} + +impl QueryBuilder { + /// Create a new builder with all fields unset, using the default string type, if needed + pub fn new() -> Self { + QueryBuilder { + _state: PhantomData, + _fields: (None, None, None, None, None, None, None, None), + _type: PhantomData, + } + } +} + +impl QueryBuilder { + /// Create a new builder with all fields unset + pub fn builder() -> Self { + QueryBuilder { + _state: PhantomData, + _fields: (None, None, None, None, None, None, None, None), + _type: PhantomData, + } + } +} + +impl QueryBuilder { + /// Set the `author` field (optional) + pub fn author(mut self, value: impl Into>>) -> Self { + self._fields.0 = value.into(); + self + } + /// Set the `author` field to an Option value (optional) + pub fn maybe_author(mut self, value: Option>) -> Self { + self._fields.0 = value; + self + } +} + +impl QueryBuilder { + /// Set the `cursor` field (optional) + pub fn cursor(mut self, value: impl Into>) -> Self { + self._fields.1 = value.into(); + self + } + /// Set the `cursor` field to an Option value (optional) + pub fn maybe_cursor(mut self, value: Option) -> Self { + self._fields.1 = value; + self + } +} + +impl QueryBuilder { + /// Set the `limit` field (optional) + pub fn limit(mut self, value: impl Into>) -> Self { + self._fields.2 = value.into(); + self + } + /// Set the `limit` field to an Option value (optional) + pub fn maybe_limit(mut self, value: Option) -> Self { + self._fields.2 = value; + self + } +} + +impl QueryBuilder { + /// Set the `nsid` field (optional) + pub fn nsid(mut self, value: impl Into>>) -> Self { + self._fields.3 = value.into(); + self + } + /// Set the `nsid` field to an Option value (optional) + pub fn maybe_nsid(mut self, value: Option>) -> Self { + self._fields.3 = value; + self + } +} + +impl QueryBuilder +where + St: query_state::State, + St::Q: query_state::IsUnset, +{ + /// Set the `q` field (required) + pub fn q(mut self, value: impl Into) -> QueryBuilder, S> { + self._fields.4 = Option::Some(value.into()); + QueryBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl QueryBuilder { + /// Set the `repo` field (optional) + pub fn repo(mut self, value: impl Into>>) -> Self { + self._fields.5 = value.into(); + self + } + /// Set the `repo` field to an Option value (optional) + pub fn maybe_repo(mut self, value: Option>) -> Self { + self._fields.5 = value; + self + } +} + +impl QueryBuilder { + /// Set the `since` field (optional) + pub fn since(mut self, value: impl Into>) -> Self { + self._fields.6 = value.into(); + self + } + /// Set the `since` field to an Option value (optional) + pub fn maybe_since(mut self, value: Option) -> Self { + self._fields.6 = value; + self + } +} + +impl QueryBuilder { + /// Set the `until` field (optional) + pub fn until(mut self, value: impl Into>) -> Self { + self._fields.7 = value.into(); + self + } + /// Set the `until` field to an Option value (optional) + pub fn maybe_until(mut self, value: Option) -> Self { + self._fields.7 = value; + self + } +} + +impl QueryBuilder +where + St: query_state::State, + St::Q: query_state::IsSet, +{ + /// Build the final struct. + pub fn build(self) -> Query { + Query { + author: self._fields.0, + cursor: self._fields.1, + limit: self._fields.2, + nsid: self._fields.3, + q: self._fields.4.unwrap(), + repo: self._fields.5, + since: self._fields.6, + until: self._fields.7, + } + } +} diff --git a/crates/jacquard-api/src/sh_tangled/spindle.rs b/crates/jacquard-api/src/sh_tangled/spindle.rs index 2c539f679..38e6c60d5 100644 --- a/crates/jacquard-api/src/sh_tangled/spindle.rs +++ b/crates/jacquard-api/src/sh_tangled/spindle.rs @@ -6,6 +6,9 @@ // Any manual changes will be overwritten on the next regeneration. //! Generated bindings for the `sh.tangled.spindle` Lexicon namespace/module. +pub mod count_members; +pub mod count_members_by; +pub mod count_spindles; pub mod list_members; pub mod list_members_by; pub mod list_spindles; diff --git a/crates/jacquard-api/src/sh_tangled/spindle/count_members.rs b/crates/jacquard-api/src/sh_tangled/spindle/count_members.rs new file mode 100644 index 000000000..d10cdc3f7 --- /dev/null +++ b/crates/jacquard-api/src/sh_tangled/spindle/count_members.rs @@ -0,0 +1,175 @@ +// @generated by jacquard-lexicon. DO NOT EDIT. +// +// Lexicon: sh.tangled.spindle.countMembers +// +// 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::deps::smol_str::SmolStr; +use jacquard_common::types::value::Data; +use jacquard_common::{BosStr, CowStr, DefaultStr, FromStaticStr}; +use jacquard_derive::IntoStatic; +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct CountMembers { + pub subject: S, +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct CountMembersOutput { + ///Total number of matching records. + pub count: i64, + ///Number of distinct authors among the matching records. + pub distinct_authors: i64, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +/** Response marker for the `sh.tangled.spindle.countMembers` query. + +Implements `jacquard_common::xrpc::XrpcResp`; successful bodies decode as `Self::Output`, which is `CountMembersOutput` for this endpoint.*/ +pub struct CountMembersResponse; +impl jacquard_common::xrpc::XrpcResp for CountMembersResponse { + const NSID: &'static str = "sh.tangled.spindle.countMembers"; + const ENCODING: &'static str = "application/json"; + type Output = CountMembersOutput; + type Err = jacquard_common::xrpc::GenericError; +} + +impl jacquard_common::xrpc::XrpcRequest for CountMembers { + const NSID: &'static str = "sh.tangled.spindle.countMembers"; + const METHOD: jacquard_common::xrpc::XrpcMethod = jacquard_common::xrpc::XrpcMethod::Query; + type Response = CountMembersResponse; +} + +/** Endpoint marker for the `sh.tangled.spindle.countMembers` query. + +Path: `/xrpc/sh.tangled.spindle.countMembers`. The request payload type is `CountMembers`; send that request with `jacquard::Client` or use this marker through lower-level `XrpcEndpoint` APIs.*/ +pub struct CountMembersRequest; +impl jacquard_common::xrpc::XrpcEndpoint for CountMembersRequest { + const PATH: &'static str = "/xrpc/sh.tangled.spindle.countMembers"; + const METHOD: jacquard_common::xrpc::XrpcMethod = jacquard_common::xrpc::XrpcMethod::Query; + type Request = CountMembers; + type Response = CountMembersResponse; +} + +pub mod count_members_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 Subject; + } + /// Empty state - all required fields are unset + pub struct Empty(()); + impl sealed::Sealed for Empty {} + impl State for Empty { + type Subject = Unset; + } + ///State transition - sets the `subject` field to Set + pub struct SetSubject(PhantomData St>); + impl sealed::Sealed for SetSubject {} + impl State for SetSubject { + type Subject = Set; + } + /// Marker types for field names + #[allow(non_camel_case_types)] + pub mod members { + ///Marker type for the `subject` field + pub struct subject(()); + } +} + +/// Builder for constructing an instance of this type. +pub struct CountMembersBuilder { + _state: PhantomData St>, + _fields: (Option,), + _type: PhantomData S>, +} + +impl CountMembers { + /// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed + pub fn new() -> CountMembersBuilder { + CountMembersBuilder::new() + } +} + +impl CountMembers { + /// Create a new builder for this type + pub fn builder() -> CountMembersBuilder { + CountMembersBuilder::builder() + } +} + +impl CountMembersBuilder { + /// Create a new builder with all fields unset, using the default string type, if needed + pub fn new() -> Self { + CountMembersBuilder { + _state: PhantomData, + _fields: (None,), + _type: PhantomData, + } + } +} + +impl CountMembersBuilder { + /// Create a new builder with all fields unset + pub fn builder() -> Self { + CountMembersBuilder { + _state: PhantomData, + _fields: (None,), + _type: PhantomData, + } + } +} + +impl CountMembersBuilder +where + St: count_members_state::State, + St::Subject: count_members_state::IsUnset, +{ + /// Set the `subject` field (required) + pub fn subject( + mut self, + value: impl Into, + ) -> CountMembersBuilder, S> { + self._fields.0 = Option::Some(value.into()); + CountMembersBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl CountMembersBuilder +where + St: count_members_state::State, + St::Subject: count_members_state::IsSet, +{ + /// Build the final struct. + pub fn build(self) -> CountMembers { + CountMembers { + subject: self._fields.0.unwrap(), + } + } +} diff --git a/crates/jacquard-api/src/sh_tangled/spindle/count_members_by.rs b/crates/jacquard-api/src/sh_tangled/spindle/count_members_by.rs new file mode 100644 index 000000000..461d771a1 --- /dev/null +++ b/crates/jacquard-api/src/sh_tangled/spindle/count_members_by.rs @@ -0,0 +1,176 @@ +// @generated by jacquard-lexicon. DO NOT EDIT. +// +// Lexicon: sh.tangled.spindle.countMembersBy +// +// 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::deps::smol_str::SmolStr; +use jacquard_common::types::string::Did; +use jacquard_common::types::value::Data; +use jacquard_common::{BosStr, DefaultStr, FromStaticStr}; +use jacquard_derive::IntoStatic; +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct CountMembersBy { + pub subject: Did, +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct CountMembersByOutput { + ///Total number of matching records. + pub count: i64, + ///Number of distinct authors among the matching records. + pub distinct_authors: i64, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +/** Response marker for the `sh.tangled.spindle.countMembersBy` query. + +Implements `jacquard_common::xrpc::XrpcResp`; successful bodies decode as `Self::Output`, which is `CountMembersByOutput` for this endpoint.*/ +pub struct CountMembersByResponse; +impl jacquard_common::xrpc::XrpcResp for CountMembersByResponse { + const NSID: &'static str = "sh.tangled.spindle.countMembersBy"; + const ENCODING: &'static str = "application/json"; + type Output = CountMembersByOutput; + type Err = jacquard_common::xrpc::GenericError; +} + +impl jacquard_common::xrpc::XrpcRequest for CountMembersBy { + const NSID: &'static str = "sh.tangled.spindle.countMembersBy"; + const METHOD: jacquard_common::xrpc::XrpcMethod = jacquard_common::xrpc::XrpcMethod::Query; + type Response = CountMembersByResponse; +} + +/** Endpoint marker for the `sh.tangled.spindle.countMembersBy` query. + +Path: `/xrpc/sh.tangled.spindle.countMembersBy`. The request payload type is `CountMembersBy`; send that request with `jacquard::Client` or use this marker through lower-level `XrpcEndpoint` APIs.*/ +pub struct CountMembersByRequest; +impl jacquard_common::xrpc::XrpcEndpoint for CountMembersByRequest { + const PATH: &'static str = "/xrpc/sh.tangled.spindle.countMembersBy"; + const METHOD: jacquard_common::xrpc::XrpcMethod = jacquard_common::xrpc::XrpcMethod::Query; + type Request = CountMembersBy; + type Response = CountMembersByResponse; +} + +pub mod count_members_by_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 Subject; + } + /// Empty state - all required fields are unset + pub struct Empty(()); + impl sealed::Sealed for Empty {} + impl State for Empty { + type Subject = Unset; + } + ///State transition - sets the `subject` field to Set + pub struct SetSubject(PhantomData St>); + impl sealed::Sealed for SetSubject {} + impl State for SetSubject { + type Subject = Set; + } + /// Marker types for field names + #[allow(non_camel_case_types)] + pub mod members { + ///Marker type for the `subject` field + pub struct subject(()); + } +} + +/// Builder for constructing an instance of this type. +pub struct CountMembersByBuilder { + _state: PhantomData St>, + _fields: (Option>,), + _type: PhantomData S>, +} + +impl CountMembersBy { + /// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed + pub fn new() -> CountMembersByBuilder { + CountMembersByBuilder::new() + } +} + +impl CountMembersBy { + /// Create a new builder for this type + pub fn builder() -> CountMembersByBuilder { + CountMembersByBuilder::builder() + } +} + +impl CountMembersByBuilder { + /// Create a new builder with all fields unset, using the default string type, if needed + pub fn new() -> Self { + CountMembersByBuilder { + _state: PhantomData, + _fields: (None,), + _type: PhantomData, + } + } +} + +impl CountMembersByBuilder { + /// Create a new builder with all fields unset + pub fn builder() -> Self { + CountMembersByBuilder { + _state: PhantomData, + _fields: (None,), + _type: PhantomData, + } + } +} + +impl CountMembersByBuilder +where + St: count_members_by_state::State, + St::Subject: count_members_by_state::IsUnset, +{ + /// Set the `subject` field (required) + pub fn subject( + mut self, + value: impl Into>, + ) -> CountMembersByBuilder, S> { + self._fields.0 = Option::Some(value.into()); + CountMembersByBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl CountMembersByBuilder +where + St: count_members_by_state::State, + St::Subject: count_members_by_state::IsSet, +{ + /// Build the final struct. + pub fn build(self) -> CountMembersBy { + CountMembersBy { + subject: self._fields.0.unwrap(), + } + } +} diff --git a/crates/jacquard-api/src/sh_tangled/spindle/count_spindles.rs b/crates/jacquard-api/src/sh_tangled/spindle/count_spindles.rs new file mode 100644 index 000000000..728c76c72 --- /dev/null +++ b/crates/jacquard-api/src/sh_tangled/spindle/count_spindles.rs @@ -0,0 +1,176 @@ +// @generated by jacquard-lexicon. DO NOT EDIT. +// +// Lexicon: sh.tangled.spindle.countSpindles +// +// 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::deps::smol_str::SmolStr; +use jacquard_common::types::string::Did; +use jacquard_common::types::value::Data; +use jacquard_common::{BosStr, DefaultStr, FromStaticStr}; +use jacquard_derive::IntoStatic; +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct CountSpindles { + pub subject: Did, +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct CountSpindlesOutput { + ///Total number of matching records. + pub count: i64, + ///Number of distinct authors among the matching records. + pub distinct_authors: i64, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +/** Response marker for the `sh.tangled.spindle.countSpindles` query. + +Implements `jacquard_common::xrpc::XrpcResp`; successful bodies decode as `Self::Output`, which is `CountSpindlesOutput` for this endpoint.*/ +pub struct CountSpindlesResponse; +impl jacquard_common::xrpc::XrpcResp for CountSpindlesResponse { + const NSID: &'static str = "sh.tangled.spindle.countSpindles"; + const ENCODING: &'static str = "application/json"; + type Output = CountSpindlesOutput; + type Err = jacquard_common::xrpc::GenericError; +} + +impl jacquard_common::xrpc::XrpcRequest for CountSpindles { + const NSID: &'static str = "sh.tangled.spindle.countSpindles"; + const METHOD: jacquard_common::xrpc::XrpcMethod = jacquard_common::xrpc::XrpcMethod::Query; + type Response = CountSpindlesResponse; +} + +/** Endpoint marker for the `sh.tangled.spindle.countSpindles` query. + +Path: `/xrpc/sh.tangled.spindle.countSpindles`. The request payload type is `CountSpindles`; send that request with `jacquard::Client` or use this marker through lower-level `XrpcEndpoint` APIs.*/ +pub struct CountSpindlesRequest; +impl jacquard_common::xrpc::XrpcEndpoint for CountSpindlesRequest { + const PATH: &'static str = "/xrpc/sh.tangled.spindle.countSpindles"; + const METHOD: jacquard_common::xrpc::XrpcMethod = jacquard_common::xrpc::XrpcMethod::Query; + type Request = CountSpindles; + type Response = CountSpindlesResponse; +} + +pub mod count_spindles_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 Subject; + } + /// Empty state - all required fields are unset + pub struct Empty(()); + impl sealed::Sealed for Empty {} + impl State for Empty { + type Subject = Unset; + } + ///State transition - sets the `subject` field to Set + pub struct SetSubject(PhantomData St>); + impl sealed::Sealed for SetSubject {} + impl State for SetSubject { + type Subject = Set; + } + /// Marker types for field names + #[allow(non_camel_case_types)] + pub mod members { + ///Marker type for the `subject` field + pub struct subject(()); + } +} + +/// Builder for constructing an instance of this type. +pub struct CountSpindlesBuilder { + _state: PhantomData St>, + _fields: (Option>,), + _type: PhantomData S>, +} + +impl CountSpindles { + /// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed + pub fn new() -> CountSpindlesBuilder { + CountSpindlesBuilder::new() + } +} + +impl CountSpindles { + /// Create a new builder for this type + pub fn builder() -> CountSpindlesBuilder { + CountSpindlesBuilder::builder() + } +} + +impl CountSpindlesBuilder { + /// Create a new builder with all fields unset, using the default string type, if needed + pub fn new() -> Self { + CountSpindlesBuilder { + _state: PhantomData, + _fields: (None,), + _type: PhantomData, + } + } +} + +impl CountSpindlesBuilder { + /// Create a new builder with all fields unset + pub fn builder() -> Self { + CountSpindlesBuilder { + _state: PhantomData, + _fields: (None,), + _type: PhantomData, + } + } +} + +impl CountSpindlesBuilder +where + St: count_spindles_state::State, + St::Subject: count_spindles_state::IsUnset, +{ + /// Set the `subject` field (required) + pub fn subject( + mut self, + value: impl Into>, + ) -> CountSpindlesBuilder, S> { + self._fields.0 = Option::Some(value.into()); + CountSpindlesBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl CountSpindlesBuilder +where + St: count_spindles_state::State, + St::Subject: count_spindles_state::IsSet, +{ + /// Build the final struct. + pub fn build(self) -> CountSpindles { + CountSpindles { + subject: self._fields.0.unwrap(), + } + } +} diff --git a/crates/jacquard-api/src/sh_tangled/string.rs b/crates/jacquard-api/src/sh_tangled/string.rs index ab8c4b8e8..02c13bcff 100644 --- a/crates/jacquard-api/src/sh_tangled/string.rs +++ b/crates/jacquard-api/src/sh_tangled/string.rs @@ -6,6 +6,7 @@ // Any manual changes will be overwritten on the next regeneration. //! Generated bindings for the `sh.tangled.string` Lexicon namespace/module. +pub mod count_strings; pub mod list_strings; #[allow(unused_imports)] diff --git a/crates/jacquard-api/src/sh_tangled/string/count_strings.rs b/crates/jacquard-api/src/sh_tangled/string/count_strings.rs new file mode 100644 index 000000000..1a3c39ae9 --- /dev/null +++ b/crates/jacquard-api/src/sh_tangled/string/count_strings.rs @@ -0,0 +1,175 @@ +// @generated by jacquard-lexicon. DO NOT EDIT. +// +// Lexicon: sh.tangled.string.countStrings +// +// 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::deps::smol_str::SmolStr; +use jacquard_common::types::value::Data; +use jacquard_common::{BosStr, CowStr, DefaultStr, FromStaticStr}; +use jacquard_derive::IntoStatic; +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct CountStrings { + pub subject: S, +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct CountStringsOutput { + ///Total number of matching records. + pub count: i64, + ///Number of distinct authors among the matching records. + pub distinct_authors: i64, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +/** Response marker for the `sh.tangled.string.countStrings` query. + +Implements `jacquard_common::xrpc::XrpcResp`; successful bodies decode as `Self::Output`, which is `CountStringsOutput` for this endpoint.*/ +pub struct CountStringsResponse; +impl jacquard_common::xrpc::XrpcResp for CountStringsResponse { + const NSID: &'static str = "sh.tangled.string.countStrings"; + const ENCODING: &'static str = "application/json"; + type Output = CountStringsOutput; + type Err = jacquard_common::xrpc::GenericError; +} + +impl jacquard_common::xrpc::XrpcRequest for CountStrings { + const NSID: &'static str = "sh.tangled.string.countStrings"; + const METHOD: jacquard_common::xrpc::XrpcMethod = jacquard_common::xrpc::XrpcMethod::Query; + type Response = CountStringsResponse; +} + +/** Endpoint marker for the `sh.tangled.string.countStrings` query. + +Path: `/xrpc/sh.tangled.string.countStrings`. The request payload type is `CountStrings`; send that request with `jacquard::Client` or use this marker through lower-level `XrpcEndpoint` APIs.*/ +pub struct CountStringsRequest; +impl jacquard_common::xrpc::XrpcEndpoint for CountStringsRequest { + const PATH: &'static str = "/xrpc/sh.tangled.string.countStrings"; + const METHOD: jacquard_common::xrpc::XrpcMethod = jacquard_common::xrpc::XrpcMethod::Query; + type Request = CountStrings; + type Response = CountStringsResponse; +} + +pub mod count_strings_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 Subject; + } + /// Empty state - all required fields are unset + pub struct Empty(()); + impl sealed::Sealed for Empty {} + impl State for Empty { + type Subject = Unset; + } + ///State transition - sets the `subject` field to Set + pub struct SetSubject(PhantomData St>); + impl sealed::Sealed for SetSubject {} + impl State for SetSubject { + type Subject = Set; + } + /// Marker types for field names + #[allow(non_camel_case_types)] + pub mod members { + ///Marker type for the `subject` field + pub struct subject(()); + } +} + +/// Builder for constructing an instance of this type. +pub struct CountStringsBuilder { + _state: PhantomData St>, + _fields: (Option,), + _type: PhantomData S>, +} + +impl CountStrings { + /// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed + pub fn new() -> CountStringsBuilder { + CountStringsBuilder::new() + } +} + +impl CountStrings { + /// Create a new builder for this type + pub fn builder() -> CountStringsBuilder { + CountStringsBuilder::builder() + } +} + +impl CountStringsBuilder { + /// Create a new builder with all fields unset, using the default string type, if needed + pub fn new() -> Self { + CountStringsBuilder { + _state: PhantomData, + _fields: (None,), + _type: PhantomData, + } + } +} + +impl CountStringsBuilder { + /// Create a new builder with all fields unset + pub fn builder() -> Self { + CountStringsBuilder { + _state: PhantomData, + _fields: (None,), + _type: PhantomData, + } + } +} + +impl CountStringsBuilder +where + St: count_strings_state::State, + St::Subject: count_strings_state::IsUnset, +{ + /// Set the `subject` field (required) + pub fn subject( + mut self, + value: impl Into, + ) -> CountStringsBuilder, S> { + self._fields.0 = Option::Some(value.into()); + CountStringsBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl CountStringsBuilder +where + St: count_strings_state::State, + St::Subject: count_strings_state::IsSet, +{ + /// Build the final struct. + pub fn build(self) -> CountStrings { + CountStrings { + subject: self._fields.0.unwrap(), + } + } +} diff --git a/crates/jacquard-api/src/sh_weaver/actor.rs b/crates/jacquard-api/src/sh_weaver/actor.rs index 3963111f5..cc51ddb31 100644 --- a/crates/jacquard-api/src/sh_weaver/actor.rs +++ b/crates/jacquard-api/src/sh_weaver/actor.rs @@ -439,6 +439,42 @@ impl LexiconSchema for ProfileView { } } } + if let Some(ref value) = self.pronouns { + #[allow(unused_comparisons)] + if value.len() > 5usize { + return Err(ConstraintError::MaxLength { + path: ValidationPath::from_field("pronouns"), + max: 5usize, + actual: value.len(), + }); + } + } + if let Some(values) = &self.pronouns { + for value in values { + #[allow(unused_comparisons)] + if ::len(value.as_ref()) > 500usize { + return Err(ConstraintError::MaxLength { + path: ValidationPath::from_field("pronouns"), + max: 500usize, + actual: ::len(value.as_ref()), + }); + } + } + } + if let Some(values) = &self.pronouns { + for value in values { + { + let count = UnicodeSegmentation::graphemes(value.as_ref(), true).count(); + if count > 50usize { + return Err(ConstraintError::MaxGraphemes { + path: ValidationPath::from_field("pronouns"), + max: 50usize, + actual: count, + }); + } + } + } + } Ok(()) } } @@ -476,6 +512,42 @@ impl LexiconSchema for ProfileViewBasic { } } } + if let Some(ref value) = self.pronouns { + #[allow(unused_comparisons)] + if value.len() > 5usize { + return Err(ConstraintError::MaxLength { + path: ValidationPath::from_field("pronouns"), + max: 5usize, + actual: value.len(), + }); + } + } + if let Some(values) = &self.pronouns { + for value in values { + #[allow(unused_comparisons)] + if ::len(value.as_ref()) > 500usize { + return Err(ConstraintError::MaxLength { + path: ValidationPath::from_field("pronouns"), + max: 500usize, + actual: ::len(value.as_ref()), + }); + } + } + } + if let Some(values) = &self.pronouns { + for value in values { + { + let count = UnicodeSegmentation::graphemes(value.as_ref(), true).count(); + if count > 50usize { + return Err(ConstraintError::MaxGraphemes { + path: ValidationPath::from_field("pronouns"), + max: 50usize, + actual: count, + }); + } + } + } + } Ok(()) } } diff --git a/crates/jacquard-api/src/sh_weaver/actor/profile.rs b/crates/jacquard-api/src/sh_weaver/actor/profile.rs index 0072bb71a..9560b2d1f 100644 --- a/crates/jacquard-api/src/sh_weaver/actor/profile.rs +++ b/crates/jacquard-api/src/sh_weaver/actor/profile.rs @@ -292,6 +292,42 @@ impl LexiconSchema for Profile { } } } + if let Some(ref value) = self.pronouns { + #[allow(unused_comparisons)] + if value.len() > 5usize { + return Err(ConstraintError::MaxLength { + path: ValidationPath::from_field("pronouns"), + max: 5usize, + actual: value.len(), + }); + } + } + if let Some(values) = &self.pronouns { + for value in values { + #[allow(unused_comparisons)] + if ::len(value.as_ref()) > 500usize { + return Err(ConstraintError::MaxLength { + path: ValidationPath::from_field("pronouns"), + max: 500usize, + actual: ::len(value.as_ref()), + }); + } + } + } + if let Some(values) = &self.pronouns { + for value in values { + { + let count = UnicodeSegmentation::graphemes(value.as_ref(), true).count(); + if count > 50usize { + return Err(ConstraintError::MaxGraphemes { + path: ValidationPath::from_field("pronouns"), + max: 50usize, + actual: count, + }); + } + } + } + } Ok(()) } } diff --git a/crates/jacquard-api/src/sh_weaver/notebook.rs b/crates/jacquard-api/src/sh_weaver/notebook.rs index 787a53a75..cff307944 100644 --- a/crates/jacquard-api/src/sh_weaver/notebook.rs +++ b/crates/jacquard-api/src/sh_weaver/notebook.rs @@ -877,6 +877,38 @@ impl LexiconSchema for ChapterView { lexicon_doc_sh_weaver_notebook_defs() } fn validate(&self) -> Result<(), ConstraintError> { + if let Some(ref value) = self.tags { + #[allow(unused_comparisons)] + if value.len() > 10usize { + return Err(ConstraintError::MaxLength { + path: ValidationPath::from_field("tags"), + max: 10usize, + actual: value.len(), + }); + } + } + if let Some(values) = &self.tags { + for value in values { + #[allow(unused_comparisons)] + if ::len(value.as_ref()) > 64usize { + return Err(ConstraintError::MaxLength { + path: ValidationPath::from_field("tags"), + max: 64usize, + actual: ::len(value.as_ref()), + }); + } + } + } + if let Some(ref value) = self.title { + #[allow(unused_comparisons)] + if ::len(value.as_ref()) > 300usize { + return Err(ConstraintError::MaxLength { + path: ValidationPath::from_field("title"), + max: 300usize, + actual: ::len(value.as_ref()), + }); + } + } Ok(()) } } @@ -907,6 +939,48 @@ impl LexiconSchema for EntryView { lexicon_doc_sh_weaver_notebook_defs() } fn validate(&self) -> Result<(), ConstraintError> { + if let Some(ref value) = self.path { + #[allow(unused_comparisons)] + if ::len(value.as_ref()) > 100usize { + return Err(ConstraintError::MaxLength { + path: ValidationPath::from_field("path"), + max: 100usize, + actual: ::len(value.as_ref()), + }); + } + } + if let Some(ref value) = self.tags { + #[allow(unused_comparisons)] + if value.len() > 10usize { + return Err(ConstraintError::MaxLength { + path: ValidationPath::from_field("tags"), + max: 10usize, + actual: value.len(), + }); + } + } + if let Some(values) = &self.tags { + for value in values { + #[allow(unused_comparisons)] + if ::len(value.as_ref()) > 64usize { + return Err(ConstraintError::MaxLength { + path: ValidationPath::from_field("tags"), + max: 64usize, + actual: ::len(value.as_ref()), + }); + } + } + } + if let Some(ref value) = self.title { + #[allow(unused_comparisons)] + if ::len(value.as_ref()) > 300usize { + return Err(ConstraintError::MaxLength { + path: ValidationPath::from_field("title"), + max: 300usize, + actual: ::len(value.as_ref()), + }); + } + } Ok(()) } } @@ -952,6 +1026,48 @@ impl LexiconSchema for NotebookView { lexicon_doc_sh_weaver_notebook_defs() } fn validate(&self) -> Result<(), ConstraintError> { + if let Some(ref value) = self.path { + #[allow(unused_comparisons)] + if ::len(value.as_ref()) > 100usize { + return Err(ConstraintError::MaxLength { + path: ValidationPath::from_field("path"), + max: 100usize, + actual: ::len(value.as_ref()), + }); + } + } + if let Some(ref value) = self.tags { + #[allow(unused_comparisons)] + if value.len() > 10usize { + return Err(ConstraintError::MaxLength { + path: ValidationPath::from_field("tags"), + max: 10usize, + actual: value.len(), + }); + } + } + if let Some(values) = &self.tags { + for value in values { + #[allow(unused_comparisons)] + if ::len(value.as_ref()) > 64usize { + return Err(ConstraintError::MaxLength { + path: ValidationPath::from_field("tags"), + max: 64usize, + actual: ::len(value.as_ref()), + }); + } + } + } + if let Some(ref value) = self.title { + #[allow(unused_comparisons)] + if ::len(value.as_ref()) > 300usize { + return Err(ConstraintError::MaxLength { + path: ValidationPath::from_field("title"), + max: 300usize, + actual: ::len(value.as_ref()), + }); + } + } Ok(()) } } @@ -967,6 +1083,38 @@ impl LexiconSchema for PageView { lexicon_doc_sh_weaver_notebook_defs() } fn validate(&self) -> Result<(), ConstraintError> { + if let Some(ref value) = self.tags { + #[allow(unused_comparisons)] + if value.len() > 10usize { + return Err(ConstraintError::MaxLength { + path: ValidationPath::from_field("tags"), + max: 10usize, + actual: value.len(), + }); + } + } + if let Some(values) = &self.tags { + for value in values { + #[allow(unused_comparisons)] + if ::len(value.as_ref()) > 64usize { + return Err(ConstraintError::MaxLength { + path: ValidationPath::from_field("tags"), + max: 64usize, + actual: ::len(value.as_ref()), + }); + } + } + } + if let Some(ref value) = self.title { + #[allow(unused_comparisons)] + if ::len(value.as_ref()) > 300usize { + return Err(ConstraintError::MaxLength { + path: ValidationPath::from_field("title"), + max: 300usize, + actual: ::len(value.as_ref()), + }); + } + } Ok(()) } } diff --git a/crates/jacquard-api/src/sh_weaver/notebook/book.rs b/crates/jacquard-api/src/sh_weaver/notebook/book.rs index 68f2b5bc2..2698f409e 100644 --- a/crates/jacquard-api/src/sh_weaver/notebook/book.rs +++ b/crates/jacquard-api/src/sh_weaver/notebook/book.rs @@ -126,6 +126,58 @@ impl LexiconSchema for Book { lexicon_doc_sh_weaver_notebook_book() } fn validate(&self) -> Result<(), ConstraintError> { + if let Some(ref value) = self.content_warnings { + #[allow(unused_comparisons)] + if value.len() > 10usize { + return Err(ConstraintError::MaxLength { + path: ValidationPath::from_field("content_warnings"), + max: 10usize, + actual: value.len(), + }); + } + } + if let Some(ref value) = self.path { + #[allow(unused_comparisons)] + if ::len(value.as_ref()) > 100usize { + return Err(ConstraintError::MaxLength { + path: ValidationPath::from_field("path"), + max: 100usize, + actual: ::len(value.as_ref()), + }); + } + } + if let Some(ref value) = self.tags { + #[allow(unused_comparisons)] + if value.len() > 10usize { + return Err(ConstraintError::MaxLength { + path: ValidationPath::from_field("tags"), + max: 10usize, + actual: value.len(), + }); + } + } + if let Some(values) = &self.tags { + for value in values { + #[allow(unused_comparisons)] + if ::len(value.as_ref()) > 64usize { + return Err(ConstraintError::MaxLength { + path: ValidationPath::from_field("tags"), + max: 64usize, + actual: ::len(value.as_ref()), + }); + } + } + } + if let Some(ref value) = self.title { + #[allow(unused_comparisons)] + if ::len(value.as_ref()) > 300usize { + return Err(ConstraintError::MaxLength { + path: ValidationPath::from_field("title"), + max: 300usize, + actual: ::len(value.as_ref()), + }); + } + } Ok(()) } } diff --git a/crates/jacquard-api/src/sh_weaver/notebook/chapter.rs b/crates/jacquard-api/src/sh_weaver/notebook/chapter.rs index fffe1b024..46739d008 100644 --- a/crates/jacquard-api/src/sh_weaver/notebook/chapter.rs +++ b/crates/jacquard-api/src/sh_weaver/notebook/chapter.rs @@ -117,6 +117,48 @@ impl LexiconSchema for Chapter { lexicon_doc_sh_weaver_notebook_chapter() } fn validate(&self) -> Result<(), ConstraintError> { + if let Some(ref value) = self.content_warnings { + #[allow(unused_comparisons)] + if value.len() > 10usize { + return Err(ConstraintError::MaxLength { + path: ValidationPath::from_field("content_warnings"), + max: 10usize, + actual: value.len(), + }); + } + } + if let Some(ref value) = self.tags { + #[allow(unused_comparisons)] + if value.len() > 10usize { + return Err(ConstraintError::MaxLength { + path: ValidationPath::from_field("tags"), + max: 10usize, + actual: value.len(), + }); + } + } + if let Some(values) = &self.tags { + for value in values { + #[allow(unused_comparisons)] + if ::len(value.as_ref()) > 64usize { + return Err(ConstraintError::MaxLength { + path: ValidationPath::from_field("tags"), + max: 64usize, + actual: ::len(value.as_ref()), + }); + } + } + } + if let Some(ref value) = self.title { + #[allow(unused_comparisons)] + if ::len(value.as_ref()) > 300usize { + return Err(ConstraintError::MaxLength { + path: ValidationPath::from_field("title"), + max: 300usize, + actual: ::len(value.as_ref()), + }); + } + } Ok(()) } } diff --git a/crates/jacquard-api/src/sh_weaver/notebook/entry.rs b/crates/jacquard-api/src/sh_weaver/notebook/entry.rs index 5ed9d6fe4..34691321f 100644 --- a/crates/jacquard-api/src/sh_weaver/notebook/entry.rs +++ b/crates/jacquard-api/src/sh_weaver/notebook/entry.rs @@ -145,6 +145,60 @@ impl LexiconSchema for Entry { lexicon_doc_sh_weaver_notebook_entry() } fn validate(&self) -> Result<(), ConstraintError> { + if let Some(ref value) = self.content_warnings { + #[allow(unused_comparisons)] + if value.len() > 10usize { + return Err(ConstraintError::MaxLength { + path: ValidationPath::from_field("content_warnings"), + max: 10usize, + actual: value.len(), + }); + } + } + { + let value = &self.path; + #[allow(unused_comparisons)] + if ::len(value.as_ref()) > 100usize { + return Err(ConstraintError::MaxLength { + path: ValidationPath::from_field("path"), + max: 100usize, + actual: ::len(value.as_ref()), + }); + } + } + if let Some(ref value) = self.tags { + #[allow(unused_comparisons)] + if value.len() > 10usize { + return Err(ConstraintError::MaxLength { + path: ValidationPath::from_field("tags"), + max: 10usize, + actual: value.len(), + }); + } + } + if let Some(values) = &self.tags { + for value in values { + #[allow(unused_comparisons)] + if ::len(value.as_ref()) > 64usize { + return Err(ConstraintError::MaxLength { + path: ValidationPath::from_field("tags"), + max: 64usize, + actual: ::len(value.as_ref()), + }); + } + } + } + { + let value = &self.title; + #[allow(unused_comparisons)] + if ::len(value.as_ref()) > 300usize { + return Err(ConstraintError::MaxLength { + path: ValidationPath::from_field("title"), + max: 300usize, + actual: ::len(value.as_ref()), + }); + } + } Ok(()) } } diff --git a/crates/jacquard-api/src/sh_weaver/notebook/page.rs b/crates/jacquard-api/src/sh_weaver/notebook/page.rs index 50f0a8f7e..622ae169e 100644 --- a/crates/jacquard-api/src/sh_weaver/notebook/page.rs +++ b/crates/jacquard-api/src/sh_weaver/notebook/page.rs @@ -109,6 +109,38 @@ impl LexiconSchema for Page { lexicon_doc_sh_weaver_notebook_page() } fn validate(&self) -> Result<(), ConstraintError> { + if let Some(ref value) = self.tags { + #[allow(unused_comparisons)] + if value.len() > 10usize { + return Err(ConstraintError::MaxLength { + path: ValidationPath::from_field("tags"), + max: 10usize, + actual: value.len(), + }); + } + } + if let Some(values) = &self.tags { + for value in values { + #[allow(unused_comparisons)] + if ::len(value.as_ref()) > 64usize { + return Err(ConstraintError::MaxLength { + path: ValidationPath::from_field("tags"), + max: 64usize, + actual: ::len(value.as_ref()), + }); + } + } + } + if let Some(ref value) = self.title { + #[allow(unused_comparisons)] + if ::len(value.as_ref()) > 300usize { + return Err(ConstraintError::MaxLength { + path: ValidationPath::from_field("title"), + max: 300usize, + actual: ::len(value.as_ref()), + }); + } + } Ok(()) } } diff --git a/crates/jacquard-api/src/site_standard/document.rs b/crates/jacquard-api/src/site_standard/document.rs index e68129510..a69787aba 100644 --- a/crates/jacquard-api/src/site_standard/document.rs +++ b/crates/jacquard-api/src/site_standard/document.rs @@ -270,6 +270,32 @@ impl LexiconSchema for Document { } } } + if let Some(values) = &self.tags { + for value in values { + #[allow(unused_comparisons)] + if ::len(value.as_ref()) > 1280usize { + return Err(ConstraintError::MaxLength { + path: ValidationPath::from_field("tags"), + max: 1280usize, + actual: ::len(value.as_ref()), + }); + } + } + } + if let Some(values) = &self.tags { + for value in values { + { + let count = UnicodeSegmentation::graphemes(value.as_ref(), true).count(); + if count > 128usize { + return Err(ConstraintError::MaxGraphemes { + path: ValidationPath::from_field("tags"), + max: 128usize, + actual: count, + }); + } + } + } + } { let value = &self.title; #[allow(unused_comparisons)] diff --git a/crates/jacquard-api/src/social_arabica/alpha/bean.rs b/crates/jacquard-api/src/social_arabica/alpha/bean.rs index 6f238f685..1bceaf2b4 100644 --- a/crates/jacquard-api/src/social_arabica/alpha/bean.rs +++ b/crates/jacquard-api/src/social_arabica/alpha/bean.rs @@ -138,10 +138,10 @@ impl LexiconSchema for Bean { fn validate(&self) -> Result<(), ConstraintError> { if let Some(ref value) = self.description { #[allow(unused_comparisons)] - if ::len(value.as_ref()) > 1000usize { + if ::len(value.as_ref()) > 5000usize { return Err(ConstraintError::MaxLength { path: ValidationPath::from_field("description"), - max: 1000usize, + max: 5000usize, actual: ::len(value.as_ref()), }); } @@ -647,7 +647,7 @@ fn lexicon_doc_social_arabica_alpha_bean() -> LexiconDoc<'static> { "Public roaster description or tasting notes for the beans", ), ), - max_length: Some(1000usize), + max_length: Some(5000usize), ..Default::default() }), ); diff --git a/crates/jacquard-api/src/social_arabica/alpha/brew.rs b/crates/jacquard-api/src/social_arabica/alpha/brew.rs index 050836fdc..12ef6add6 100644 --- a/crates/jacquard-api/src/social_arabica/alpha/brew.rs +++ b/crates/jacquard-api/src/social_arabica/alpha/brew.rs @@ -96,7 +96,7 @@ pub struct Brew { ///Tasting notes and observations about the brew #[serde(skip_serializing_if = "Option::is_none")] pub tasting_notes: Option, - ///Water temperature in tenths of a degree Celsius (e.g., 935 = 93.5°C) + ///Water temperature in tenths of a degree Celsius or Fahrenheit (e.g., 935 = 93.5°C) #[serde(skip_serializing_if = "Option::is_none")] pub temperature: Option, ///Total brew time in seconds @@ -307,10 +307,10 @@ impl LexiconSchema for Brew { } } if let Some(ref value) = self.temperature { - if *value > 1000i64 { + if *value > 2120i64 { return Err(ConstraintError::Maximum { path: ValidationPath::from_field("temperature"), - max: 1000i64, + max: 2120i64, actual: *value, }); } @@ -646,7 +646,7 @@ fn lexicon_doc_social_arabica_alpha_brew() -> LexiconDoc<'static> { SmolStr::new_static("temperature"), LexObjectProperty::Integer(LexInteger { minimum: Some(0i64), - maximum: Some(1000i64), + maximum: Some(2120i64), ..Default::default() }), ); diff --git a/crates/jacquard-api/src/social_coves.rs b/crates/jacquard-api/src/social_coves.rs new file mode 100644 index 000000000..e69de29bb diff --git a/crates/jacquard-api/src/social_coves/actor.rs b/crates/jacquard-api/src/social_coves/actor.rs new file mode 100644 index 000000000..e69de29bb diff --git a/crates/jacquard-api/src/social_coves/actor/block.rs b/crates/jacquard-api/src/social_coves/actor/block.rs new file mode 100644 index 000000000..e69de29bb diff --git a/crates/jacquard-api/src/social_coves/actor/get_comments.rs b/crates/jacquard-api/src/social_coves/actor/get_comments.rs new file mode 100644 index 000000000..e69de29bb diff --git a/crates/jacquard-api/src/social_coves/actor/get_posts.rs b/crates/jacquard-api/src/social_coves/actor/get_posts.rs new file mode 100644 index 000000000..e69de29bb diff --git a/crates/jacquard-api/src/social_coves/actor/get_profile.rs b/crates/jacquard-api/src/social_coves/actor/get_profile.rs new file mode 100644 index 000000000..e69de29bb diff --git a/crates/jacquard-api/src/social_coves/actor/profile.rs b/crates/jacquard-api/src/social_coves/actor/profile.rs new file mode 100644 index 000000000..e69de29bb diff --git a/crates/jacquard-api/src/social_coves/actor/signup.rs b/crates/jacquard-api/src/social_coves/actor/signup.rs new file mode 100644 index 000000000..e69de29bb diff --git a/crates/jacquard-api/src/social_coves/actor/update_profile.rs b/crates/jacquard-api/src/social_coves/actor/update_profile.rs new file mode 100644 index 000000000..e69de29bb diff --git a/crates/jacquard-api/src/social_coves/aggregator.rs b/crates/jacquard-api/src/social_coves/aggregator.rs new file mode 100644 index 000000000..e69de29bb diff --git a/crates/jacquard-api/src/social_coves/aggregator/authorization.rs b/crates/jacquard-api/src/social_coves/aggregator/authorization.rs new file mode 100644 index 000000000..e69de29bb diff --git a/crates/jacquard-api/src/social_coves/aggregator/create_api_key.rs b/crates/jacquard-api/src/social_coves/aggregator/create_api_key.rs new file mode 100644 index 000000000..e69de29bb diff --git a/crates/jacquard-api/src/social_coves/aggregator/disable.rs b/crates/jacquard-api/src/social_coves/aggregator/disable.rs new file mode 100644 index 000000000..e69de29bb diff --git a/crates/jacquard-api/src/social_coves/aggregator/enable.rs b/crates/jacquard-api/src/social_coves/aggregator/enable.rs new file mode 100644 index 000000000..e69de29bb diff --git a/crates/jacquard-api/src/social_coves/aggregator/get_api_key.rs b/crates/jacquard-api/src/social_coves/aggregator/get_api_key.rs new file mode 100644 index 000000000..e69de29bb diff --git a/crates/jacquard-api/src/social_coves/aggregator/get_authorizations.rs b/crates/jacquard-api/src/social_coves/aggregator/get_authorizations.rs new file mode 100644 index 000000000..e69de29bb diff --git a/crates/jacquard-api/src/social_coves/aggregator/get_services.rs b/crates/jacquard-api/src/social_coves/aggregator/get_services.rs new file mode 100644 index 000000000..e69de29bb diff --git a/crates/jacquard-api/src/social_coves/aggregator/list_for_community.rs b/crates/jacquard-api/src/social_coves/aggregator/list_for_community.rs new file mode 100644 index 000000000..e69de29bb diff --git a/crates/jacquard-api/src/social_coves/aggregator/register.rs b/crates/jacquard-api/src/social_coves/aggregator/register.rs new file mode 100644 index 000000000..e69de29bb diff --git a/crates/jacquard-api/src/social_coves/aggregator/revoke_api_key.rs b/crates/jacquard-api/src/social_coves/aggregator/revoke_api_key.rs new file mode 100644 index 000000000..e69de29bb diff --git a/crates/jacquard-api/src/social_coves/aggregator/service.rs b/crates/jacquard-api/src/social_coves/aggregator/service.rs new file mode 100644 index 000000000..e69de29bb diff --git a/crates/jacquard-api/src/social_coves/aggregator/update_config.rs b/crates/jacquard-api/src/social_coves/aggregator/update_config.rs new file mode 100644 index 000000000..e69de29bb diff --git a/crates/jacquard-api/src/social_coves/community.rs b/crates/jacquard-api/src/social_coves/community.rs new file mode 100644 index 000000000..e69de29bb diff --git a/crates/jacquard-api/src/social_coves/community/block.rs b/crates/jacquard-api/src/social_coves/community/block.rs new file mode 100644 index 000000000..e69de29bb diff --git a/crates/jacquard-api/src/social_coves/community/comment.rs b/crates/jacquard-api/src/social_coves/community/comment.rs new file mode 100644 index 000000000..e69de29bb diff --git a/crates/jacquard-api/src/social_coves/community/comment/delete.rs b/crates/jacquard-api/src/social_coves/community/comment/delete.rs new file mode 100644 index 000000000..e69de29bb diff --git a/crates/jacquard-api/src/social_coves/community/comment/get_comments.rs b/crates/jacquard-api/src/social_coves/community/comment/get_comments.rs new file mode 100644 index 000000000..e69de29bb diff --git a/crates/jacquard-api/src/social_coves/community/comment/update.rs b/crates/jacquard-api/src/social_coves/community/comment/update.rs new file mode 100644 index 000000000..e69de29bb diff --git a/crates/jacquard-api/src/social_coves/community/create.rs b/crates/jacquard-api/src/social_coves/community/create.rs new file mode 100644 index 000000000..e69de29bb diff --git a/crates/jacquard-api/src/social_coves/community/get.rs b/crates/jacquard-api/src/social_coves/community/get.rs new file mode 100644 index 000000000..e69de29bb diff --git a/crates/jacquard-api/src/social_coves/community/get_members.rs b/crates/jacquard-api/src/social_coves/community/get_members.rs new file mode 100644 index 000000000..e69de29bb diff --git a/crates/jacquard-api/src/social_coves/community/get_subscribers.rs b/crates/jacquard-api/src/social_coves/community/get_subscribers.rs new file mode 100644 index 000000000..e69de29bb diff --git a/crates/jacquard-api/src/social_coves/community/list.rs b/crates/jacquard-api/src/social_coves/community/list.rs new file mode 100644 index 000000000..e69de29bb diff --git a/crates/jacquard-api/src/social_coves/community/post.rs b/crates/jacquard-api/src/social_coves/community/post.rs new file mode 100644 index 000000000..e69de29bb diff --git a/crates/jacquard-api/src/social_coves/community/post/create.rs b/crates/jacquard-api/src/social_coves/community/post/create.rs new file mode 100644 index 000000000..e69de29bb diff --git a/crates/jacquard-api/src/social_coves/community/post/delete.rs b/crates/jacquard-api/src/social_coves/community/post/delete.rs new file mode 100644 index 000000000..e69de29bb diff --git a/crates/jacquard-api/src/social_coves/community/post/get.rs b/crates/jacquard-api/src/social_coves/community/post/get.rs new file mode 100644 index 000000000..e69de29bb diff --git a/crates/jacquard-api/src/social_coves/community/post/search.rs b/crates/jacquard-api/src/social_coves/community/post/search.rs new file mode 100644 index 000000000..e69de29bb diff --git a/crates/jacquard-api/src/social_coves/community/post/update.rs b/crates/jacquard-api/src/social_coves/community/post/update.rs new file mode 100644 index 000000000..e69de29bb diff --git a/crates/jacquard-api/src/social_coves/community/profile.rs b/crates/jacquard-api/src/social_coves/community/profile.rs new file mode 100644 index 000000000..e69de29bb diff --git a/crates/jacquard-api/src/social_coves/community/search.rs b/crates/jacquard-api/src/social_coves/community/search.rs new file mode 100644 index 000000000..e69de29bb diff --git a/crates/jacquard-api/src/social_coves/community/subscribe.rs b/crates/jacquard-api/src/social_coves/community/subscribe.rs new file mode 100644 index 000000000..e69de29bb diff --git a/crates/jacquard-api/src/social_coves/community/subscription.rs b/crates/jacquard-api/src/social_coves/community/subscription.rs new file mode 100644 index 000000000..e69de29bb diff --git a/crates/jacquard-api/src/social_coves/community/unsubscribe.rs b/crates/jacquard-api/src/social_coves/community/unsubscribe.rs new file mode 100644 index 000000000..e69de29bb diff --git a/crates/jacquard-api/src/social_coves/community/update.rs b/crates/jacquard-api/src/social_coves/community/update.rs new file mode 100644 index 000000000..e69de29bb diff --git a/crates/jacquard-api/src/social_coves/community/wiki.rs b/crates/jacquard-api/src/social_coves/community/wiki.rs new file mode 100644 index 000000000..e69de29bb diff --git a/crates/jacquard-api/src/social_coves/embed.rs b/crates/jacquard-api/src/social_coves/embed.rs new file mode 100644 index 000000000..e69de29bb diff --git a/crates/jacquard-api/src/social_coves/embed/external.rs b/crates/jacquard-api/src/social_coves/embed/external.rs new file mode 100644 index 000000000..e69de29bb diff --git a/crates/jacquard-api/src/social_coves/embed/images.rs b/crates/jacquard-api/src/social_coves/embed/images.rs new file mode 100644 index 000000000..e69de29bb diff --git a/crates/jacquard-api/src/social_coves/embed/post.rs b/crates/jacquard-api/src/social_coves/embed/post.rs new file mode 100644 index 000000000..e69de29bb diff --git a/crates/jacquard-api/src/social_coves/embed/video.rs b/crates/jacquard-api/src/social_coves/embed/video.rs new file mode 100644 index 000000000..e69de29bb diff --git a/crates/jacquard-api/src/social_coves/feed.rs b/crates/jacquard-api/src/social_coves/feed.rs new file mode 100644 index 000000000..e69de29bb diff --git a/crates/jacquard-api/src/social_coves/feed/get_all.rs b/crates/jacquard-api/src/social_coves/feed/get_all.rs new file mode 100644 index 000000000..e69de29bb diff --git a/crates/jacquard-api/src/social_coves/feed/get_community.rs b/crates/jacquard-api/src/social_coves/feed/get_community.rs new file mode 100644 index 000000000..e69de29bb diff --git a/crates/jacquard-api/src/social_coves/feed/get_discover.rs b/crates/jacquard-api/src/social_coves/feed/get_discover.rs new file mode 100644 index 000000000..e69de29bb diff --git a/crates/jacquard-api/src/social_coves/feed/get_timeline.rs b/crates/jacquard-api/src/social_coves/feed/get_timeline.rs new file mode 100644 index 000000000..e69de29bb diff --git a/crates/jacquard-api/src/social_coves/feed/vote.rs b/crates/jacquard-api/src/social_coves/feed/vote.rs new file mode 100644 index 000000000..e69de29bb diff --git a/crates/jacquard-api/src/social_coves/feed/vote/create.rs b/crates/jacquard-api/src/social_coves/feed/vote/create.rs new file mode 100644 index 000000000..e69de29bb diff --git a/crates/jacquard-api/src/social_coves/feed/vote/delete.rs b/crates/jacquard-api/src/social_coves/feed/vote/delete.rs new file mode 100644 index 000000000..e69de29bb diff --git a/crates/jacquard-api/src/social_pace/feed/activity.rs b/crates/jacquard-api/src/social_pace/feed/activity.rs index c5c71c70f..0c1a93cdb 100644 --- a/crates/jacquard-api/src/social_pace/feed/activity.rs +++ b/crates/jacquard-api/src/social_pace/feed/activity.rs @@ -160,6 +160,17 @@ impl LexiconSchema for Activity { } } } + { + let value = &self.r#type; + #[allow(unused_comparisons)] + if ::len(value.as_ref()) > 50usize { + return Err(ConstraintError::MaxLength { + path: ValidationPath::from_field("type"), + max: 50usize, + actual: ::len(value.as_ref()), + }); + } + } Ok(()) } } diff --git a/crates/jacquard-api/src/social_showcase.rs b/crates/jacquard-api/src/social_showcase.rs index f79ff5020..8d6d173c1 100644 --- a/crates/jacquard-api/src/social_showcase.rs +++ b/crates/jacquard-api/src/social_showcase.rs @@ -929,6 +929,16 @@ impl LexiconSchema for CollectionView { }); } } + for value in &self.tags { + #[allow(unused_comparisons)] + if ::len(value.as_ref()) > 64usize { + return Err(ConstraintError::MaxLength { + path: ValidationPath::from_field("tags"), + max: 64usize, + actual: ::len(value.as_ref()), + }); + } + } { let value = &self.r#type; #[allow(unused_comparisons)] @@ -1097,6 +1107,16 @@ impl LexiconSchema for ItemView { }); } } + for value in &self.tags { + #[allow(unused_comparisons)] + if ::len(value.as_ref()) > 64usize { + return Err(ConstraintError::MaxLength { + path: ValidationPath::from_field("tags"), + max: 64usize, + actual: ::len(value.as_ref()), + }); + } + } { let value = &self.title; #[allow(unused_comparisons)] @@ -1196,6 +1216,18 @@ impl LexiconSchema for ProfileView { }); } } + if let Some(values) = &self.tags { + for value in values { + #[allow(unused_comparisons)] + if ::len(value.as_ref()) > 64usize { + return Err(ConstraintError::MaxLength { + path: ValidationPath::from_field("tags"), + max: 64usize, + actual: ::len(value.as_ref()), + }); + } + } + } Ok(()) } } diff --git a/crates/jacquard-api/src/social_showcase/library/item.rs b/crates/jacquard-api/src/social_showcase/library/item.rs index 4a68d9bbb..907cea215 100644 --- a/crates/jacquard-api/src/social_showcase/library/item.rs +++ b/crates/jacquard-api/src/social_showcase/library/item.rs @@ -259,6 +259,16 @@ impl LexiconSchema for Item { }); } } + for value in &self.tags { + #[allow(unused_comparisons)] + if ::len(value.as_ref()) > 64usize { + return Err(ConstraintError::MaxLength { + path: ValidationPath::from_field("tags"), + max: 64usize, + actual: ::len(value.as_ref()), + }); + } + } { let value = &self.title; #[allow(unused_comparisons)] diff --git a/crates/jacquard-api/src/social_showcase/profile/profile.rs b/crates/jacquard-api/src/social_showcase/profile/profile.rs index f4e2ae42a..0fcecf482 100644 --- a/crates/jacquard-api/src/social_showcase/profile/profile.rs +++ b/crates/jacquard-api/src/social_showcase/profile/profile.rs @@ -294,6 +294,16 @@ impl LexiconSchema for Profile { }); } } + for value in &self.tags { + #[allow(unused_comparisons)] + if ::len(value.as_ref()) > 64usize { + return Err(ConstraintError::MaxLength { + path: ValidationPath::from_field("tags"), + max: 64usize, + actual: ::len(value.as_ref()), + }); + } + } if let Some(ref value) = self.theme { #[allow(unused_comparisons)] if ::len(value.as_ref()) > 64usize { diff --git a/crates/jacquard-api/src/systems_timker/hawlt/note.rs b/crates/jacquard-api/src/systems_timker/hawlt/note.rs index 1af193c66..84654b258 100644 --- a/crates/jacquard-api/src/systems_timker/hawlt/note.rs +++ b/crates/jacquard-api/src/systems_timker/hawlt/note.rs @@ -283,6 +283,32 @@ impl LexiconSchema for Note { }); } } + if let Some(values) = &self.tags { + for value in values { + #[allow(unused_comparisons)] + if ::len(value.as_ref()) > 1280usize { + return Err(ConstraintError::MaxLength { + path: ValidationPath::from_field("tags"), + max: 1280usize, + actual: ::len(value.as_ref()), + }); + } + } + } + if let Some(values) = &self.tags { + for value in values { + { + let count = UnicodeSegmentation::graphemes(value.as_ref(), true).count(); + if count > 128usize { + return Err(ConstraintError::MaxGraphemes { + path: ValidationPath::from_field("tags"), + max: 128usize, + actual: count, + }); + } + } + } + } Ok(()) } } diff --git a/crates/jacquard-api/src/tech_manos/twmirror/post.rs b/crates/jacquard-api/src/tech_manos/twmirror/post.rs index 92d4d40df..62bb6b7dc 100644 --- a/crates/jacquard-api/src/tech_manos/twmirror/post.rs +++ b/crates/jacquard-api/src/tech_manos/twmirror/post.rs @@ -106,6 +106,50 @@ impl LexiconSchema for Post { lexicon_doc_tech_manos_twmirror_post() } fn validate(&self) -> Result<(), ConstraintError> { + { + let value = &self.tw_user_id; + #[allow(unused_comparisons)] + if ::len(value.as_ref()) > 20usize { + return Err(ConstraintError::MaxLength { + path: ValidationPath::from_field("tw_user_id"), + max: 20usize, + actual: ::len(value.as_ref()), + }); + } + } + { + let value = &self.tw_user_id; + #[allow(unused_comparisons)] + if ::len(value.as_ref()) < 1usize { + return Err(ConstraintError::MinLength { + path: ValidationPath::from_field("tw_user_id"), + min: 1usize, + actual: ::len(value.as_ref()), + }); + } + } + { + let value = &self.tweet_id; + #[allow(unused_comparisons)] + if ::len(value.as_ref()) > 20usize { + return Err(ConstraintError::MaxLength { + path: ValidationPath::from_field("tweet_id"), + max: 20usize, + actual: ::len(value.as_ref()), + }); + } + } + { + let value = &self.tweet_id; + #[allow(unused_comparisons)] + if ::len(value.as_ref()) < 1usize { + return Err(ConstraintError::MinLength { + path: ValidationPath::from_field("tweet_id"), + min: 1usize, + actual: ::len(value.as_ref()), + }); + } + } Ok(()) } } diff --git a/crates/jacquard-api/src/tech_tokimeki/kaku.rs b/crates/jacquard-api/src/tech_tokimeki/kaku.rs index 38ef0f26e..1b7cb53b8 100644 --- a/crates/jacquard-api/src/tech_tokimeki/kaku.rs +++ b/crates/jacquard-api/src/tech_tokimeki/kaku.rs @@ -449,6 +449,32 @@ impl LexiconSchema for PostView { }); } } + if let Some(values) = &self.tags { + for value in values { + #[allow(unused_comparisons)] + if ::len(value.as_ref()) > 64usize { + return Err(ConstraintError::MaxLength { + path: ValidationPath::from_field("tags"), + max: 64usize, + actual: ::len(value.as_ref()), + }); + } + } + } + if let Some(values) = &self.tags { + for value in values { + { + let count = UnicodeSegmentation::graphemes(value.as_ref(), true).count(); + if count > 32usize { + return Err(ConstraintError::MaxGraphemes { + path: ValidationPath::from_field("tags"), + max: 32usize, + actual: count, + }); + } + } + } + } if let Some(ref value) = self.text { #[allow(unused_comparisons)] if ::len(value.as_ref()) > 1000usize { @@ -597,6 +623,32 @@ impl LexiconSchema for RequestView { }); } } + if let Some(values) = &self.tags { + for value in values { + #[allow(unused_comparisons)] + if ::len(value.as_ref()) > 64usize { + return Err(ConstraintError::MaxLength { + path: ValidationPath::from_field("tags"), + max: 64usize, + actual: ::len(value.as_ref()), + }); + } + } + } + if let Some(values) = &self.tags { + for value in values { + { + let count = UnicodeSegmentation::graphemes(value.as_ref(), true).count(); + if count > 32usize { + return Err(ConstraintError::MaxGraphemes { + path: ValidationPath::from_field("tags"), + max: 32usize, + actual: count, + }); + } + } + } + } { let value = &self.text; #[allow(unused_comparisons)] diff --git a/crates/jacquard-api/src/tech_tokimeki/kaku/post.rs b/crates/jacquard-api/src/tech_tokimeki/kaku/post.rs index 68496003c..36c81f8ab 100644 --- a/crates/jacquard-api/src/tech_tokimeki/kaku/post.rs +++ b/crates/jacquard-api/src/tech_tokimeki/kaku/post.rs @@ -164,6 +164,32 @@ impl LexiconSchema for Post { }); } } + if let Some(values) = &self.tags { + for value in values { + #[allow(unused_comparisons)] + if ::len(value.as_ref()) > 64usize { + return Err(ConstraintError::MaxLength { + path: ValidationPath::from_field("tags"), + max: 64usize, + actual: ::len(value.as_ref()), + }); + } + } + } + if let Some(values) = &self.tags { + for value in values { + { + let count = UnicodeSegmentation::graphemes(value.as_ref(), true).count(); + if count > 32usize { + return Err(ConstraintError::MaxGraphemes { + path: ValidationPath::from_field("tags"), + max: 32usize, + actual: count, + }); + } + } + } + } if let Some(ref value) = self.text { #[allow(unused_comparisons)] if ::len(value.as_ref()) > 1000usize { diff --git a/crates/jacquard-api/src/tech_tokimeki/kaku/request.rs b/crates/jacquard-api/src/tech_tokimeki/kaku/request.rs index 5fa67956c..c3e3273b3 100644 --- a/crates/jacquard-api/src/tech_tokimeki/kaku/request.rs +++ b/crates/jacquard-api/src/tech_tokimeki/kaku/request.rs @@ -133,6 +133,18 @@ impl LexiconSchema for Request { }); } } + if let Some(values) = &self.tags { + for value in values { + #[allow(unused_comparisons)] + if ::len(value.as_ref()) > 64usize { + return Err(ConstraintError::MaxLength { + path: ValidationPath::from_field("tags"), + max: 64usize, + actual: ::len(value.as_ref()), + }); + } + } + } { let value = &self.text; #[allow(unused_comparisons)] diff --git a/crates/jacquard-api/src/tech_tokimeki/poll/poll.rs b/crates/jacquard-api/src/tech_tokimeki/poll/poll.rs index d6f54d3b3..f7e985a23 100644 --- a/crates/jacquard-api/src/tech_tokimeki/poll/poll.rs +++ b/crates/jacquard-api/src/tech_tokimeki/poll/poll.rs @@ -127,6 +127,28 @@ impl LexiconSchema for Poll { }); } } + for value in &self.options { + #[allow(unused_comparisons)] + if ::len(value.as_ref()) > 100usize { + return Err(ConstraintError::MaxLength { + path: ValidationPath::from_field("options"), + max: 100usize, + actual: ::len(value.as_ref()), + }); + } + } + for value in &self.options { + { + let count = UnicodeSegmentation::graphemes(value.as_ref(), true).count(); + if count > 50usize { + return Err(ConstraintError::MaxGraphemes { + path: ValidationPath::from_field("options"), + max: 50usize, + actual: count, + }); + } + } + } Ok(()) } } diff --git a/crates/jacquard-api/src/tools_ozone/queue.rs b/crates/jacquard-api/src/tools_ozone/queue.rs index f371b4613..6c99e5943 100644 --- a/crates/jacquard-api/src/tools_ozone/queue.rs +++ b/crates/jacquard-api/src/tools_ozone/queue.rs @@ -111,12 +111,17 @@ pub struct QueueView { pub id: i64, ///Display name of the queue pub name: S, + ///Policy keys recommended when actioning reports in this queue + #[serde(skip_serializing_if = "Option::is_none")] + pub recommended_policies: Option>, ///Report reason types this queue accepts (fully qualified NSIDs) - pub report_types: Vec, + #[serde(skip_serializing_if = "Option::is_none")] + pub report_types: Option>, ///Statistics about this queue pub stats: queue::QueueStats, ///Subject types this queue accepts. - pub subject_types: Vec, + #[serde(skip_serializing_if = "Option::is_none")] + pub subject_types: Option>, pub updated_at: Datetime, #[serde(flatten, default, skip_serializing_if = "Option::is_none")] pub extra_data: Option>>, @@ -163,28 +168,6 @@ impl LexiconSchema for QueueView { lexicon_doc_tools_ozone_queue_defs() } fn validate(&self) -> Result<(), ConstraintError> { - { - let value = &self.report_types; - #[allow(unused_comparisons)] - if value.len() < 1usize { - return Err(ConstraintError::MinLength { - path: ValidationPath::from_field("report_types"), - min: 1usize, - actual: value.len(), - }); - } - } - { - let value = &self.subject_types; - #[allow(unused_comparisons)] - if value.len() < 1usize { - return Err(ConstraintError::MinLength { - path: ValidationPath::from_field("subject_types"), - min: 1usize, - actual: value.len(), - }); - } - } Ok(()) } } @@ -581,8 +564,6 @@ fn lexicon_doc_tools_ozone_queue_defs() -> LexiconDoc<'static> { required: Some( vec![ SmolStr::new_static("id"), SmolStr::new_static("name"), - SmolStr::new_static("subjectTypes"), - SmolStr::new_static("reportTypes"), SmolStr::new_static("createdBy"), SmolStr::new_static("createdAt"), SmolStr::new_static("updatedAt"), @@ -665,6 +646,20 @@ fn lexicon_doc_tools_ozone_queue_defs() -> LexiconDoc<'static> { ..Default::default() }), ); + map.insert( + SmolStr::new_static("recommendedPolicies"), + LexObjectProperty::Array(LexArray { + description: Some( + CowStr::new_static( + "Policy keys recommended when actioning reports in this queue", + ), + ), + items: LexArrayItem::String(LexString { + ..Default::default() + }), + ..Default::default() + }), + ); map.insert( SmolStr::new_static("reportTypes"), LexObjectProperty::Array(LexArray { @@ -676,7 +671,6 @@ fn lexicon_doc_tools_ozone_queue_defs() -> LexiconDoc<'static> { items: LexArrayItem::String(LexString { ..Default::default() }), - min_length: Some(1usize), ..Default::default() }), ); @@ -696,7 +690,6 @@ fn lexicon_doc_tools_ozone_queue_defs() -> LexiconDoc<'static> { items: LexArrayItem::String(LexString { ..Default::default() }), - min_length: Some(1usize), ..Default::default() }), ); @@ -733,9 +726,7 @@ pub mod queue_view_state { type Enabled; type Id; type Name; - type ReportTypes; type Stats; - type SubjectTypes; type UpdatedAt; } /// Empty state - all required fields are unset @@ -747,9 +738,7 @@ pub mod queue_view_state { type Enabled = Unset; type Id = Unset; type Name = Unset; - type ReportTypes = Unset; type Stats = Unset; - type SubjectTypes = Unset; type UpdatedAt = Unset; } ///State transition - sets the `created_at` field to Set @@ -761,9 +750,7 @@ pub mod queue_view_state { type Enabled = St::Enabled; type Id = St::Id; type Name = St::Name; - type ReportTypes = St::ReportTypes; type Stats = St::Stats; - type SubjectTypes = St::SubjectTypes; type UpdatedAt = St::UpdatedAt; } ///State transition - sets the `created_by` field to Set @@ -775,9 +762,7 @@ pub mod queue_view_state { type Enabled = St::Enabled; type Id = St::Id; type Name = St::Name; - type ReportTypes = St::ReportTypes; type Stats = St::Stats; - type SubjectTypes = St::SubjectTypes; type UpdatedAt = St::UpdatedAt; } ///State transition - sets the `enabled` field to Set @@ -789,9 +774,7 @@ pub mod queue_view_state { type Enabled = Set; type Id = St::Id; type Name = St::Name; - type ReportTypes = St::ReportTypes; type Stats = St::Stats; - type SubjectTypes = St::SubjectTypes; type UpdatedAt = St::UpdatedAt; } ///State transition - sets the `id` field to Set @@ -803,9 +786,7 @@ pub mod queue_view_state { type Enabled = St::Enabled; type Id = Set; type Name = St::Name; - type ReportTypes = St::ReportTypes; type Stats = St::Stats; - type SubjectTypes = St::SubjectTypes; type UpdatedAt = St::UpdatedAt; } ///State transition - sets the `name` field to Set @@ -817,23 +798,7 @@ pub mod queue_view_state { type Enabled = St::Enabled; type Id = St::Id; type Name = Set; - type ReportTypes = St::ReportTypes; type Stats = St::Stats; - type SubjectTypes = St::SubjectTypes; - type UpdatedAt = St::UpdatedAt; - } - ///State transition - sets the `report_types` field to Set - pub struct SetReportTypes(PhantomData St>); - impl sealed::Sealed for SetReportTypes {} - impl State for SetReportTypes { - type CreatedAt = St::CreatedAt; - type CreatedBy = St::CreatedBy; - type Enabled = St::Enabled; - type Id = St::Id; - type Name = St::Name; - type ReportTypes = Set; - type Stats = St::Stats; - type SubjectTypes = St::SubjectTypes; type UpdatedAt = St::UpdatedAt; } ///State transition - sets the `stats` field to Set @@ -845,23 +810,7 @@ pub mod queue_view_state { type Enabled = St::Enabled; type Id = St::Id; type Name = St::Name; - type ReportTypes = St::ReportTypes; type Stats = Set; - type SubjectTypes = St::SubjectTypes; - type UpdatedAt = St::UpdatedAt; - } - ///State transition - sets the `subject_types` field to Set - pub struct SetSubjectTypes(PhantomData St>); - impl sealed::Sealed for SetSubjectTypes {} - impl State for SetSubjectTypes { - type CreatedAt = St::CreatedAt; - type CreatedBy = St::CreatedBy; - type Enabled = St::Enabled; - type Id = St::Id; - type Name = St::Name; - type ReportTypes = St::ReportTypes; - type Stats = St::Stats; - type SubjectTypes = Set; type UpdatedAt = St::UpdatedAt; } ///State transition - sets the `updated_at` field to Set @@ -873,9 +822,7 @@ pub mod queue_view_state { type Enabled = St::Enabled; type Id = St::Id; type Name = St::Name; - type ReportTypes = St::ReportTypes; type Stats = St::Stats; - type SubjectTypes = St::SubjectTypes; type UpdatedAt = Set; } /// Marker types for field names @@ -891,12 +838,8 @@ pub mod queue_view_state { pub struct id(()); ///Marker type for the `name` field pub struct name(()); - ///Marker type for the `report_types` field - pub struct report_types(()); ///Marker type for the `stats` field pub struct stats(()); - ///Marker type for the `subject_types` field - pub struct subject_types(()); ///Marker type for the `updated_at` field pub struct updated_at(()); } @@ -915,6 +858,7 @@ pub struct QueueViewBuilder Option, Option, Option>, + Option>, Option>, Option>, Option, @@ -942,7 +886,7 @@ impl QueueViewBuilder { QueueViewBuilder { _state: PhantomData, _fields: ( - None, None, None, None, None, None, None, None, None, None, None, None, + None, None, None, None, None, None, None, None, None, None, None, None, None, ), _type: PhantomData, } @@ -955,7 +899,7 @@ impl QueueViewBuilder { QueueViewBuilder { _state: PhantomData, _fields: ( - None, None, None, None, None, None, None, None, None, None, None, None, + None, None, None, None, None, None, None, None, None, None, None, None, None, ), _type: PhantomData, } @@ -1093,22 +1037,29 @@ where } } -impl QueueViewBuilder -where - St: queue_view_state::State, - St::ReportTypes: queue_view_state::IsUnset, -{ - /// Set the `reportTypes` field (required) - pub fn report_types( - mut self, - value: impl Into>, - ) -> QueueViewBuilder, S> { - self._fields.8 = Option::Some(value.into()); - QueueViewBuilder { - _state: PhantomData, - _fields: self._fields, - _type: PhantomData, - } +impl QueueViewBuilder { + /// Set the `recommendedPolicies` field (optional) + pub fn recommended_policies(mut self, value: impl Into>>) -> Self { + self._fields.8 = value.into(); + self + } + /// Set the `recommendedPolicies` field to an Option value (optional) + pub fn maybe_recommended_policies(mut self, value: Option>) -> Self { + self._fields.8 = value; + self + } +} + +impl QueueViewBuilder { + /// Set the `reportTypes` field (optional) + pub fn report_types(mut self, value: impl Into>>) -> Self { + self._fields.9 = value.into(); + self + } + /// Set the `reportTypes` field to an Option value (optional) + pub fn maybe_report_types(mut self, value: Option>) -> Self { + self._fields.9 = value; + self } } @@ -1122,7 +1073,7 @@ where mut self, value: impl Into>, ) -> QueueViewBuilder, S> { - self._fields.9 = Option::Some(value.into()); + self._fields.10 = Option::Some(value.into()); QueueViewBuilder { _state: PhantomData, _fields: self._fields, @@ -1131,22 +1082,16 @@ where } } -impl QueueViewBuilder -where - St: queue_view_state::State, - St::SubjectTypes: queue_view_state::IsUnset, -{ - /// Set the `subjectTypes` field (required) - pub fn subject_types( - mut self, - value: impl Into>, - ) -> QueueViewBuilder, S> { - self._fields.10 = Option::Some(value.into()); - QueueViewBuilder { - _state: PhantomData, - _fields: self._fields, - _type: PhantomData, - } +impl QueueViewBuilder { + /// Set the `subjectTypes` field (optional) + pub fn subject_types(mut self, value: impl Into>>) -> Self { + self._fields.11 = value.into(); + self + } + /// Set the `subjectTypes` field to an Option value (optional) + pub fn maybe_subject_types(mut self, value: Option>) -> Self { + self._fields.11 = value; + self } } @@ -1160,7 +1105,7 @@ where mut self, value: impl Into, ) -> QueueViewBuilder, S> { - self._fields.11 = Option::Some(value.into()); + self._fields.12 = Option::Some(value.into()); QueueViewBuilder { _state: PhantomData, _fields: self._fields, @@ -1177,9 +1122,7 @@ where St::Enabled: queue_view_state::IsSet, St::Id: queue_view_state::IsSet, St::Name: queue_view_state::IsSet, - St::ReportTypes: queue_view_state::IsSet, St::Stats: queue_view_state::IsSet, - St::SubjectTypes: queue_view_state::IsSet, St::UpdatedAt: queue_view_state::IsSet, { /// Build the final struct. @@ -1193,10 +1136,11 @@ where enabled: self._fields.5.unwrap(), id: self._fields.6.unwrap(), name: self._fields.7.unwrap(), - report_types: self._fields.8.unwrap(), - stats: self._fields.9.unwrap(), - subject_types: self._fields.10.unwrap(), - updated_at: self._fields.11.unwrap(), + recommended_policies: self._fields.8, + report_types: self._fields.9, + stats: self._fields.10.unwrap(), + subject_types: self._fields.11, + updated_at: self._fields.12.unwrap(), extra_data: Default::default(), } } @@ -1211,10 +1155,11 @@ where enabled: self._fields.5.unwrap(), id: self._fields.6.unwrap(), name: self._fields.7.unwrap(), - report_types: self._fields.8.unwrap(), - stats: self._fields.9.unwrap(), - subject_types: self._fields.10.unwrap(), - updated_at: self._fields.11.unwrap(), + recommended_policies: self._fields.8, + report_types: self._fields.9, + stats: self._fields.10.unwrap(), + subject_types: self._fields.11, + updated_at: self._fields.12.unwrap(), extra_data: Some(extra_data), } } diff --git a/crates/jacquard-api/src/tools_ozone/queue/create_queue.rs b/crates/jacquard-api/src/tools_ozone/queue/create_queue.rs index 27f840e84..bae59aed9 100644 --- a/crates/jacquard-api/src/tools_ozone/queue/create_queue.rs +++ b/crates/jacquard-api/src/tools_ozone/queue/create_queue.rs @@ -18,7 +18,7 @@ use jacquard_common::{BosStr, CowStr, DefaultStr, FromStaticStr}; use jacquard_derive::{IntoStatic, open_union}; use serde::{Deserialize, Serialize}; -#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic, Default)] #[serde( rename_all = "camelCase", bound(deserialize = "S: Deserialize<'de> + BosStr") @@ -32,10 +32,15 @@ pub struct CreateQueue { pub description: Option, ///Display name for the queue (must be unique) pub name: S, + ///Policy keys to recommend when actioning reports in this queue + #[serde(skip_serializing_if = "Option::is_none")] + pub recommended_policies: Option>, ///Report reason types (fully qualified NSIDs) - pub report_types: Vec, + #[serde(skip_serializing_if = "Option::is_none")] + pub report_types: Option>, ///Subject types this queue accepts - pub subject_types: Vec, + #[serde(skip_serializing_if = "Option::is_none")] + pub subject_types: Option>, #[serde(flatten, default, skip_serializing_if = "Option::is_none")] pub extra_data: Option>>, } @@ -56,6 +61,9 @@ pub struct CreateQueueOutput { )] #[serde(tag = "error", content = "message")] pub enum CreateQueueError { + /// One or more recommended policy keys do not exist in the configured policy list + #[serde(rename = "InvalidRecommendedPolicies")] + InvalidRecommendedPolicies(Option), /// The queue configuration conflicts with an existing queue #[serde(rename = "ConflictingQueue")] ConflictingQueue(Option), @@ -70,6 +78,13 @@ pub enum CreateQueueError { impl core::fmt::Display for CreateQueueError { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { match self { + Self::InvalidRecommendedPolicies(msg) => { + write!(f, "InvalidRecommendedPolicies")?; + if let Some(msg) = msg { + write!(f, ": {}", msg)?; + } + Ok(()) + } Self::ConflictingQueue(msg) => { write!(f, "ConflictingQueue")?; if let Some(msg) = msg { @@ -117,224 +132,3 @@ impl jacquard_common::xrpc::XrpcEndpoint for CreateQueueRequest { type Request = CreateQueue; type Response = CreateQueueResponse; } - -pub mod create_queue_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 Name; - type ReportTypes; - type SubjectTypes; - } - /// Empty state - all required fields are unset - pub struct Empty(()); - impl sealed::Sealed for Empty {} - impl State for Empty { - type Name = Unset; - type ReportTypes = Unset; - type SubjectTypes = Unset; - } - ///State transition - sets the `name` field to Set - pub struct SetName(PhantomData St>); - impl sealed::Sealed for SetName {} - impl State for SetName { - type Name = Set; - type ReportTypes = St::ReportTypes; - type SubjectTypes = St::SubjectTypes; - } - ///State transition - sets the `report_types` field to Set - pub struct SetReportTypes(PhantomData St>); - impl sealed::Sealed for SetReportTypes {} - impl State for SetReportTypes { - type Name = St::Name; - type ReportTypes = Set; - type SubjectTypes = St::SubjectTypes; - } - ///State transition - sets the `subject_types` field to Set - pub struct SetSubjectTypes(PhantomData St>); - impl sealed::Sealed for SetSubjectTypes {} - impl State for SetSubjectTypes { - type Name = St::Name; - type ReportTypes = St::ReportTypes; - type SubjectTypes = Set; - } - /// Marker types for field names - #[allow(non_camel_case_types)] - pub mod members { - ///Marker type for the `name` field - pub struct name(()); - ///Marker type for the `report_types` field - pub struct report_types(()); - ///Marker type for the `subject_types` field - pub struct subject_types(()); - } -} - -/// Builder for constructing an instance of this type. -pub struct CreateQueueBuilder { - _state: PhantomData St>, - _fields: ( - Option>, - Option, - Option, - Option>, - Option>, - ), - _type: PhantomData S>, -} - -impl CreateQueue { - /// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed - pub fn new() -> CreateQueueBuilder { - CreateQueueBuilder::new() - } -} - -impl CreateQueue { - /// Create a new builder for this type - pub fn builder() -> CreateQueueBuilder { - CreateQueueBuilder::builder() - } -} - -impl CreateQueueBuilder { - /// Create a new builder with all fields unset, using the default string type, if needed - pub fn new() -> Self { - CreateQueueBuilder { - _state: PhantomData, - _fields: (None, None, None, None, None), - _type: PhantomData, - } - } -} - -impl CreateQueueBuilder { - /// Create a new builder with all fields unset - pub fn builder() -> Self { - CreateQueueBuilder { - _state: PhantomData, - _fields: (None, None, None, None, None), - _type: PhantomData, - } - } -} - -impl CreateQueueBuilder { - /// Set the `collection` field (optional) - pub fn collection(mut self, value: impl Into>>) -> Self { - self._fields.0 = value.into(); - self - } - /// Set the `collection` field to an Option value (optional) - pub fn maybe_collection(mut self, value: Option>) -> Self { - self._fields.0 = value; - self - } -} - -impl CreateQueueBuilder { - /// Set the `description` field (optional) - pub fn description(mut self, value: impl Into>) -> Self { - self._fields.1 = value.into(); - self - } - /// Set the `description` field to an Option value (optional) - pub fn maybe_description(mut self, value: Option) -> Self { - self._fields.1 = value; - self - } -} - -impl CreateQueueBuilder -where - St: create_queue_state::State, - St::Name: create_queue_state::IsUnset, -{ - /// Set the `name` field (required) - pub fn name( - mut self, - value: impl Into, - ) -> CreateQueueBuilder, S> { - self._fields.2 = Option::Some(value.into()); - CreateQueueBuilder { - _state: PhantomData, - _fields: self._fields, - _type: PhantomData, - } - } -} - -impl CreateQueueBuilder -where - St: create_queue_state::State, - St::ReportTypes: create_queue_state::IsUnset, -{ - /// Set the `reportTypes` field (required) - pub fn report_types( - mut self, - value: impl Into>, - ) -> CreateQueueBuilder, S> { - self._fields.3 = Option::Some(value.into()); - CreateQueueBuilder { - _state: PhantomData, - _fields: self._fields, - _type: PhantomData, - } - } -} - -impl CreateQueueBuilder -where - St: create_queue_state::State, - St::SubjectTypes: create_queue_state::IsUnset, -{ - /// Set the `subjectTypes` field (required) - pub fn subject_types( - mut self, - value: impl Into>, - ) -> CreateQueueBuilder, S> { - self._fields.4 = Option::Some(value.into()); - CreateQueueBuilder { - _state: PhantomData, - _fields: self._fields, - _type: PhantomData, - } - } -} - -impl CreateQueueBuilder -where - St: create_queue_state::State, - St::Name: create_queue_state::IsSet, - St::ReportTypes: create_queue_state::IsSet, - St::SubjectTypes: create_queue_state::IsSet, -{ - /// Build the final struct. - pub fn build(self) -> CreateQueue { - CreateQueue { - collection: self._fields.0, - description: self._fields.1, - name: self._fields.2.unwrap(), - report_types: self._fields.3.unwrap(), - subject_types: self._fields.4.unwrap(), - extra_data: Default::default(), - } - } - /// Build the final struct with custom extra_data. - pub fn build_with_data(self, extra_data: BTreeMap>) -> CreateQueue { - CreateQueue { - collection: self._fields.0, - description: self._fields.1, - name: self._fields.2.unwrap(), - report_types: self._fields.3.unwrap(), - subject_types: self._fields.4.unwrap(), - extra_data: Some(extra_data), - } - } -} diff --git a/crates/jacquard-api/src/tools_ozone/queue/update_queue.rs b/crates/jacquard-api/src/tools_ozone/queue/update_queue.rs index 9d20304d1..b489dc114 100644 --- a/crates/jacquard-api/src/tools_ozone/queue/update_queue.rs +++ b/crates/jacquard-api/src/tools_ozone/queue/update_queue.rs @@ -14,7 +14,7 @@ use core::marker::PhantomData; use jacquard_common::deps::smol_str::SmolStr; use jacquard_common::types::value::Data; use jacquard_common::{BosStr, CowStr, DefaultStr, FromStaticStr}; -use jacquard_derive::IntoStatic; +use jacquard_derive::{IntoStatic, open_union}; use serde::{Deserialize, Serialize}; #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] @@ -34,6 +34,9 @@ pub struct UpdateQueue { pub name: Option, ///ID of the queue to update pub queue_id: i64, + ///Policy keys to recommend when actioning reports in this queue + #[serde(skip_serializing_if = "Option::is_none")] + pub recommended_policies: Option>, #[serde(flatten, default, skip_serializing_if = "Option::is_none")] pub extra_data: Option>>, } @@ -49,6 +52,43 @@ pub struct UpdateQueueOutput { pub extra_data: Option>>, } +#[derive( + Serialize, Deserialize, Debug, Clone, PartialEq, Eq, thiserror::Error, miette::Diagnostic, +)] +#[serde(tag = "error", content = "message")] +pub enum UpdateQueueError { + /// One or more recommended policy keys do not exist in the configured policy list + #[serde(rename = "InvalidRecommendedPolicies")] + InvalidRecommendedPolicies(Option), + /// Catch-all for unknown error codes. + #[serde(untagged)] + Other { + error: SmolStr, + message: Option, + }, +} + +impl core::fmt::Display for UpdateQueueError { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + match self { + Self::InvalidRecommendedPolicies(msg) => { + write!(f, "InvalidRecommendedPolicies")?; + if let Some(msg) = msg { + write!(f, ": {}", msg)?; + } + Ok(()) + } + Self::Other { error, message } => { + write!(f, "{}", error)?; + if let Some(msg) = message { + write!(f, ": {}", msg)?; + } + Ok(()) + } + } + } +} + /** Response marker for the `tools.ozone.queue.updateQueue` procedure. Implements `jacquard_common::xrpc::XrpcResp`; successful bodies decode as `Self::Output`, which is `UpdateQueueOutput` for this endpoint.*/ @@ -57,7 +97,7 @@ impl jacquard_common::xrpc::XrpcResp for UpdateQueueResponse { const NSID: &'static str = "tools.ozone.queue.updateQueue"; const ENCODING: &'static str = "application/json"; type Output = UpdateQueueOutput; - type Err = jacquard_common::xrpc::GenericError; + type Err = UpdateQueueError; } impl jacquard_common::xrpc::XrpcRequest for UpdateQueue { @@ -114,7 +154,13 @@ pub mod update_queue_state { /// Builder for constructing an instance of this type. pub struct UpdateQueueBuilder { _state: PhantomData St>, - _fields: (Option, Option, Option, Option), + _fields: ( + Option, + Option, + Option, + Option, + Option>, + ), _type: PhantomData S>, } @@ -137,7 +183,7 @@ impl UpdateQueueBuilder { pub fn new() -> Self { UpdateQueueBuilder { _state: PhantomData, - _fields: (None, None, None, None), + _fields: (None, None, None, None, None), _type: PhantomData, } } @@ -148,7 +194,7 @@ impl UpdateQueueBuilder { pub fn builder() -> Self { UpdateQueueBuilder { _state: PhantomData, - _fields: (None, None, None, None), + _fields: (None, None, None, None, None), _type: PhantomData, } } @@ -212,6 +258,19 @@ where } } +impl UpdateQueueBuilder { + /// Set the `recommendedPolicies` field (optional) + pub fn recommended_policies(mut self, value: impl Into>>) -> Self { + self._fields.4 = value.into(); + self + } + /// Set the `recommendedPolicies` field to an Option value (optional) + pub fn maybe_recommended_policies(mut self, value: Option>) -> Self { + self._fields.4 = value; + self + } +} + impl UpdateQueueBuilder where St: update_queue_state::State, @@ -224,6 +283,7 @@ where enabled: self._fields.1, name: self._fields.2, queue_id: self._fields.3.unwrap(), + recommended_policies: self._fields.4, extra_data: Default::default(), } } @@ -234,6 +294,7 @@ where enabled: self._fields.1, name: self._fields.2, queue_id: self._fields.3.unwrap(), + recommended_policies: self._fields.4, extra_data: Some(extra_data), } } diff --git a/crates/jacquard-api/src/tools_ozone/report.rs b/crates/jacquard-api/src/tools_ozone/report.rs index 8bb664467..cbd235359 100644 --- a/crates/jacquard-api/src/tools_ozone/report.rs +++ b/crates/jacquard-api/src/tools_ozone/report.rs @@ -7,6 +7,7 @@ //! Generated bindings for the `tools.ozone.report` Lexicon namespace/module. pub mod assign_moderator; +pub mod close_reports; pub mod create_activity; pub mod get_assignments; pub mod get_historical_stats; @@ -1649,6 +1650,10 @@ pub struct ReportView { pub event_id: i64, ///Report ID pub id: i64, + ///Whether this report was emitted by automated tooling. Defaults to `false`. + #[serde(skip_serializing_if = "Option::is_none")] + #[serde(default = "_default_report_view_is_automated")] + pub is_automated: Option, ///Whether this report is muted. A report is muted if the reporter was muted or the subject was muted at the time the report was created. #[serde(skip_serializing_if = "Option::is_none")] pub is_muted: Option, @@ -2819,6 +2824,12 @@ fn lexicon_doc_tools_ozone_report_defs() -> LexiconDoc<'static> { ..Default::default() }), ); + map.insert( + SmolStr::new_static("isAutomated"), + LexObjectProperty::Boolean(LexBoolean { + ..Default::default() + }), + ); map.insert( SmolStr::new_static("isMuted"), LexObjectProperty::Boolean(LexBoolean { @@ -3765,6 +3776,10 @@ where } } +fn _default_report_view_is_automated() -> Option { + Some(false) +} + pub mod report_view_state { pub use crate::builder_types::{IsSet, IsUnset, Set, Unset}; @@ -3936,6 +3951,7 @@ pub struct ReportViewBuilder, Option, Option, + Option, Option>, Option, Option, @@ -3971,7 +3987,7 @@ impl ReportViewBuilder { _state: PhantomData, _fields: ( None, None, None, None, None, None, None, None, None, None, None, None, None, None, - None, None, None, None, None, + None, None, None, None, None, None, ), _type: PhantomData, } @@ -3985,7 +4001,7 @@ impl ReportViewBuilder { _state: PhantomData, _fields: ( None, None, None, None, None, None, None, None, None, None, None, None, None, None, - None, None, None, None, None, + None, None, None, None, None, None, ), _type: PhantomData, } @@ -4114,15 +4130,28 @@ where } } +impl ReportViewBuilder { + /// Set the `isAutomated` field (optional) + pub fn is_automated(mut self, value: impl Into>) -> Self { + self._fields.8 = value.into(); + self + } + /// Set the `isAutomated` field to an Option value (optional) + pub fn maybe_is_automated(mut self, value: Option) -> Self { + self._fields.8 = value; + self + } +} + impl ReportViewBuilder { /// Set the `isMuted` field (optional) pub fn is_muted(mut self, value: impl Into>) -> Self { - self._fields.8 = value.into(); + self._fields.9 = value.into(); self } /// Set the `isMuted` field to an Option value (optional) pub fn maybe_is_muted(mut self, value: Option) -> Self { - self._fields.8 = value; + self._fields.9 = value; self } } @@ -4130,12 +4159,12 @@ impl ReportViewBuilder { impl ReportViewBuilder { /// Set the `queue` field (optional) pub fn queue(mut self, value: impl Into>>) -> Self { - self._fields.9 = value.into(); + self._fields.10 = value.into(); self } /// Set the `queue` field to an Option value (optional) pub fn maybe_queue(mut self, value: Option>) -> Self { - self._fields.9 = value; + self._fields.10 = value; self } } @@ -4143,12 +4172,12 @@ impl ReportViewBuilder { impl ReportViewBuilder { /// Set the `queuedAt` field (optional) pub fn queued_at(mut self, value: impl Into>) -> Self { - self._fields.10 = value.into(); + self._fields.11 = value.into(); self } /// Set the `queuedAt` field to an Option value (optional) pub fn maybe_queued_at(mut self, value: Option) -> Self { - self._fields.10 = value; + self._fields.11 = value; self } } @@ -4156,12 +4185,12 @@ impl ReportViewBuilder { impl ReportViewBuilder { /// Set the `relatedReportCount` field (optional) pub fn related_report_count(mut self, value: impl Into>) -> Self { - self._fields.11 = value.into(); + self._fields.12 = value.into(); self } /// Set the `relatedReportCount` field to an Option value (optional) pub fn maybe_related_report_count(mut self, value: Option) -> Self { - self._fields.11 = value; + self._fields.12 = value; self } } @@ -4176,7 +4205,7 @@ where mut self, value: impl Into>, ) -> ReportViewBuilder, S> { - self._fields.12 = Option::Some(value.into()); + self._fields.13 = Option::Some(value.into()); ReportViewBuilder { _state: PhantomData, _fields: self._fields, @@ -4195,7 +4224,7 @@ where mut self, value: impl Into>, ) -> ReportViewBuilder, S> { - self._fields.13 = Option::Some(value.into()); + self._fields.14 = Option::Some(value.into()); ReportViewBuilder { _state: PhantomData, _fields: self._fields, @@ -4214,7 +4243,7 @@ where mut self, value: impl Into>, ) -> ReportViewBuilder, S> { - self._fields.14 = Option::Some(value.into()); + self._fields.15 = Option::Some(value.into()); ReportViewBuilder { _state: PhantomData, _fields: self._fields, @@ -4233,7 +4262,7 @@ where mut self, value: impl Into>, ) -> ReportViewBuilder, S> { - self._fields.15 = Option::Some(value.into()); + self._fields.16 = Option::Some(value.into()); ReportViewBuilder { _state: PhantomData, _fields: self._fields, @@ -4252,7 +4281,7 @@ where mut self, value: impl Into>, ) -> ReportViewBuilder, S> { - self._fields.16 = Option::Some(value.into()); + self._fields.17 = Option::Some(value.into()); ReportViewBuilder { _state: PhantomData, _fields: self._fields, @@ -4264,12 +4293,12 @@ where impl ReportViewBuilder { /// Set the `subjectStatus` field (optional) pub fn subject_status(mut self, value: impl Into>>) -> Self { - self._fields.17 = value.into(); + self._fields.18 = value.into(); self } /// Set the `subjectStatus` field to an Option value (optional) pub fn maybe_subject_status(mut self, value: Option>) -> Self { - self._fields.17 = value; + self._fields.18 = value; self } } @@ -4277,12 +4306,12 @@ impl ReportViewBuilder { impl ReportViewBuilder { /// Set the `updatedAt` field (optional) pub fn updated_at(mut self, value: impl Into>) -> Self { - self._fields.18 = value.into(); + self._fields.19 = value.into(); self } /// Set the `updatedAt` field to an Option value (optional) pub fn maybe_updated_at(mut self, value: Option) -> Self { - self._fields.18 = value; + self._fields.19 = value; self } } @@ -4310,17 +4339,18 @@ where created_at: self._fields.5.unwrap(), event_id: self._fields.6.unwrap(), id: self._fields.7.unwrap(), - is_muted: self._fields.8, - queue: self._fields.9, - queued_at: self._fields.10, - related_report_count: self._fields.11, - report_type: self._fields.12.unwrap(), - reported_by: self._fields.13.unwrap(), - reporter: self._fields.14.unwrap(), - status: self._fields.15.unwrap(), - subject: self._fields.16.unwrap(), - subject_status: self._fields.17, - updated_at: self._fields.18, + is_automated: self._fields.8.or_else(|| Some(false)), + is_muted: self._fields.9, + queue: self._fields.10, + queued_at: self._fields.11, + related_report_count: self._fields.12, + report_type: self._fields.13.unwrap(), + reported_by: self._fields.14.unwrap(), + reporter: self._fields.15.unwrap(), + status: self._fields.16.unwrap(), + subject: self._fields.17.unwrap(), + subject_status: self._fields.18, + updated_at: self._fields.19, extra_data: Default::default(), } } @@ -4335,17 +4365,18 @@ where created_at: self._fields.5.unwrap(), event_id: self._fields.6.unwrap(), id: self._fields.7.unwrap(), - is_muted: self._fields.8, - queue: self._fields.9, - queued_at: self._fields.10, - related_report_count: self._fields.11, - report_type: self._fields.12.unwrap(), - reported_by: self._fields.13.unwrap(), - reporter: self._fields.14.unwrap(), - status: self._fields.15.unwrap(), - subject: self._fields.16.unwrap(), - subject_status: self._fields.17, - updated_at: self._fields.18, + is_automated: self._fields.8.or_else(|| Some(false)), + is_muted: self._fields.9, + queue: self._fields.10, + queued_at: self._fields.11, + related_report_count: self._fields.12, + report_type: self._fields.13.unwrap(), + reported_by: self._fields.14.unwrap(), + reporter: self._fields.15.unwrap(), + status: self._fields.16.unwrap(), + subject: self._fields.17.unwrap(), + subject_status: self._fields.18, + updated_at: self._fields.19, extra_data: Some(extra_data), } } diff --git a/crates/jacquard-api/src/tools_ozone/report/close_reports.rs b/crates/jacquard-api/src/tools_ozone/report/close_reports.rs new file mode 100644 index 000000000..f075d6ccb --- /dev/null +++ b/crates/jacquard-api/src/tools_ozone/report/close_reports.rs @@ -0,0 +1,248 @@ +// @generated by jacquard-lexicon. DO NOT EDIT. +// +// Lexicon: tools.ozone.report.closeReports +// +// 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::deps::smol_str::SmolStr; +use jacquard_common::types::string::UriValue; +use jacquard_common::types::value::Data; +use jacquard_common::{BosStr, CowStr, DefaultStr, FromStaticStr}; +use jacquard_derive::IntoStatic; +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct CloseReports { + ///Optional moderator-only note recorded on each close activity. Not visible to reporters. + #[serde(skip_serializing_if = "Option::is_none")] + pub internal_note: Option, + ///Set true when this action is triggered by an automated process. Defaults to false. Defaults to `false`. + #[serde(skip_serializing_if = "Option::is_none")] + #[serde(default = "_default_close_reports_is_automated")] + pub is_automated: Option, + ///If specified, only reports of the given report types (fully qualified reason NSIDs) are closed. When omitted, all non-closed reports on the subject are targeted. + #[serde(skip_serializing_if = "Option::is_none")] + pub report_types: Option>, + ///Subject DID (account-level reports) or AT-URI (record-level reports) whose reports should be closed. + pub subject: UriValue, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)] +#[serde( + rename_all = "camelCase", + bound(deserialize = "S: Deserialize<'de> + BosStr") +)] +pub struct CloseReportsOutput { + ///Number of reports that were transitioned to closed. + pub closed_count: i64, + ///IDs of the reports that were closed. + pub report_ids: Vec, + #[serde(flatten, default, skip_serializing_if = "Option::is_none")] + pub extra_data: Option>>, +} + +/** Response marker for the `tools.ozone.report.closeReports` procedure. + +Implements `jacquard_common::xrpc::XrpcResp`; successful bodies decode as `Self::Output`, which is `CloseReportsOutput` for this endpoint.*/ +pub struct CloseReportsResponse; +impl jacquard_common::xrpc::XrpcResp for CloseReportsResponse { + const NSID: &'static str = "tools.ozone.report.closeReports"; + const ENCODING: &'static str = "application/json"; + type Output = CloseReportsOutput; + type Err = jacquard_common::xrpc::GenericError; +} + +impl jacquard_common::xrpc::XrpcRequest for CloseReports { + const NSID: &'static str = "tools.ozone.report.closeReports"; + const METHOD: jacquard_common::xrpc::XrpcMethod = + jacquard_common::xrpc::XrpcMethod::Procedure("application/json"); + type Response = CloseReportsResponse; +} + +/** Endpoint marker for the `tools.ozone.report.closeReports` procedure. + +Path: `/xrpc/tools.ozone.report.closeReports`. The request payload type is `CloseReports`; send that request with `jacquard::Client` or use this marker through lower-level `XrpcEndpoint` APIs.*/ +pub struct CloseReportsRequest; +impl jacquard_common::xrpc::XrpcEndpoint for CloseReportsRequest { + const PATH: &'static str = "/xrpc/tools.ozone.report.closeReports"; + const METHOD: jacquard_common::xrpc::XrpcMethod = + jacquard_common::xrpc::XrpcMethod::Procedure("application/json"); + type Request = CloseReports; + type Response = CloseReportsResponse; +} + +fn _default_close_reports_is_automated() -> Option { + Some(false) +} + +pub mod close_reports_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 Subject; + } + /// Empty state - all required fields are unset + pub struct Empty(()); + impl sealed::Sealed for Empty {} + impl State for Empty { + type Subject = Unset; + } + ///State transition - sets the `subject` field to Set + pub struct SetSubject(PhantomData St>); + impl sealed::Sealed for SetSubject {} + impl State for SetSubject { + type Subject = Set; + } + /// Marker types for field names + #[allow(non_camel_case_types)] + pub mod members { + ///Marker type for the `subject` field + pub struct subject(()); + } +} + +/// Builder for constructing an instance of this type. +pub struct CloseReportsBuilder { + _state: PhantomData St>, + _fields: (Option, Option, Option>, Option>), + _type: PhantomData S>, +} + +impl CloseReports { + /// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed + pub fn new() -> CloseReportsBuilder { + CloseReportsBuilder::new() + } +} + +impl CloseReports { + /// Create a new builder for this type + pub fn builder() -> CloseReportsBuilder { + CloseReportsBuilder::builder() + } +} + +impl CloseReportsBuilder { + /// Create a new builder with all fields unset, using the default string type, if needed + pub fn new() -> Self { + CloseReportsBuilder { + _state: PhantomData, + _fields: (None, None, None, None), + _type: PhantomData, + } + } +} + +impl CloseReportsBuilder { + /// Create a new builder with all fields unset + pub fn builder() -> Self { + CloseReportsBuilder { + _state: PhantomData, + _fields: (None, None, None, None), + _type: PhantomData, + } + } +} + +impl CloseReportsBuilder { + /// Set the `internalNote` field (optional) + pub fn internal_note(mut self, value: impl Into>) -> Self { + self._fields.0 = value.into(); + self + } + /// Set the `internalNote` field to an Option value (optional) + pub fn maybe_internal_note(mut self, value: Option) -> Self { + self._fields.0 = value; + self + } +} + +impl CloseReportsBuilder { + /// Set the `isAutomated` field (optional) + pub fn is_automated(mut self, value: impl Into>) -> Self { + self._fields.1 = value.into(); + self + } + /// Set the `isAutomated` field to an Option value (optional) + pub fn maybe_is_automated(mut self, value: Option) -> Self { + self._fields.1 = value; + self + } +} + +impl CloseReportsBuilder { + /// Set the `reportTypes` field (optional) + pub fn report_types(mut self, value: impl Into>>) -> Self { + self._fields.2 = value.into(); + self + } + /// Set the `reportTypes` field to an Option value (optional) + pub fn maybe_report_types(mut self, value: Option>) -> Self { + self._fields.2 = value; + self + } +} + +impl CloseReportsBuilder +where + St: close_reports_state::State, + St::Subject: close_reports_state::IsUnset, +{ + /// Set the `subject` field (required) + pub fn subject( + mut self, + value: impl Into>, + ) -> CloseReportsBuilder, S> { + self._fields.3 = Option::Some(value.into()); + CloseReportsBuilder { + _state: PhantomData, + _fields: self._fields, + _type: PhantomData, + } + } +} + +impl CloseReportsBuilder +where + St: close_reports_state::State, + St::Subject: close_reports_state::IsSet, +{ + /// Build the final struct. + pub fn build(self) -> CloseReports { + CloseReports { + internal_note: self._fields.0, + is_automated: self._fields.1.or_else(|| Some(false)), + report_types: self._fields.2, + subject: self._fields.3.unwrap(), + extra_data: Default::default(), + } + } + /// Build the final struct with custom extra_data. + pub fn build_with_data(self, extra_data: BTreeMap>) -> CloseReports { + CloseReports { + internal_note: self._fields.0, + is_automated: self._fields.1.or_else(|| Some(false)), + report_types: self._fields.2, + subject: self._fields.3.unwrap(), + extra_data: Some(extra_data), + } + } +} diff --git a/crates/jacquard-api/src/tools_ozone/report/create_activity.rs b/crates/jacquard-api/src/tools_ozone/report/create_activity.rs index 01ca0ac3d..e9c4ff6cd 100644 --- a/crates/jacquard-api/src/tools_ozone/report/create_activity.rs +++ b/crates/jacquard-api/src/tools_ozone/report/create_activity.rs @@ -31,6 +31,9 @@ use serde::{Deserialize, Serialize}; pub struct CreateActivity { ///The type of activity to record. pub activity: CreateActivityActivity, + ///ID of the report moderation event. Resolves to the report created from that event. Exactly one of reportId or eventId must be provided. + #[serde(skip_serializing_if = "Option::is_none")] + pub event_id: Option, ///Optional moderator-only note. Not visible to reporters. #[serde(skip_serializing_if = "Option::is_none")] pub internal_note: Option, @@ -41,8 +44,9 @@ pub struct CreateActivity { ///Optional public-facing note, potentially visible to the reporter. #[serde(skip_serializing_if = "Option::is_none")] pub public_note: Option, - ///ID of the report to record activity on - pub report_id: i64, + ///ID of the report to record activity on. Exactly one of reportId or eventId must be provided. + #[serde(skip_serializing_if = "Option::is_none")] + pub report_id: Option, #[serde(flatten, default, skip_serializing_if = "Option::is_none")] pub extra_data: Option>>, } @@ -81,7 +85,7 @@ pub struct CreateActivityOutput { )] #[serde(tag = "error", content = "message")] pub enum CreateActivityError { - /// No report exists with the given reportId + /// No report exists with the given reportId or eventId #[serde(rename = "ReportNotFound")] ReportNotFound(Option), /// The requested state transition is not permitted from the report's current status @@ -178,36 +182,24 @@ pub mod create_activity_state { /// State trait tracking which required fields have been set pub trait State: sealed::Sealed { type Activity; - type ReportId; } /// Empty state - all required fields are unset pub struct Empty(()); impl sealed::Sealed for Empty {} impl State for Empty { type Activity = Unset; - type ReportId = Unset; } ///State transition - sets the `activity` field to Set pub struct SetActivity(PhantomData St>); impl sealed::Sealed for SetActivity {} impl State for SetActivity { type Activity = Set; - type ReportId = St::ReportId; - } - ///State transition - sets the `report_id` field to Set - pub struct SetReportId(PhantomData St>); - impl sealed::Sealed for SetReportId {} - impl State for SetReportId { - type Activity = St::Activity; - type ReportId = Set; } /// Marker types for field names #[allow(non_camel_case_types)] pub mod members { ///Marker type for the `activity` field pub struct activity(()); - ///Marker type for the `report_id` field - pub struct report_id(()); } } @@ -216,6 +208,7 @@ pub struct CreateActivityBuilder St>, _fields: ( Option>, + Option, Option, Option, Option, @@ -243,7 +236,7 @@ impl CreateActivityBuilder { pub fn new() -> Self { CreateActivityBuilder { _state: PhantomData, - _fields: (None, None, None, None, None), + _fields: (None, None, None, None, None, None), _type: PhantomData, } } @@ -254,7 +247,7 @@ impl CreateActivityBuilder { pub fn builder() -> Self { CreateActivityBuilder { _state: PhantomData, - _fields: (None, None, None, None, None), + _fields: (None, None, None, None, None, None), _type: PhantomData, } } @@ -279,15 +272,28 @@ where } } +impl CreateActivityBuilder { + /// Set the `eventId` field (optional) + pub fn event_id(mut self, value: impl Into>) -> Self { + self._fields.1 = value.into(); + self + } + /// Set the `eventId` field to an Option value (optional) + pub fn maybe_event_id(mut self, value: Option) -> Self { + self._fields.1 = value; + self + } +} + impl CreateActivityBuilder { /// Set the `internalNote` field (optional) pub fn internal_note(mut self, value: impl Into>) -> Self { - self._fields.1 = value.into(); + self._fields.2 = value.into(); self } /// Set the `internalNote` field to an Option value (optional) pub fn maybe_internal_note(mut self, value: Option) -> Self { - self._fields.1 = value; + self._fields.2 = value; self } } @@ -295,12 +301,12 @@ impl CreateActivityBuilder { impl CreateActivityBuilder { /// Set the `isAutomated` field (optional) pub fn is_automated(mut self, value: impl Into>) -> Self { - self._fields.2 = value.into(); + self._fields.3 = value.into(); self } /// Set the `isAutomated` field to an Option value (optional) pub fn maybe_is_automated(mut self, value: Option) -> Self { - self._fields.2 = value; + self._fields.3 = value; self } } @@ -308,32 +314,26 @@ impl CreateActivityBuilder { impl CreateActivityBuilder { /// Set the `publicNote` field (optional) pub fn public_note(mut self, value: impl Into>) -> Self { - self._fields.3 = value.into(); + self._fields.4 = value.into(); self } /// Set the `publicNote` field to an Option value (optional) pub fn maybe_public_note(mut self, value: Option) -> Self { - self._fields.3 = value; + self._fields.4 = value; self } } -impl CreateActivityBuilder -where - St: create_activity_state::State, - St::ReportId: create_activity_state::IsUnset, -{ - /// Set the `reportId` field (required) - pub fn report_id( - mut self, - value: impl Into, - ) -> CreateActivityBuilder, S> { - self._fields.4 = Option::Some(value.into()); - CreateActivityBuilder { - _state: PhantomData, - _fields: self._fields, - _type: PhantomData, - } +impl CreateActivityBuilder { + /// Set the `reportId` field (optional) + pub fn report_id(mut self, value: impl Into>) -> Self { + self._fields.5 = value.into(); + self + } + /// Set the `reportId` field to an Option value (optional) + pub fn maybe_report_id(mut self, value: Option) -> Self { + self._fields.5 = value; + self } } @@ -341,16 +341,16 @@ impl CreateActivityBuilder where St: create_activity_state::State, St::Activity: create_activity_state::IsSet, - St::ReportId: create_activity_state::IsSet, { /// Build the final struct. pub fn build(self) -> CreateActivity { CreateActivity { activity: self._fields.0.unwrap(), - internal_note: self._fields.1, - is_automated: self._fields.2.or_else(|| Some(false)), - public_note: self._fields.3, - report_id: self._fields.4.unwrap(), + event_id: self._fields.1, + internal_note: self._fields.2, + is_automated: self._fields.3.or_else(|| Some(false)), + public_note: self._fields.4, + report_id: self._fields.5, extra_data: Default::default(), } } @@ -358,10 +358,11 @@ where pub fn build_with_data(self, extra_data: BTreeMap>) -> CreateActivity { CreateActivity { activity: self._fields.0.unwrap(), - internal_note: self._fields.1, - is_automated: self._fields.2.or_else(|| Some(false)), - public_note: self._fields.3, - report_id: self._fields.4.unwrap(), + event_id: self._fields.1, + internal_note: self._fields.2, + is_automated: self._fields.3.or_else(|| Some(false)), + public_note: self._fields.4, + report_id: self._fields.5, extra_data: Some(extra_data), } } diff --git a/crates/jacquard-api/src/zone_stratos/feed/post.rs b/crates/jacquard-api/src/zone_stratos/feed/post.rs index 38fd0fe9c..14db2e009 100644 --- a/crates/jacquard-api/src/zone_stratos/feed/post.rs +++ b/crates/jacquard-api/src/zone_stratos/feed/post.rs @@ -184,6 +184,32 @@ impl LexiconSchema for Post { }); } } + if let Some(values) = &self.tags { + for value in values { + #[allow(unused_comparisons)] + if ::len(value.as_ref()) > 640usize { + return Err(ConstraintError::MaxLength { + path: ValidationPath::from_field("tags"), + max: 640usize, + actual: ::len(value.as_ref()), + }); + } + } + } + if let Some(values) = &self.tags { + for value in values { + { + let count = UnicodeSegmentation::graphemes(value.as_ref(), true).count(); + if count > 64usize { + return Err(ConstraintError::MaxGraphemes { + path: ValidationPath::from_field("tags"), + max: 64usize, + actual: count, + }); + } + } + } + } if let Some(ref value) = self.text { #[allow(unused_comparisons)] if ::len(value.as_ref()) > 3000usize { diff --git a/crates/jacquard-common/src/serde_bytes_helper.rs b/crates/jacquard-common/src/serde_bytes_helper.rs index de6a425a3..239d5de23 100644 --- a/crates/jacquard-common/src/serde_bytes_helper.rs +++ b/crates/jacquard-common/src/serde_bytes_helper.rs @@ -11,7 +11,7 @@ use base64::{ use bytes::Bytes; use serde::{ Deserializer, Serializer, - de::{self, MapAccess, Visitor}, + de::{self, MapAccess, SeqAccess, Visitor}, }; /// Serialize Bytes as a CBOR byte string @@ -37,7 +37,7 @@ where D: Deserializer<'de>, { if deserializer.is_human_readable() { - Ok(deserializer.deserialize_map(BytesVisitor)?) + deserializer.deserialize_any(BytesVisitor) } else { let vec: Vec = serde_bytes::deserialize(deserializer)?; Ok(Bytes::from(vec)) @@ -74,6 +74,17 @@ impl<'de> Visitor<'de> for BytesVisitor { Ok(Bytes::from_owner(v)) } + fn visit_seq(self, mut seq: A) -> Result + where + A: SeqAccess<'de>, + { + let mut value = Vec::with_capacity(seq.size_hint().unwrap_or(0)); + while let Some(byte) = seq.next_element()? { + value.push(byte); + } + Ok(Bytes::from(value)) + } + fn visit_map(self, mut map: A) -> Result where A: MapAccess<'de>, @@ -109,3 +120,32 @@ impl<'de> Visitor<'de> for BytesVisitor { bytes.ok_or_else(|| de::Error::missing_field("$bytes")) } } + +#[cfg(test)] +mod tests { + use super::*; + use serde::{Deserialize, Serialize}; + + #[derive(Debug, PartialEq, Eq, Serialize, Deserialize)] + struct BytePayload { + #[serde(with = "super")] + bytes: Bytes, + } + + #[derive(Debug, PartialEq, Eq, Serialize, Deserialize)] + #[serde(tag = "$type")] + enum TaggedPayload { + #[serde(rename = "com.example.bytes")] + Bytes(BytePayload), + } + + #[test] + fn dag_cbor_bytes_survive_internally_tagged_buffering() { + let value = TaggedPayload::Bytes(BytePayload { + bytes: Bytes::from_static(&[0, 1, 2, 255]), + }); + let encoded = serde_ipld_dagcbor::to_vec(&value).unwrap(); + let decoded: TaggedPayload = serde_ipld_dagcbor::from_slice(&encoded).unwrap(); + assert_eq!(decoded, value); + } +} diff --git a/crates/jacquard-common/src/types.rs b/crates/jacquard-common/src/types.rs index 41dfcd253..17deec91a 100644 --- a/crates/jacquard-common/src/types.rs +++ b/crates/jacquard-common/src/types.rs @@ -3,7 +3,7 @@ use serde::{Deserialize, Serialize}; // Re-export Lazy from crate root for submodule use via `super::Lazy` pub use crate::Lazy; -/// AT Protocol URI (at://) types and validation +/// AT Protocol URI (`at://`) types and validation, including permissioned space URIs. pub mod aturi; /// Blob references for binary data pub mod blob; diff --git a/crates/jacquard-common/src/types/aturi.rs b/crates/jacquard-common/src/types/aturi.rs index d31eea2f0..ca80e1abc 100644 --- a/crates/jacquard-common/src/types/aturi.rs +++ b/crates/jacquard-common/src/types/aturi.rs @@ -20,7 +20,7 @@ use regex_automata::meta::Regex; #[cfg(target_arch = "wasm32")] use regex_lite::Regex; use serde::Serializer; -use serde::{de::Error, Deserialize, Deserializer, Serialize}; +use serde::{Deserialize, Deserializer, Serialize, de::Error}; use smol_str::SmolStr; use super::Lazy; @@ -276,9 +276,7 @@ fn validate_uri_shape(uri: &str) -> Result { // The space marker is positional: only the first path segment after the // authority may carry it. A standard URI with a collection or rkey that // happens to be "space" must parse as standard. - let after_scheme = uri - .strip_prefix("at://") - .unwrap_or(uri); + let after_scheme = uri.strip_prefix("at://").unwrap_or(uri); let first_path_segment = after_scheme.split('/').nth(1); if first_path_segment == Some("space") { validate_space_and_index(uri).map(|indices| UriShape::Space { indices }) @@ -1393,10 +1391,12 @@ mod tests { fn permissioned_space_rejects_noncanonical_forms() { assert!(AtSpaceUri::new("at://did:plc:space/com.example.type/demo").is_err()); assert!(AtSpaceUri::new("at://did:plc:space/space/com.example.type/demo/").is_err()); - assert!(AtSpaceUri::new( - "at://did:plc:space/space/com.example.type/demo/did:plc:author/com.example.record" - ) - .is_err()); + assert!( + AtSpaceUri::new( + "at://did:plc:space/space/com.example.type/demo/did:plc:author/com.example.record" + ) + .is_err() + ); } #[test] diff --git a/crates/jacquard-common/src/types/cid.rs b/crates/jacquard-common/src/types/cid.rs index 4e633ddc1..3f61a3522 100644 --- a/crates/jacquard-common/src/types/cid.rs +++ b/crates/jacquard-common/src/types/cid.rs @@ -3,7 +3,7 @@ use crate::{CowStr, IntoStatic}; use alloc::string::{String, ToString}; pub use cid::Cid as IpldCid; use core::{convert::Infallible, fmt, ops::Deref, str::FromStr}; -use serde::{de::Visitor, Deserialize, Deserializer, Serialize, Serializer}; +use serde::{Deserialize, Deserializer, Serialize, Serializer, de::Visitor}; use smol_str::{SmolStr, ToSmolStr}; /// CID codec for AT Protocol (raw). diff --git a/crates/jacquard-lexicon/src/codegen.rs b/crates/jacquard-lexicon/src/codegen.rs index ddc94e617..42540260f 100644 --- a/crates/jacquard-lexicon/src/codegen.rs +++ b/crates/jacquard-lexicon/src/codegen.rs @@ -384,6 +384,7 @@ impl<'c> CodeGenerator<'c> { // resolver (Phase 5), not generated as code. Ok(GeneratedCode::default()) } + LexUserType::Space(space) => self.generate_space(nsid, def_name, space), } } } diff --git a/crates/jacquard-lexicon/src/codegen/collect.rs b/crates/jacquard-lexicon/src/codegen/collect.rs index d536a3865..a76a94857 100644 --- a/crates/jacquard-lexicon/src/codegen/collect.rs +++ b/crates/jacquard-lexicon/src/codegen/collect.rs @@ -134,6 +134,9 @@ impl<'c> CodeGenerator<'c> { Some(LexStringFormat::AtUri) => { imports.common.insert(CommonType::AtUri); } + Some(LexStringFormat::SpaceRef) => { + imports.common.insert(CommonType::AtSpaceUri); + } Some(LexStringFormat::Uri) => { imports.common.insert(CommonType::UriValue); } @@ -723,6 +726,8 @@ impl<'c> CodeGenerator<'c> { i.external.insert(ExternalImport::Bytes); i } + // Space declarations generate metadata-only marker types. + LexUserType::Space(_) => ImportSet::default(), // Boolean, plain Integer, Blob: type aliases with no special imports. _ => ImportSet::default(), }; diff --git a/crates/jacquard-lexicon/src/codegen/prettify.rs b/crates/jacquard-lexicon/src/codegen/prettify.rs index 87af16719..6b2874e5d 100644 --- a/crates/jacquard-lexicon/src/codegen/prettify.rs +++ b/crates/jacquard-lexicon/src/codegen/prettify.rs @@ -19,6 +19,7 @@ pub enum CommonType { Did, Handle, AtUri, + AtSpaceUri, Nsid, Tid, Cid, @@ -51,6 +52,7 @@ impl CommonType { Self::Did => "Did", Self::Handle => "Handle", Self::AtUri => "AtUri", + Self::AtSpaceUri => "AtSpaceUri", Self::Nsid => "Nsid", Self::Tid => "Tid", Self::Cid => "Cid", @@ -88,6 +90,7 @@ impl CommonType { Self::CidLink => ("jacquard_common::types::cid::CidLink", true), Self::BlobRef => ("jacquard_common::types::blob::BlobRef", true), Self::AtUri => ("jacquard_common::types::string::AtUri", true), + Self::AtSpaceUri => ("jacquard_common::types::aturi::AtSpaceUri", true), Self::Nsid => ("jacquard_common::types::string::Nsid", true), Self::Cid => ("jacquard_common::types::string::Cid", true), // RecordKey is a COMPOSITE type: RecordKey>. needs_type_param @@ -117,6 +120,7 @@ impl CommonType { | Self::RecordKey | Self::Rkey | Self::UriValue => "jacquard_common::types::string", + Self::AtSpaceUri => "jacquard_common::types::aturi", Self::AtIdentifier => "jacquard_common::types::ident", Self::CidLink => "jacquard_common::types::cid", Self::BlobRef => "jacquard_common::types::blob", diff --git a/crates/jacquard-lexicon/src/codegen/structs.rs b/crates/jacquard-lexicon/src/codegen/structs.rs index a5a68b0a3..332457214 100644 --- a/crates/jacquard-lexicon/src/codegen/structs.rs +++ b/crates/jacquard-lexicon/src/codegen/structs.rs @@ -804,6 +804,46 @@ impl<'c> CodeGenerator<'c> { Ok(GeneratedCode::type_only(enum_def)) } + /// Generate a permissioned-space declaration marker. + /// + /// `type: "space"` is lexicon metadata rather than a wire object. Keep the + /// declaration available to repository code without inventing a serde + /// representation for fields that are never sent on the wire. + pub(super) fn generate_space( + &self, + nsid: &str, + def_name: &str, + space: &crate::lexicon::LexSpace<'static>, + ) -> Result { + let type_name = self.def_to_type_name(nsid, def_name); + let ident = syn::Ident::new(&type_name, proc_macro2::Span::call_site()); + let doc = self.generate_doc_comment(space.description.as_ref()); + let key = space.key.as_ref().map(|value| value.as_ref()).unwrap_or(""); + let name = space + .name + .as_ref() + .map(|value| value.as_ref()) + .unwrap_or(""); + let collections: Vec<&str> = space + .collections + .iter() + .map(|value| value.as_ref()) + .collect(); + + let tokens = quote! { + #doc + #[derive(Clone, Copy, Debug, Default, Eq, PartialEq)] + pub struct #ident; + + impl #ident { + pub const KEY: &'static str = #key; + pub const NAME: &'static str = #name; + pub const COLLECTIONS: &'static [&'static str] = &[#(#collections),*]; + } + }; + Ok(GeneratedCode::type_only(tokens)) + } + /// Generate enum for string with known values. pub(super) fn generate_known_values_enum( &self, diff --git a/crates/jacquard-lexicon/src/codegen/type_param.rs b/crates/jacquard-lexicon/src/codegen/type_param.rs index 28be20188..b3ba083e8 100644 --- a/crates/jacquard-lexicon/src/codegen/type_param.rs +++ b/crates/jacquard-lexicon/src/codegen/type_param.rs @@ -81,6 +81,7 @@ impl HasTypeParam for LexUserType<'_> { } LexUserType::Union(_) => true, // Union enums are always generated with LexUserType::PermissionSet(_) => true, // Permission sets are parameterized on S + LexUserType::Space(_) => true, } } } diff --git a/crates/jacquard-lexicon/src/codegen/types.rs b/crates/jacquard-lexicon/src/codegen/types.rs index 9706ce8c7..0497049e0 100644 --- a/crates/jacquard-lexicon/src/codegen/types.rs +++ b/crates/jacquard-lexicon/src/codegen/types.rs @@ -183,6 +183,7 @@ impl<'c> CodeGenerator<'c> { Some(LexStringFormat::AtIdentifier) => resolved.type_tokens(&CommonType::AtIdentifier), Some(LexStringFormat::Nsid) => resolved.type_tokens(&CommonType::Nsid), Some(LexStringFormat::AtUri) => resolved.type_tokens(&CommonType::AtUri), + Some(LexStringFormat::SpaceRef) => resolved.type_tokens(&CommonType::AtSpaceUri), Some(LexStringFormat::Uri) => resolved.type_tokens(&CommonType::UriValue), Some(LexStringFormat::Cid) => resolved.type_tokens(&CommonType::Cid), Some(LexStringFormat::Language) => resolved.type_tokens(&CommonType::Language), diff --git a/crates/jacquard-lexicon/src/derive_impl/doc_to_tokens.rs b/crates/jacquard-lexicon/src/derive_impl/doc_to_tokens.rs index f629b97dd..e8fb1f9a7 100644 --- a/crates/jacquard-lexicon/src/derive_impl/doc_to_tokens.rs +++ b/crates/jacquard-lexicon/src/derive_impl/doc_to_tokens.rs @@ -292,6 +292,56 @@ fn user_type_to_tokens( permissions: vec![], }) }, + LexUserType::Space(space) => { + let description = field_cow_str("description", &space.description, p); + let key = field_cow_str("key", &space.key, p); + let name = field_cow_str("name", &space.name, p); + let cow = &p.cow; + let btree = &p.btree; + let name_lang = match &space.name_lang { + Some(values) => { + let entries: Vec<_> = values + .iter() + .map(|(language, value)| { + let language = language.as_ref(); + let value = value.as_ref(); + quote! { + map.insert(#cow::new_static(#language), #cow::new_static(#value)); + } + }) + .collect(); + quote! { + name_lang: Some({ + let mut map = #btree::new(); + #(#entries)* + map + }), + } + } + None => TokenStream::new(), + }; + let collections: Vec<_> = space + .collections + .iter() + .map(|collection| { + let collection = collection.as_ref(); + quote! { + ::jacquard_common::types::nsid::Nsid::from( + #cow::new_static(#collection) + ) + } + }) + .collect(); + quote! { + #lex LexUserType::Space(#lex LexSpace { + #description + #key + #name + #name_lang + collections: vec![#(#collections),*], + }) + } + } } } @@ -579,6 +629,7 @@ fn lex_string_to_tokens(s: &LexString, p: &DocPaths) -> TokenStream { LexStringFormat::Did => quote! { #lex LexStringFormat::Did }, LexStringFormat::Handle => quote! { #lex LexStringFormat::Handle }, LexStringFormat::AtUri => quote! { #lex LexStringFormat::AtUri }, + LexStringFormat::SpaceRef => quote! { #lex LexStringFormat::SpaceRef }, LexStringFormat::Nsid => quote! { #lex LexStringFormat::Nsid }, LexStringFormat::Cid => quote! { #lex LexStringFormat::Cid }, LexStringFormat::Datetime => quote! { #lex LexStringFormat::Datetime }, diff --git a/crates/jacquard-lexicon/src/lexicon.rs b/crates/jacquard-lexicon/src/lexicon.rs index 15f8757e2..89451a272 100644 --- a/crates/jacquard-lexicon/src/lexicon.rs +++ b/crates/jacquard-lexicon/src/lexicon.rs @@ -79,6 +79,9 @@ pub enum LexStringFormat { Language, Tid, RecordKey, + /// Permissioned space URI reference (`at://.../space/...`). + #[serde(rename = "space-ref")] + SpaceRef, } #[skip_serializing_none] #[derive(Debug, Serialize, Deserialize, PartialEq, Eq, Clone, Default)] @@ -379,6 +382,28 @@ pub struct LexXrpcSubscription<'s> { pub errors: Option>>, } +// Permissioned spaces + +/// A permissioned-space declaration (`type: "space"`). +/// +/// This is a Lexicon extension used by proposal-0016. The parser keeps the +/// declaration in the same AST as records, procedures, and permission sets so +/// resolved documents do not need a parallel JSON model. +#[skip_serializing_none] +#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, Clone, Default)] +pub struct LexSpace<'s> { + #[serde(borrow)] + pub description: Option>, + #[serde(borrow)] + pub key: Option>, + #[serde(borrow)] + pub name: Option>, + #[serde(default, rename = "name:lang")] + pub name_lang: Option, CowStr<'s>>>, + #[serde(borrow)] + pub collections: Vec>>, +} + // database #[derive(Debug, Serialize, Deserialize, PartialEq, Eq, Clone)] @@ -596,6 +621,9 @@ pub enum LexUserType<'s> { // lexPermissionSet #[serde(borrow)] PermissionSet(LexPermissionSet<'s>), + // proposal-0016 permissioned space declaration + #[serde(borrow)] + Space(LexSpace<'s>), } // IntoStatic implementations for all lexicon types @@ -1052,6 +1080,24 @@ impl IntoStatic for LexPermissionSet<'_> { } } +impl IntoStatic for LexSpace<'_> { + type Output = LexSpace<'static>; + + fn into_static(self) -> Self::Output { + LexSpace { + description: self.description.into_static(), + key: self.key.into_static(), + name: self.name.into_static(), + name_lang: self.name_lang.into_static(), + collections: self + .collections + .into_iter() + .map(|collection| collection.into_static()) + .collect(), + } + } +} + impl IntoStatic for LexUserType<'_> { type Output = LexUserType<'static>; fn into_static(self) -> Self::Output { @@ -1072,6 +1118,7 @@ impl IntoStatic for LexUserType<'_> { Self::Unknown(x) => LexUserType::Unknown(x.into_static()), Self::Union(x) => LexUserType::Union(x.into_static()), Self::PermissionSet(x) => LexUserType::PermissionSet(x.into_static()), + Self::Space(x) => LexUserType::Space(x.into_static()), } } } diff --git a/crates/jacquard-oauth/src/dpop.rs b/crates/jacquard-oauth/src/dpop.rs index 49552630a..7e735780e 100644 --- a/crates/jacquard-oauth/src/dpop.rs +++ b/crates/jacquard-oauth/src/dpop.rs @@ -817,6 +817,7 @@ pub fn build_dpop_proof( htu: Some(url), ath, nonce, + cnf: None, }, }; Ok(signing::create_signed_jwt_es256( diff --git a/crates/jacquard-oauth/src/jose/jwt.rs b/crates/jacquard-oauth/src/jose/jwt.rs index b141ff5b6..11f342239 100644 --- a/crates/jacquard-oauth/src/jose/jwt.rs +++ b/crates/jacquard-oauth/src/jose/jwt.rs @@ -83,7 +83,7 @@ pub struct PublicClaims { /// HTTP method of the request the DPoP proof is bound to (e.g., `"POST"`). #[serde(skip_serializing_if = "Option::is_none")] pub htm: Option, - /// HTTP target URI of the request the DPoP proof is bound to. + /// HTTP target URI of the DPoP proof is bound to. #[serde(skip_serializing_if = "Option::is_none")] pub htu: Option, /// Access token hash: base64url-encoded SHA-256 of the access token, binding the proof to a specific token. @@ -92,6 +92,17 @@ pub struct PublicClaims { /// Server-provided nonce, included to prevent replay attacks when required by the authorization server. #[serde(skip_serializing_if = "Option::is_none")] pub nonce: Option, + /// DPoP confirmation key thumbprint for a bound access or space credential token. + #[serde(skip_serializing_if = "Option::is_none")] + pub cnf: Option>, +} + +/// DPoP confirmation claim used by tokens bound to a holder key. +#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] +#[serde(bound(deserialize = "S: serde::Deserialize<'de> + BosStr"))] +pub struct Confirmation { + /// RFC 7638 JWK thumbprint of the holder key. + pub jkt: S, } /// Manual `Default` impl to avoid a spurious `S: Default` bound from the derive macro. @@ -104,6 +115,7 @@ impl Default for PublicClaims { htu: None, ath: None, nonce: None, + cnf: None, } } } @@ -159,6 +171,20 @@ where htu: self.htu.map(IntoStatic::into_static), ath: self.ath.map(IntoStatic::into_static), nonce: self.nonce.map(IntoStatic::into_static), + cnf: self.cnf.map(IntoStatic::into_static), + } + } +} + +impl IntoStatic for Confirmation +where + S: BosStr + IntoStatic, + S::Output: BosStr, +{ + type Output = Confirmation; + fn into_static(self) -> Self::Output { + Confirmation { + jkt: self.jkt.into_static(), } } } diff --git a/crates/jacquard-repo/Cargo.toml b/crates/jacquard-repo/Cargo.toml index 757f94544..cdb61110f 100644 --- a/crates/jacquard-repo/Cargo.toml +++ b/crates/jacquard-repo/Cargo.toml @@ -18,6 +18,7 @@ default = [] # Internal jacquard-common = { path = "../jacquard-common", version = "0.12.1", features = ["crypto-ed25519", "crypto-k256", "crypto-p256"] } jacquard-derive = { path = "../jacquard-derive", version = "0.12.1" } +jacquard-lexicon = { path = "../jacquard-lexicon", version = "0.12.1" } jacquard-api = { path = "../jacquard-api", version = "0.12.1", features = ["streaming"] } # Serialization @@ -43,6 +44,7 @@ hkdf = "0.12" hmac = "0.12" rand = "0.8" serde_json = "1.0" +url = "2.5" # Error handling thiserror.workspace = true diff --git a/crates/jacquard-repo/src/lib.rs b/crates/jacquard-repo/src/lib.rs index b54a736e8..5aef6916c 100644 --- a/crates/jacquard-repo/src/lib.rs +++ b/crates/jacquard-repo/src/lib.rs @@ -47,15 +47,15 @@ pub mod car; pub mod commit; pub mod error; pub mod mst; +pub mod permissioned; pub mod repo; pub mod storage; -pub mod permissioned; pub use error::{RepoError, RepoErrorKind, Result}; pub use mst::{Mst, MstDiff, WriteOp}; +pub use permissioned::{LtHash, SignedCommit}; pub use repo::{CommitData, Repository}; pub use storage::{BlockStore, FileBlockStore, LayeredBlockStore, MemoryBlockStore}; -pub use permissioned::{LtHash, PermissionedPath, SignedCommit}; /// DAG-CBOR codec identifier for CIDs (0x71) pub const DAG_CBOR_CID_CODEC: u64 = 0x71; diff --git a/crates/jacquard-repo/src/permissioned/mod.rs b/crates/jacquard-repo/src/permissioned/mod.rs index c0f079ada..62ff0f17d 100644 --- a/crates/jacquard-repo/src/permissioned/mod.rs +++ b/crates/jacquard-repo/src/permissioned/mod.rs @@ -15,12 +15,13 @@ use ed25519_dalek::{Signature, Signer, Verifier, VerifyingKey}; use hmac::{Hmac, Mac}; use jacquard_common::SmolStr; use jacquard_common::types::aturi::AtSpaceUri; -use jacquard_common::types::cid::Cid as AtCid; +use jacquard_common::types::cid::{Cid as AtCid, CidLink}; use jacquard_common::types::did::Did; use jacquard_common::types::ident::AtIdentifier; use jacquard_common::types::nsid::Nsid; use jacquard_common::types::recordkey::Rkey; use jacquard_common::types::tid::Tid; +use jacquard_common::types::value::Data; type SpaceUri = AtSpaceUri; type DidOwned = Did; @@ -43,7 +44,12 @@ const COMMIT_DOMAIN: &[u8] = b"atproto-space-v1"; pub enum PermissionedError { /// A string did not satisfy the protocol syntax or length bound. #[error("invalid {field}: {value}")] - InvalidComponent { field: &'static str, value: String }, + InvalidComponent { + /// Name of the invalid component. + field: &'static str, + /// Supplied invalid value. + value: String, + }, /// A space declaration did not satisfy the required shape. #[error("invalid space declaration: {0}")] InvalidDeclaration(String), @@ -80,19 +86,10 @@ fn invalid_component(field: &'static str, value: impl Into) -> Permissio } } -fn space_uri(uri: impl AsRef) -> Result { - SpaceUri::new_owned(uri) - .map_err(|error| invalid_component("permissioned URI", error.to_string())) -} - fn parse_did(field: &'static str, value: impl AsRef) -> Result { DidOwned::from_str(value.as_ref()).map_err(|_| invalid_component(field, value.as_ref())) } -fn parse_identifier(field: &'static str, value: impl AsRef) -> Result { - Identifier::from_str(value.as_ref()).map_err(|_| invalid_component(field, value.as_ref())) -} - fn parse_nsid(field: &'static str, value: impl AsRef) -> Result { NsidOwned::from_str(value.as_ref()).map_err(|_| invalid_component(field, value.as_ref())) } @@ -101,10 +98,6 @@ fn parse_rkey(field: &'static str, value: impl AsRef) -> Result RkeyOwned::from_str(value.as_ref()).map_err(|_| invalid_component(field, value.as_ref())) } -fn parse_cid(field: &'static str, value: impl AsRef) -> Result { - CidOwned::from_str(value.as_ref()).map_err(|_| invalid_component(field, value.as_ref())) -} - fn parse_tid(field: &'static str, value: impl AsRef) -> Result { Tid::from_str(value.as_ref()).map_err(|_| invalid_component(field, value.as_ref())) } @@ -262,8 +255,11 @@ impl LtHash { /// Inputs used to frame a signed permissioned commit context. #[derive(Debug, Clone, PartialEq, Eq)] pub struct CommitContext { + /// Canonical permissioned-space URI. pub space: SpaceUri, + /// DID of the record author. pub author: DidOwned, + /// Host-assigned commit revision. pub rev: Tid, } @@ -285,6 +281,42 @@ pub struct SignedCommit { pub rev: Tid, } +impl TryFrom for SignedCommit { + type Error = PermissionedError; + + fn try_from(value: jacquard_api::com_atproto::space::SignedCommit) -> Result { + fn array32(field: &'static str, value: Bytes) -> Result<[u8; 32]> { + value.as_ref().try_into().map_err(|_| { + PermissionedError::InvalidCommit(format!("{field} must contain 32 bytes")) + }) + } + let ver = u8::try_from(value.ver) + .map_err(|_| PermissionedError::InvalidCommit("version is out of range".into()))?; + Ok(Self { + ver, + hash: array32("hash", value.hash)?, + ikm: array32("ikm", value.ikm)?, + mac: array32("mac", value.mac)?, + sig: value.sig.to_vec(), + rev: value.rev, + }) + } +} + +impl From for jacquard_api::com_atproto::space::SignedCommit { + fn from(value: SignedCommit) -> Self { + Self { + hash: Bytes::copy_from_slice(&value.hash), + ikm: Bytes::copy_from_slice(&value.ikm), + mac: Bytes::copy_from_slice(&value.mac), + rev: value.rev, + sig: Bytes::from(value.sig), + ver: i64::from(value.ver), + extra_data: None, + } + } +} + impl SignedCommit { /// Sign a commit with fresh random IKM. pub fn sign( @@ -331,15 +363,18 @@ impl SignedCommit { key.verify(&context_bytes, &signature) .map_err(|_| PermissionedError::InvalidCommit("signature mismatch".into())) } - /// Encode the commit as canonical DAG-CBOR. + /// Encode the commit as canonical DAG-CBOR using generated byte-string fields. pub fn to_cbor(&self) -> Result> { - serde_ipld_dagcbor::to_vec(self) + let generated: jacquard_api::com_atproto::space::SignedCommit = self.clone().into(); + serde_ipld_dagcbor::to_vec(&generated) .map_err(|error| PermissionedError::Serialization(error.to_string())) } - /// Decode a DAG-CBOR commit. + /// Decode and length-check a generated DAG-CBOR commit. pub fn from_cbor(bytes: &[u8]) -> Result { - serde_ipld_dagcbor::from_slice(bytes) - .map_err(|error| PermissionedError::Serialization(error.to_string())) + let generated: jacquard_api::com_atproto::space::SignedCommit = + serde_ipld_dagcbor::from_slice(bytes) + .map_err(|error| PermissionedError::Serialization(error.to_string()))?; + Self::try_from(generated) } } @@ -376,19 +411,31 @@ fn compute_mac(ikm: &[u8; 32], context: &[u8], hash: &[u8; 32]) -> [u8; 32] { /// A pure record write candidate. #[derive(Debug, Clone, PartialEq, Eq)] pub enum WriteOperation { + /// Create a new record. Create { + /// Record URI to create. uri: SpaceUri, + /// CID of the new record block. cid: CidOwned, + /// Canonical record bytes. value: Bytes, }, + /// Replace an existing record. Update { + /// Record URI to replace. uri: SpaceUri, + /// CID currently stored at the URI. prev: CidOwned, + /// CID of the replacement block. cid: CidOwned, + /// Replacement record bytes. value: Bytes, }, + /// Delete an existing record. Delete { + /// Record URI to remove. uri: SpaceUri, + /// CID currently stored at the URI. prev: CidOwned, }, } @@ -396,22 +443,29 @@ pub enum WriteOperation { /// Current in-memory values used by pure write validation and conformance tests. #[derive(Debug, Clone, Default, PartialEq, Eq)] pub struct WriteState { + /// Current records keyed by canonical space URI. pub records: HashMap, + /// Current LtHash accumulator. pub lthash: LtHash, } /// A current record value and CID. #[derive(Debug, Clone, PartialEq, Eq)] pub struct RecordValue { + /// Current record block CID. pub cid: CidOwned, + /// Canonical record bytes. pub value: Bytes, + /// Record author identifier. pub author: Identifier, } /// One write's result in input order. #[derive(Debug, Clone, PartialEq, Eq)] pub struct WriteResult { + /// Canonical URI affected by the write. pub uri: SpaceUri, + /// New record CID, or `None` for deletion. pub cid: Option, } @@ -419,31 +473,47 @@ pub struct WriteResult { #[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] #[serde(rename_all = "lowercase")] pub enum OplogAction { + /// A record was created. Create, + /// A record was replaced. Update, + /// A record was deleted. Delete, } /// Reference-shaped oplog entry. #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] pub struct OplogEntry { + /// Space containing the operation. pub space: SpaceUri, + /// Batch revision. pub rev: Tid, + /// Zero-based operation index within the batch. pub idx: u32, + /// Operation kind. pub action: OplogAction, + /// Canonical record URI. pub uri: SpaceUri, + /// Record collection NSID. pub collection: NsidOwned, + /// Record key. pub rkey: RkeyOwned, + /// Resulting record CID, absent for deletion. pub cid: Option, + /// Previous record CID, absent for creation. pub prev: Option, } /// Atomic result of validating and applying a write group. #[derive(Debug, Clone, PartialEq, Eq)] pub struct ApplyWritesResult { + /// Revision shared by all writes in the batch. pub revision: Tid, + /// Per-write results in input order. pub results: Vec, + /// Oplog entries in input order. pub oplog: Vec, + /// Candidate LtHash after applying the batch. pub lthash: LtHash, } @@ -457,9 +527,16 @@ pub fn apply_writes( if operations.len() > 200 { return Err(PermissionedError::InvalidWrite("maximum 200 writes".into())); } + let space_authority = space.did_authority(); + if space.is_record() { + return Err(PermissionedError::InvalidWrite( + "space URI must not name a record".into(), + )); + } let mut candidate = state.clone(); let mut results = Vec::with_capacity(operations.len()); let mut oplog = Vec::with_capacity(operations.len()); + let mut batch_author: Option = None; for (idx, operation) in operations.iter().enumerate() { let (uri, action, cid, prev, value) = match operation { WriteOperation::Create { uri, cid, value } => ( @@ -490,9 +567,24 @@ pub fn apply_writes( "write URI must name a record".into(), )); } + if uri.did_authority().as_str() != space_authority.as_str() + || uri.space_type().as_str() != space.space_type().as_str() + || uri.skey().as_str() != space.skey().as_str() + { + return Err(PermissionedError::InvalidWrite( + "write URI targets a different space".into(), + )); + } let author = uri - .author() + .did_author() .ok_or_else(|| PermissionedError::InvalidWrite("missing author DID".into()))?; + let author = parse_did("record author", author.as_str())?; + if batch_author.as_ref().is_some_and(|value| value != &author) { + return Err(PermissionedError::InvalidWrite( + "all writes must target the same author DID".into(), + )); + } + batch_author.get_or_insert_with(|| author.clone()); let key = uri.clone(); let existing = candidate.records.get(&key).cloned(); match operation { @@ -517,8 +609,8 @@ pub fn apply_writes( } WriteOperation::Create { .. } => {} } - if let Some(cid_value) = &cid { - if let Some(record_value) = &value { + match (&cid, &value) { + (Some(cid_value), Some(record_value)) => { candidate.lthash.add(&format!( "{}/{}/{}", path_collection(uri)?, @@ -535,9 +627,15 @@ pub fn apply_writes( })?, }, ); - } else { + } + (None, None) => { candidate.records.remove(&key); } + _ => { + return Err(PermissionedError::InvalidWrite( + "write CID/value shape mismatch".into(), + )); + } } let (collection, rkey) = (path_collection(uri)?, path_rkey(uri)?); oplog.push(OplogEntry { @@ -606,8 +704,11 @@ pub fn format_cursor(rev: &Tid, idx: u32) -> SmolStr { /// A page of ordered operations. #[derive(Debug, Clone, PartialEq, Eq)] pub struct OplogPage { + /// Operations in revision/index order. pub ops: Vec, + /// Cursor for the next page, if one exists. pub cursor: Option, + /// Terminal commit included on a short page. pub commit: Option, } @@ -620,6 +721,11 @@ pub fn list_repo_ops( commit: Option, ) -> Result { let limit = limit.unwrap_or(100).min(1000); + if limit == 0 { + return Err(PermissionedError::InvalidWrite( + "limit must be greater than zero".into(), + )); + } let start = if let Some(cursor) = cursor { Some(parse_cursor(cursor)?) } else if let Some(since) = since { @@ -634,9 +740,7 @@ pub fn list_repo_ops( ordered.sort_by(|left, right| left.rev.cmp(&right.rev).then(left.idx.cmp(&right.idx))); if let Some((start_rev, _)) = &start { if since.is_some() - && ordered - .first() - .is_some_and(|entry| entry.rev.as_str() > start_rev.as_str()) + && !ordered.is_empty() && !ordered.iter().any(|entry| entry.rev == *start_rev) { return Err(PermissionedError::SinceUnavailable); @@ -665,49 +769,124 @@ pub fn list_repo_ops( }) } -/// Credential class used by host exchanges. -#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] -pub enum CredentialKind { - Delegation, - Space, - ClientAttestation, -} +/// JWT `typ` for a delegation token. +pub const DELEGATION_TOKEN_TYP: &str = "atproto-space-delegation+jwt"; +/// JWT `typ` for a reusable DPoP-bound space credential. +pub const SPACE_CREDENTIAL_TYP: &str = "atproto-space-credential+jwt"; +/// JWT `typ` for an OAuth client attestation. +pub const CLIENT_ATTESTATION_TYP: &str = "atproto-client-attestation+jwt"; +/// Permitted clock skew when evaluating token timestamps. +pub const CLOCK_SKEW_SEC: i64 = 5; -/// Claims independent of a JWT library; host code supplies signing and key resolution. +/// Wire-shaped credential header and claims after JWT signature verification. +/// +/// Issuer and subject remain strings because client attestations use a client +/// ID URL for both, while delegation and space credentials use DID/space values. #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] pub struct CredentialClaims { - pub typ: CredentialKind, - pub iss: DidOwned, - pub sub: SpaceUri, - pub aud: Option, + /// The protected JWT `typ` header. + pub typ: SmolStr, + /// Token issuer: a DID except for client attestations. + pub iss: SmolStr, + /// Token subject: a space URI except for client attestations. + pub sub: SmolStr, + /// Optional JWT audience. + pub aud: Option, + /// Issued-at timestamp in Unix seconds. pub iat: i64, + /// Expiry timestamp in Unix seconds. pub exp: i64, + /// Unique token identifier. pub jti: SmolStr, + /// Optional DPoP JWK thumbprint from `cnf.jkt`. pub cnf_jkt: Option, } impl CredentialClaims { - /// Validate issuer, subject, audience, expiry, and DPoP binding semantics. - pub fn validate( + fn validate_common(&self, typ: &str, now: i64) -> Result<()> { + if self.typ != typ || self.jti.is_empty() { + return Err(PermissionedError::InvalidCredential( + "token type or jti mismatch".into(), + )); + } + if self.exp < now - CLOCK_SKEW_SEC || self.iat > now + CLOCK_SKEW_SEC { + return Err(PermissionedError::InvalidCredential( + "token time claim mismatch".into(), + )); + } + Ok(()) + } + + /// Validate a delegation token and consume its `jti` in the replay set. + pub fn validate_delegation( + &self, + now: i64, + expected_issuer: &Did<&str>, + expected_subject: &AtSpaceUri<&str>, + replay: &mut BTreeSet, + ) -> Result<()> { + self.validate_common(DELEGATION_TOKEN_TYP, now)?; + let expected_audience = format!("{}#atproto_space_host", expected_subject.did_authority()); + if self.iss != expected_issuer.as_str() + || self.sub != expected_subject.as_str() + || self.aud.as_deref() != Some(expected_audience.as_str()) + || self.cnf_jkt.is_some() + || !replay.insert(self.jti.clone()) + { + return Err(PermissionedError::InvalidCredential( + "delegation claims or replay mismatch".into(), + )); + } + Ok(()) + } + + /// Validate an authority-issued DPoP-bound space credential. + pub fn validate_space_credential( &self, now: i64, - expected_subject: &str, - expected_audience: Option<&str>, - required_jkt: Option<&str>, + expected_issuer: &Did<&str>, + expected_subject: &AtSpaceUri<&str>, + required_jkt: &str, ) -> Result<()> { - if self.sub.as_str() != expected_subject || self.exp < now || self.iat > now + 5 { + self.validate_common(SPACE_CREDENTIAL_TYP, now)?; + if self.iss != expected_issuer.as_str() + || self.sub != expected_subject.as_str() + || self.aud.is_some() + || self.cnf_jkt.as_deref() != Some(required_jkt) + { return Err(PermissionedError::InvalidCredential( - "subject or time claim mismatch".into(), + "space credential claims mismatch".into(), )); } - if self.aud.as_ref().map(AsRef::as_ref) != expected_audience { + Ok(()) + } + + /// Validate a client attestation and consume its `jti` in the replay set. + pub fn validate_client_attestation( + &self, + now: i64, + expected_client_id: &str, + expected_authority: &Did<&str>, + replay: &mut BTreeSet, + ) -> Result<()> { + self.validate_common(CLIENT_ATTESTATION_TYP, now)?; + let client_id = url::Url::parse(expected_client_id).map_err(|_| { + PermissionedError::InvalidCredential("client_id must be an absolute URL".into()) + })?; + if client_id.scheme() != "https" || client_id.host_str().is_none() { return Err(PermissionedError::InvalidCredential( - "audience mismatch".into(), + "client_id must be an HTTPS URL".into(), )); } - if self.cnf_jkt.as_deref() != required_jkt { + let expected_audience = format!("{expected_authority}#atproto_space_host"); + if self.iss != expected_client_id + || self.sub != expected_client_id + || self.aud.as_deref() != Some(expected_audience.as_str()) + || self.cnf_jkt.is_some() + || !replay.insert(self.jti.clone()) + { return Err(PermissionedError::InvalidCredential( - "DPoP thumbprint mismatch".into(), + "client attestation claims or replay mismatch".into(), )); } Ok(()) @@ -717,10 +896,15 @@ impl CredentialClaims { /// DPoP proof claims after JWT signature verification. #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] pub struct DpopProof { + /// Unique proof identifier used for replay detection. pub jti: SmolStr, + /// HTTP method bound to the proof. pub htm: SmolStr, + /// HTTP target URL bound to the proof. pub htu: SmolStr, + /// Base64url SHA-256 digest of the credential. pub ath: SmolStr, + /// Issued-at timestamp in Unix seconds. pub iat: i64, } @@ -733,8 +917,10 @@ pub fn verify_dpop( now: i64, replay: &mut BTreeSet, ) -> Result<()> { + let proof_htu = normalize_htu(&proof.htu)?; + let request_htu = normalize_htu(url)?; if proof.htm != method - || normalize_htu(&proof.htu) != normalize_htu(url) + || proof_htu != request_htu || proof.iat < now - 65 || proof.iat > now + 5 { @@ -755,9 +941,24 @@ pub fn verify_dpop( Ok(()) } -/// Remove query and fragment from a DPoP URL. -pub fn normalize_htu(url: &str) -> String { - url.split(['?', '#']).next().unwrap_or(url).to_owned() +/// Normalize a DPoP target URL to its WHATWG origin and pathname. +/// +/// Parsing canonicalizes the hostname and elides default ports, matching +/// `new URL(url).origin + pathname` in the reference implementation. +pub fn normalize_htu(url: &str) -> Result { + let parsed = url::Url::parse(url).map_err(|_| { + PermissionedError::InvalidCredential("DPoP htu must be an absolute URL".into()) + })?; + if !matches!(parsed.scheme(), "http" | "https") || parsed.host_str().is_none() { + return Err(PermissionedError::InvalidCredential( + "DPoP htu must use HTTP(S) with an authority".into(), + )); + } + Ok(format!( + "{}{}", + parsed.origin().ascii_serialization(), + parsed.path() + )) } fn base64url(bytes: &[u8]) -> String { const TABLE: &[u8] = b"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"; @@ -780,50 +981,113 @@ fn base64url(bytes: &[u8]) -> String { out } +/// Authority selector used by a permissioned-space OAuth resource. +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(rename_all = "snake_case")] +pub enum AuthoritySelector { + /// Resolve the authority from the requesting user. + Self_, + /// Match any authority. + Any, + /// Match one concrete DID. + Did(DidOwned), +} + +/// Collection selector used by a permissioned-space OAuth resource. +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(rename_all = "snake_case")] +pub enum CollectionSelector { + /// Match any collection. + Any, + /// Match one concrete NSID. + Nsid(NsidOwned), +} + +/// Record action granted by a permissioned-space OAuth resource. +#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] +#[serde(rename_all = "snake_case")] +pub enum PermissionAction { + /// Read only records authored by the requesting user. + ReadSelf, + /// Read all records covered by the resource. + Read, + /// Create records. + Create, + /// Update records. + Update, + /// Delete records. + Delete, +} + +/// Management action granted by a permissioned-space OAuth resource. +#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] +#[serde(rename_all = "snake_case")] +pub enum ManageAction { + /// Create a space. + Create, + /// Update a space. + Update, + /// Delete a space. + Delete, +} + /// A permissioned-space OAuth resource. #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] pub struct SpacePermission { + /// Concrete space type. Wildcard space types are not valid in a set. pub space_type: NsidOwned, - pub authority: Option, + /// Optional authority selector. + pub authority: Option, + /// Optional stable space key. pub skey: Option, - pub collection: Vec, - pub action: Vec, - pub manage: Vec, + /// Collections covered by this resource; empty means any collection. + pub collection: Vec, + /// Record actions covered by this resource; empty means any action. + pub action: Vec, + /// Management actions covered by this resource. + pub manage: Vec, } impl SpacePermission { /// Validate a permission-set entry; wildcard space types are forbidden in sets. pub fn validate(&self, namespace: &str) -> Result<()> { - if !self.space_type.as_str().starts_with(namespace) { + let space_type = self.space_type.as_str(); + if space_type != namespace + && !space_type + .strip_prefix(namespace) + .is_some_and(|suffix| suffix.starts_with('.')) + { return Err(PermissionedError::InvalidCredential( "permission outside namespace".into(), )); } - for collection in &self.collection { - if collection != "*" { - parse_nsid("collection", collection)?; - } - } - if let Some(authority) = &self.authority { - if authority != "self" && authority != "*" { - parse_did("authority", authority)?; - } - } Ok(()) } - /// Match independently against a requested space and action. + + /// Match independently against a requested space, collection, and action. pub fn matches(&self, space_type: &str, collection: &str, action: &str) -> bool { - (self.space_type.as_str() == space_type || self.space_type.as_str() == "*") + self.space_type.as_str() == space_type && (self.collection.is_empty() - || self - .collection - .iter() - .any(|value| value == "*" || value == collection)) + || self.collection.iter().any(|value| match value { + CollectionSelector::Any => true, + CollectionSelector::Nsid(nsid) => nsid.as_str() == collection, + })) && (self.action.is_empty() || self .action .iter() - .any(|value| value == action || (action == "read_self" && value == "read"))) + .any(|value| permission_action_matches(*value, action))) + } +} + +fn permission_action_matches(action: PermissionAction, requested: &str) -> bool { + match (action, requested) { + (PermissionAction::Read, "read" | "read_self") + | (PermissionAction::ReadSelf, "read_self") + | (PermissionAction::Create, "create") + | (PermissionAction::Update, "update") + | (PermissionAction::Delete, "delete") => true, + _ => false, } } @@ -836,22 +1100,23 @@ pub struct PermissionedCar { pub blocks: Vec<(CarCid, Bytes)>, } -/// Immutable result returned after CAR verification. +/// Immutable result returned after full CAR verification. #[derive(Debug, Clone, PartialEq, Eq)] pub struct ValidatedRepoSnapshot { - /// Verified roots. - pub roots: [CarCid; 2], - /// Verified blocks in input order. - pub blocks: Vec<(CarCid, Bytes)>, + roots: [CarCid; 2], + commit: SignedCommit, + index: Vec<(SmolStr, CarCid)>, + records: Vec<(SmolStr, CarCid, Bytes)>, } impl PermissionedCar { - /// Construct and validate a two-root CAR representation. + /// Construct a two-root CAR representation after structural CID validation. pub fn new(roots: [CarCid; 2], blocks: Vec<(CarCid, Bytes)>) -> Result { let car = Self { roots, blocks }; - car.validate()?; + car.validate_structure()?; Ok(car) } + /// Return a roots-only CAR representation. pub fn exclude_values(&self) -> Self { Self { @@ -859,8 +1124,8 @@ impl PermissionedCar { blocks: self.blocks.iter().take(2).cloned().collect(), } } - /// Verify root count/order, block CIDs, and duplicate blocks. - pub fn validate(&self) -> Result<()> { + + fn validate_structure(&self) -> Result<()> { if self.blocks.len() < 2 || self.blocks[0].0 != self.roots[0] || self.blocks[1].0 != self.roots[1] @@ -882,25 +1147,148 @@ impl PermissionedCar { } Ok(()) } - /// Consume the CAR into an immutable validated snapshot. - pub fn snapshot(self) -> Result { - self.validate()?; + + /// Fully authenticate the commit, DRISL index, and optional record blocks. + /// + /// The expected space and author are supplied out of band, as in the + /// reference consumer. A roots-only CAR is accepted when `expect_values` is + /// false; otherwise every index entry must have exactly one matching block. + pub fn validate( + &self, + space: &SpaceUri, + author: &DidOwned, + key: &VerifyingKey, + expect_values: bool, + ) -> Result { + self.validate_structure()?; + + let commit = SignedCommit::from_cbor(&self.blocks[0].1) + .map_err(|error| PermissionedError::InvalidCar(error.to_string()))?; + let commit_bytes = commit + .to_cbor() + .map_err(|error| PermissionedError::InvalidCar(error.to_string()))?; + if commit_bytes.as_slice() != self.blocks[0].1.as_ref() { + return Err(PermissionedError::InvalidCar( + "commit block is not canonical DAG-CBOR".into(), + )); + } + let context = CommitContext { + space: space.clone(), + author: author.clone(), + rev: commit.rev.clone(), + }; + commit + .verify(&context, key) + .map_err(|error| PermissionedError::InvalidCar(error.to_string()))?; + + let decoded: BTreeMap> = + serde_ipld_dagcbor::from_slice(&self.blocks[1].1) + .map_err(|error| PermissionedError::InvalidCar(error.to_string()))?; + let canonical = serde_ipld_dagcbor::to_vec(&decoded) + .map_err(|error| PermissionedError::InvalidCar(error.to_string()))?; + if canonical.as_slice() != self.blocks[1].1.as_ref() { + return Err(PermissionedError::InvalidCar( + "index block is not canonical DAG-CBOR".into(), + )); + } + + let mut index = decoded + .into_iter() + .map(|(path, cid)| { + let (collection, rkey) = path.split_once('/').ok_or_else(|| { + PermissionedError::InvalidCar("invalid index record path".into()) + })?; + if path.matches('/').count() != 1 { + return Err(PermissionedError::InvalidCar( + "invalid index record path".into(), + )); + } + parse_nsid("index collection", collection) + .map_err(|error| PermissionedError::InvalidCar(error.to_string()))?; + parse_rkey("index rkey", rkey) + .map_err(|error| PermissionedError::InvalidCar(error.to_string()))?; + let cid = cid + .to_ipld() + .map_err(|error| PermissionedError::InvalidCar(error.to_string()))?; + Ok((path, cid)) + }) + .collect::>>()?; + index.sort_by(|left, right| { + left.0 + .len() + .cmp(&right.0.len()) + .then_with(|| left.0.as_bytes().cmp(right.0.as_bytes())) + }); + + let mut lthash = LtHash::default(); + for (path, cid) in &index { + lthash.add(&format!("{path}/{cid}")); + } + if lthash.digest() != commit.hash { + return Err(PermissionedError::InvalidCar( + "index does not match commit hash".into(), + )); + } + + let record_blocks = &self.blocks[2..]; + if expect_values && record_blocks.len() != index.len() { + return Err(PermissionedError::InvalidCar( + "record block count does not match index".into(), + )); + } + if !expect_values && !record_blocks.is_empty() && record_blocks.len() != index.len() { + return Err(PermissionedError::InvalidCar( + "partial record block stream".into(), + )); + } + + let mut records = Vec::with_capacity(record_blocks.len()); + for ((path, expected_cid), (actual_cid, bytes)) in index.iter().zip(record_blocks) { + if actual_cid != expected_cid { + return Err(PermissionedError::InvalidCar( + "record blocks do not follow index order".into(), + )); + } + let value: Data = serde_ipld_dagcbor::from_slice(bytes) + .map_err(|error| PermissionedError::InvalidCar(error.to_string()))?; + let canonical = serde_ipld_dagcbor::to_vec(&value) + .map_err(|error| PermissionedError::InvalidCar(error.to_string()))?; + if canonical.as_slice() != bytes.as_ref() { + return Err(PermissionedError::InvalidCar( + "record block is not canonical DAG-CBOR".into(), + )); + } + records.push((path.clone(), *actual_cid, bytes.clone())); + } + Ok(ValidatedRepoSnapshot { roots: self.roots, - blocks: self.blocks, + commit, + index, + records, }) } } impl ValidatedRepoSnapshot { - /// Return the ordered roots. + /// Return the ordered commit and index roots. pub fn roots(&self) -> &[CarCid; 2] { &self.roots } - /// Return verified blocks without exposing mutable state. - pub fn blocks(&self) -> &[(CarCid, Bytes)] { - &self.blocks + /// Return the authenticated signed commit. + pub fn commit(&self) -> &SignedCommit { + &self.commit + } + + /// Return the canonical ordered DRISL index. + pub fn index(&self) -> &[(SmolStr, CarCid)] { + &self.index + } + + /// Return verified record blocks in index order. + pub fn records(&self) -> &[(SmolStr, CarCid, Bytes)] { + &self.records } } @@ -953,16 +1341,52 @@ mod tests { assert_eq!(SignedCommit::from_cbor(&bytes).unwrap(), commit); } #[test] - fn signed_commit_mutation_fails() { + fn signed_commit_all_mutation_paths_fail() { let context = CommitContext { space: SpaceUri::new_owned("at://did:plc:space/space/com.example.type/demo").unwrap(), author: DidOwned::new_owned("did:plc:author").unwrap(), rev: Tid::new("3jzfcijpj2m2a").unwrap(), }; let key = SigningKey::from_bytes(&[7; 32]); - let mut commit = SignedCommit::sign_with_ikm([9; 32], &context, &key, [0x20; 32]).unwrap(); - commit.hash[0] ^= 1; - assert!(commit.verify(&context, &key.verifying_key()).is_err()); + let commit = SignedCommit::sign_with_ikm([9; 32], &context, &key, [0x20; 32]).unwrap(); + + let mut changed_context = context.clone(); + changed_context.space = + SpaceUri::new_owned("at://did:plc:other/space/com.example.type/demo").unwrap(); + assert!( + commit + .verify(&changed_context, &key.verifying_key()) + .is_err() + ); + changed_context = context.clone(); + changed_context.author = DidOwned::new_owned("did:plc:other").unwrap(); + assert!( + commit + .verify(&changed_context, &key.verifying_key()) + .is_err() + ); + changed_context = context.clone(); + changed_context.rev = Tid::new("3jzfcijpj2m2b").unwrap(); + assert!( + commit + .verify(&changed_context, &key.verifying_key()) + .is_err() + ); + + for mutate in [ + |value: &mut SignedCommit| value.hash[0] ^= 1, + |value: &mut SignedCommit| value.ikm[0] ^= 1, + |value: &mut SignedCommit| value.mac[0] ^= 1, + |value: &mut SignedCommit| value.sig[0] ^= 1, + |value: &mut SignedCommit| value.ver += 1, + ] { + let mut changed = commit.clone(); + mutate(&mut changed); + assert!(changed.verify(&context, &key.verifying_key()).is_err()); + } + let mut changed = commit.clone(); + changed.rev = Tid::new("3jzfcijpj2m2b").unwrap(); + assert!(changed.verify(&context, &key.verifying_key()).is_err()); } #[test] fn write_group_is_atomic_and_cursor_uses_slash() { @@ -982,4 +1406,208 @@ mod tests { assert_eq!(result.oplog[0].idx, 0); assert_eq!(format_cursor(&revision, 0), "3jzfcijpj2m2a/0"); } + + fn credential_claims( + typ: &'static str, + iss: &str, + sub: &str, + aud: Option<&str>, + cnf_jkt: Option<&str>, + ) -> CredentialClaims { + CredentialClaims { + typ: SmolStr::new_static(typ), + iss: SmolStr::new(iss), + sub: SmolStr::new(sub), + aud: aud.map(SmolStr::new), + iat: 100, + exp: 160, + jti: SmolStr::new_static("unique"), + cnf_jkt: cnf_jkt.map(SmolStr::new), + } + } + + #[test] + fn credentials_validate_each_kind_and_replay() { + let space = SpaceUri::new_owned("at://did:plc:space/space/com.example.type/demo").unwrap(); + let user = DidOwned::new_owned("did:plc:user").unwrap(); + let authority = DidOwned::new_owned("did:plc:space").unwrap(); + let user_ref = Did::new(user.as_str()).unwrap(); + let authority_ref = Did::new(authority.as_str()).unwrap(); + let space_ref = AtSpaceUri::new(space.as_str()).unwrap(); + let mut replay = BTreeSet::new(); + let delegation = credential_claims( + DELEGATION_TOKEN_TYP, + user.as_str(), + space.as_str(), + Some("did:plc:space#atproto_space_host"), + None, + ); + delegation + .validate_delegation(100, &user_ref, &space_ref, &mut replay) + .unwrap(); + assert!( + delegation + .validate_delegation(100, &user_ref, &space_ref, &mut replay) + .is_err() + ); + + let credential = credential_claims( + SPACE_CREDENTIAL_TYP, + authority.as_str(), + space.as_str(), + None, + Some("thumbprint"), + ); + credential + .validate_space_credential(100, &authority_ref, &space_ref, "thumbprint") + .unwrap(); + assert!( + credential + .validate_space_credential(100, &user_ref, &space_ref, "thumbprint") + .is_err() + ); + + let client_id = "https://client.example/metadata.json"; + let attestation = credential_claims( + CLIENT_ATTESTATION_TYP, + client_id, + client_id, + Some("did:plc:space#atproto_space_host"), + None, + ); + let mut replay = BTreeSet::new(); + attestation + .validate_client_attestation(100, client_id, &authority_ref, &mut replay) + .unwrap(); + assert!( + attestation + .validate_client_attestation( + 100, + "did:plc:not-a-client-url", + &authority_ref, + &mut BTreeSet::new(), + ) + .is_err() + ); + } + + #[test] + fn credentials_apply_five_second_expiry_grace() { + let space = SpaceUri::new_owned("at://did:plc:space/space/com.example.type/demo").unwrap(); + let authority = DidOwned::new_owned("did:plc:space").unwrap(); + let authority_ref = Did::new(authority.as_str()).unwrap(); + let space_ref = AtSpaceUri::new(space.as_str()).unwrap(); + let mut credential = credential_claims( + SPACE_CREDENTIAL_TYP, + authority.as_str(), + space.as_str(), + None, + Some("thumbprint"), + ); + credential.exp = 100; + assert!( + credential + .validate_space_credential(105, &authority_ref, &space_ref, "thumbprint") + .is_ok() + ); + assert!( + credential + .validate_space_credential(106, &authority_ref, &space_ref, "thumbprint") + .is_err() + ); + } + + fn verified_car_fixture() -> (PermissionedCar, SpaceUri, DidOwned, SigningKey) { + let space = SpaceUri::new_owned("at://did:plc:space/space/com.example.type/demo").unwrap(); + let author = DidOwned::new_owned("did:plc:author").unwrap(); + let key = SigningKey::from_bytes(&[7; 32]); + let record = serde_ipld_dagcbor::to_vec(&BTreeMap::from([( + SmolStr::new_static("text"), + SmolStr::new_static("hello"), + )])) + .unwrap(); + let record_cid = crate::mst::util::compute_cid(&record).unwrap(); + let path = SmolStr::new_static("com.example.record/r"); + let index = BTreeMap::from([(path.clone(), CidLink::::ipld(record_cid))]); + let index_bytes = serde_ipld_dagcbor::to_vec(&index).unwrap(); + let index_cid = crate::mst::util::compute_cid(&index_bytes).unwrap(); + let mut lthash = LtHash::default(); + lthash.add(&format!("{path}/{record_cid}")); + let context = CommitContext { + space: space.clone(), + author: author.clone(), + rev: Tid::new("3jzfcijpj2m2a").unwrap(), + }; + let commit = + SignedCommit::sign_with_ikm(lthash.digest(), &context, &key, [0x20; 32]).unwrap(); + let commit_bytes = commit.to_cbor().unwrap(); + let commit_cid = crate::mst::util::compute_cid(&commit_bytes).unwrap(); + let car = PermissionedCar::new( + [commit_cid, index_cid], + vec![ + (commit_cid, Bytes::from(commit_bytes)), + (index_cid, Bytes::from(index_bytes)), + (record_cid, Bytes::from(record)), + ], + ) + .unwrap(); + (car, space, author, key) + } + + #[test] + fn permissioned_car_full_semantic_verification() { + let (car, space, author, key) = verified_car_fixture(); + let snapshot = car + .validate(&space, &author, &key.verifying_key(), true) + .unwrap(); + assert_eq!(snapshot.index().len(), 1); + assert_eq!(snapshot.records().len(), 1); + assert_eq!(snapshot.commit().hash, { + let mut hash = LtHash::default(); + hash.add(&format!( + "{}/{}", + snapshot.index()[0].0, + snapshot.index()[0].1 + )); + hash.digest() + }); + + let roots_only = car.exclude_values(); + assert!( + roots_only + .validate(&space, &author, &key.verifying_key(), false) + .is_ok() + ); + assert!( + roots_only + .validate(&space, &author, &key.verifying_key(), true) + .is_err() + ); + } + + #[test] + fn permissioned_car_rejects_wrong_context_and_record_order() { + let (car, space, author, key) = verified_car_fixture(); + let other_author = DidOwned::new_owned("did:plc:other").unwrap(); + assert!( + car.validate(&space, &other_author, &key.verifying_key(), true) + .is_err() + ); + let wrong_key = SigningKey::from_bytes(&[8; 32]); + assert!( + car.validate(&space, &author, &wrong_key.verifying_key(), true) + .is_err() + ); + + let mut truncated = car.clone(); + truncated.blocks.pop(); + assert!( + truncated + .validate(&space, &author, &key.verifying_key(), true) + .is_err() + ); + let mut wrong_record = car; + wrong_record.blocks[2].1 = Bytes::from_static(b"bad"); + assert!(wrong_record.validate_structure().is_err()); + } } -- 2.51.2