├── .nvmrc ├── services ├── pds │ ├── .gitignore │ └── package.json ├── bsync │ └── package.json ├── ozone │ └── package.json └── bsky │ └── package.json ├── packages ├── oauth │ ├── oauth-client-browser-example │ │ ├── .gitignore │ │ ├── .postcssrc.yml │ │ ├── src │ │ │ ├── index.css │ │ │ ├── lib │ │ │ │ ├── util.ts │ │ │ │ ├── use-bsky-client.ts │ │ │ │ └── use-escape-key.ts │ │ │ ├── index.tsx │ │ │ └── queries │ │ │ │ ├── use-get-token-info-query.ts │ │ │ │ └── use-get-session-query.ts │ │ ├── tsconfig.json │ │ ├── tsconfig.tools.json │ │ ├── tsconfig.build.json │ │ └── tailwind.config.mjs │ ├── oauth-client-expo │ │ ├── .gitignore │ │ ├── src │ │ │ ├── polyfill.d.ts │ │ │ ├── polyfill.web.ts │ │ │ ├── ExpoAtprotoOAuthClientModule.types.ts │ │ │ ├── polyfill.native.ts │ │ │ ├── index.ts │ │ │ ├── expo-oauth-client.d.ts │ │ │ └── expo-oauth-client-interface.ts │ │ ├── android │ │ │ ├── .editorconfig │ │ │ └── src │ │ │ │ └── main │ │ │ │ └── AndroidManifest.xml │ │ ├── tsconfig.json │ │ ├── tsconfig.build.json │ │ └── expo-module.config.json │ ├── jwk-jose │ │ ├── src │ │ │ └── index.ts │ │ ├── tsconfig.json │ │ └── tsconfig.build.json │ ├── oauth-provider-ui │ │ ├── src │ │ │ ├── hydration-data.d.ts │ │ │ ├── hooks │ │ │ │ ├── use-bound-dispatch.ts │ │ │ │ └── use-escape-key.ts │ │ │ ├── locales │ │ │ │ └── load.ts │ │ │ └── lib │ │ │ │ └── ref.ts │ │ ├── .gitignore │ │ ├── tsconfig.json │ │ ├── tsconfig.tools.json │ │ ├── CONTRIBUTING.md │ │ ├── tsconfig.src.json │ │ └── index.html │ ├── jwk-webcrypto │ │ ├── src │ │ │ └── index.ts │ │ ├── tsconfig.json │ │ └── tsconfig.build.json │ ├── oauth-provider-frontend │ │ ├── src │ │ │ ├── hydration-data.d.ts │ │ │ ├── components │ │ │ │ ├── Divider.tsx │ │ │ │ └── forms │ │ │ │ │ ├── index.tsx │ │ │ │ │ ├── Item.tsx │ │ │ │ │ └── Fieldset.tsx │ │ │ ├── util │ │ │ │ ├── sleep.ts │ │ │ │ ├── wait.ts │ │ │ │ ├── format2FACode.ts │ │ │ │ ├── getAccountName.ts │ │ │ │ ├── sanitizeHandle.ts │ │ │ │ └── upsert.ts │ │ │ ├── locales │ │ │ │ ├── setup.ts │ │ │ │ └── activateLocale.ts │ │ │ ├── data │ │ │ │ ├── useCustomizationData.ts │ │ │ │ ├── useHasAccounts.ts │ │ │ │ ├── useHydrationData.ts │ │ │ │ └── usePasswordConfirmMutation.ts │ │ │ └── api │ │ │ │ └── index.ts │ │ ├── .gitignore │ │ ├── tsconfig.json │ │ ├── tsconfig.tools.json │ │ ├── index.html │ │ ├── tsconfig.src.json │ │ └── hydration-data.d.ts │ ├── jwk │ │ ├── tsconfig.json │ │ └── tsconfig.build.json │ ├── oauth-scopes │ │ ├── src │ │ │ ├── lib │ │ │ │ ├── lexicon.ts │ │ │ │ ├── nsid.ts │ │ │ │ └── resource-permission.ts │ │ │ └── scope-missing-error.ts │ │ ├── tsconfig.json │ │ ├── tsconfig.tests.json │ │ ├── jest.config.js │ │ └── tsconfig.build.json │ ├── oauth-client │ │ ├── tsconfig.json │ │ ├── src │ │ │ ├── errors │ │ │ │ ├── auth-method-unsatisfiable-error.ts │ │ │ │ ├── token-refresh-error.ts │ │ │ │ ├── token-invalid-error.ts │ │ │ │ └── token-revoked-error.ts │ │ │ ├── constants.ts │ │ │ └── state-store.ts │ │ └── tsconfig.build.json │ ├── oauth-provider │ │ ├── src │ │ │ ├── oauth-dpop.ts │ │ │ ├── types │ │ │ │ ├── email-otp.ts │ │ │ │ ├── color-hue.ts │ │ │ │ ├── invite-code.ts │ │ │ │ └── password.ts │ │ │ ├── access-token │ │ │ │ └── access-token-mode.ts │ │ │ ├── dpop │ │ │ │ └── dpop-proof.ts │ │ │ ├── oidc │ │ │ │ └── sub.ts │ │ │ ├── lib │ │ │ │ ├── html │ │ │ │ │ └── index.ts │ │ │ │ ├── nsid.ts │ │ │ │ ├── util │ │ │ │ │ ├── date.ts │ │ │ │ │ ├── error.ts │ │ │ │ │ ├── well-known.ts │ │ │ │ │ ├── locale.ts │ │ │ │ │ ├── ui8.ts │ │ │ │ │ └── cast.ts │ │ │ │ └── http │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── headers.ts │ │ │ │ │ └── types.ts │ │ │ ├── oauth-client.ts │ │ │ ├── client │ │ │ │ ├── client-id.ts │ │ │ │ ├── client-data.ts │ │ │ │ └── client-info.ts │ │ │ ├── lexicon │ │ │ │ └── lexicon-data.ts │ │ │ ├── router │ │ │ │ ├── error-handler.ts │ │ │ │ └── middleware-options.ts │ │ │ ├── device │ │ │ │ └── device-data.ts │ │ │ ├── errors │ │ │ │ ├── invalid-invite-code-error.ts │ │ │ │ ├── invalid-dpop-proof-error.ts │ │ │ │ ├── access-denied-error.ts │ │ │ │ ├── login-required-error.ts │ │ │ │ └── consent-required-error.ts │ │ │ ├── result │ │ │ │ └── authorization-result-redirect.ts │ │ │ ├── customization │ │ │ │ ├── links.ts │ │ │ │ └── branding.ts │ │ │ └── oauth-store.ts │ │ ├── tsconfig.json │ │ └── tsconfig.build.json │ ├── oauth-types │ │ ├── tsconfig.json │ │ ├── src │ │ │ ├── constants.ts │ │ │ ├── oauth-code-challenge-method.ts │ │ │ ├── oauth-client-id.ts │ │ │ ├── atproto-loopback-client-redirect-uris.ts │ │ │ ├── oauth-request-uri.ts │ │ │ ├── oauth-access-token.ts │ │ │ ├── oauth-refresh-token.ts │ │ │ ├── oidc-entity-type.ts │ │ │ ├── oauth-endpoint-name.ts │ │ │ ├── oauth-response-mode.ts │ │ │ ├── oauth-par-response.ts │ │ │ ├── oauth-client-credentials-grant-token-request.ts │ │ │ ├── oauth-password-grant-token-request.ts │ │ │ ├── oauth-authorization-request-uri.ts │ │ │ ├── oauth-endpoint-auth-method.ts │ │ │ ├── oauth-grant-type.ts │ │ │ ├── oauth-token-type.ts │ │ │ ├── oidc-claims-properties.ts │ │ │ └── oauth-refresh-token-grant-token-request.ts │ │ ├── README.md │ │ └── tsconfig.build.json │ ├── oauth-client-node │ │ ├── tsconfig.json │ │ ├── src │ │ │ ├── util.ts │ │ │ └── index.ts │ │ └── tsconfig.build.json │ ├── oauth-provider-api │ │ ├── tsconfig.json │ │ ├── src │ │ │ ├── index.ts │ │ │ └── contants.ts │ │ └── tsconfig.build.json │ └── oauth-client-browser │ │ ├── tsconfig.json │ │ ├── src │ │ ├── indexed-db │ │ │ ├── schema.ts │ │ │ ├── index.ts │ │ │ └── README.md │ │ ├── index.ts │ │ └── errors.ts │ │ └── tsconfig.build.json ├── pds │ ├── test.env │ ├── src │ │ ├── repo │ │ │ └── index.ts │ │ ├── config │ │ │ └── index.ts │ │ ├── read-after-write │ │ │ └── index.ts │ │ ├── sequencer │ │ │ ├── index.ts │ │ │ └── db │ │ │ │ └── migrations │ │ │ │ └── index.ts │ │ ├── db │ │ │ └── index.ts │ │ ├── actor-store │ │ │ ├── db │ │ │ │ ├── migrations │ │ │ │ │ └── index.ts │ │ │ │ └── schema │ │ │ │ │ ├── record-blob.ts │ │ │ │ │ ├── backlink.ts │ │ │ │ │ ├── repo-root.ts │ │ │ │ │ ├── repo-block.ts │ │ │ │ │ ├── account-pref.ts │ │ │ │ │ ├── blob.ts │ │ │ │ │ └── record.ts │ │ │ ├── actor-store-resources.ts │ │ │ └── preference │ │ │ │ └── util.ts │ │ ├── mailer │ │ │ ├── templates │ │ │ │ ├── update-email.d.ts │ │ │ │ ├── confirm-email.d.ts │ │ │ │ ├── delete-account.d.ts │ │ │ │ ├── plc-operation.d.ts │ │ │ │ └── reset-password.d.ts │ │ │ └── templates.ts │ │ ├── util │ │ │ ├── types.ts │ │ │ ├── debug.ts │ │ │ ├── params.ts │ │ │ └── compression.ts │ │ ├── did-cache │ │ │ └── db │ │ │ │ └── schema.ts │ │ ├── scripts │ │ │ └── util.ts │ │ ├── account-manager │ │ │ └── db │ │ │ │ ├── schema │ │ │ │ ├── repo-root.ts │ │ │ │ ├── app-password.ts │ │ │ │ ├── refresh-token.ts │ │ │ │ ├── account-device.ts │ │ │ │ ├── account.ts │ │ │ │ ├── actor.ts │ │ │ │ ├── email-token.ts │ │ │ │ ├── used-refresh-token.ts │ │ │ │ ├── lexicon.ts │ │ │ │ └── device.ts │ │ │ │ └── migrations │ │ │ │ └── 003-privileged-app-passwords.ts │ │ └── api │ │ │ ├── app │ │ │ └── bsky │ │ │ │ ├── notification │ │ │ │ └── index.ts │ │ │ │ ├── index.ts │ │ │ │ └── actor │ │ │ │ └── index.ts │ │ │ ├── com │ │ │ └── atproto │ │ │ │ ├── moderation │ │ │ │ └── index.ts │ │ │ │ └── temp │ │ │ │ └── index.ts │ │ │ └── index.ts │ ├── tsconfig.json │ ├── tsconfig.tests.json │ ├── tsconfig.build.json │ ├── tests │ │ └── seeds │ │ │ └── likes.ts │ └── jest.config.js ├── bsky │ ├── test.env │ ├── src │ │ ├── image │ │ │ ├── index.ts │ │ │ └── logger.ts │ │ ├── data-plane │ │ │ ├── index.ts │ │ │ └── server │ │ │ │ └── db │ │ │ │ ├── index.ts │ │ │ │ ├── tables │ │ │ │ ├── mute.ts │ │ │ │ ├── list-mute.ts │ │ │ │ ├── suggested-feed.ts │ │ │ │ ├── actor-sync.ts │ │ │ │ ├── subscription.ts │ │ │ │ ├── suggested-follow.ts │ │ │ │ ├── blob-takedown.ts │ │ │ │ ├── thread-mute.ts │ │ │ │ ├── tagged-suggestion.ts │ │ │ │ ├── algo.ts │ │ │ │ ├── bookmark.ts │ │ │ │ ├── duplicate-record.ts │ │ │ │ ├── label.ts │ │ │ │ ├── post-gate.ts │ │ │ │ ├── thread-gate.ts │ │ │ │ ├── actor-state.ts │ │ │ │ ├── did-cache.ts │ │ │ │ ├── feed-item.ts │ │ │ │ ├── notification-push-token.ts │ │ │ │ ├── private-data.ts │ │ │ │ ├── profile-agg.ts │ │ │ │ ├── labeler.ts │ │ │ │ ├── quote.ts │ │ │ │ ├── activity-subscription.ts │ │ │ │ ├── follow.ts │ │ │ │ ├── actor-block.ts │ │ │ │ ├── list-block.ts │ │ │ │ ├── record.ts │ │ │ │ ├── starter-pack.ts │ │ │ │ ├── list-item.ts │ │ │ │ ├── notification.ts │ │ │ │ ├── post-agg.ts │ │ │ │ ├── view-param.ts │ │ │ │ ├── like.ts │ │ │ │ ├── repost.ts │ │ │ │ ├── actor.ts │ │ │ │ ├── verification.ts │ │ │ │ ├── list.ts │ │ │ │ └── profile.ts │ │ │ │ ├── types.ts │ │ │ │ └── migrations │ │ │ │ ├── 20230620T161134972Z-post-langs.ts │ │ │ │ ├── 20230920T213858047Z-add-tags-to-post.ts │ │ │ │ ├── 20250207T174822012Z-add-label-exp.ts │ │ │ │ ├── 20250528T221913281Z-add-record-tags.ts │ │ │ │ ├── 20230808T172902639Z-repo-rev.ts │ │ │ │ ├── 20240530T170337073Z-account-deactivation.ts │ │ │ │ ├── 20240723T220700077Z-quotes-post-aggs.ts │ │ │ │ ├── 20250813T174955711Z-add-post-agg-bookmarks.ts │ │ │ │ ├── 20230627T212437895Z-optional-handle.ts │ │ │ │ ├── 20230427T194702079Z-notif-record-index.ts │ │ │ │ ├── 20230807T035309811Z-feed-item-delete-invite-for-user-idx.ts │ │ │ │ ├── 20230611T215300060Z-actor-state.ts │ │ │ │ ├── 20230830T205507322Z-suggested-feeds.ts │ │ │ │ └── 20230610T203555962Z-suggested-follows.ts │ │ ├── util │ │ │ ├── debug.ts │ │ │ └── retry.ts │ │ ├── api │ │ │ ├── external.ts │ │ │ ├── com │ │ │ │ └── atproto │ │ │ │ │ └── temp │ │ │ │ │ └── fetchLabels.ts │ │ │ └── app │ │ │ │ └── bsky │ │ │ │ └── bookmark │ │ │ │ └── util.ts │ │ └── error.ts │ ├── tsconfig.json │ ├── tsconfig.tests.json │ ├── tsconfig.build.json │ ├── buf.gen.yaml │ └── jest.config.js ├── identity │ ├── test.env │ ├── src │ │ ├── index.ts │ │ └── did │ │ │ ├── index.ts │ │ │ └── util.ts │ ├── tsconfig.json │ ├── tsconfig.tests.json │ ├── tsconfig.build.json │ └── jest.config.js ├── internal │ ├── xrpc-utils │ │ ├── src │ │ │ └── index.ts │ │ ├── tsconfig.json │ │ └── tsconfig.build.json │ ├── identity-resolver │ │ ├── src │ │ │ ├── constants.ts │ │ │ ├── identity-resolver-error.ts │ │ │ └── index.ts │ │ ├── tsconfig.json │ │ └── tsconfig.build.json │ ├── handle-resolver-node │ │ ├── src │ │ │ └── index.ts │ │ ├── tsconfig.json │ │ └── tsconfig.build.json │ ├── pipe │ │ ├── src │ │ │ ├── index.ts │ │ │ └── type.ts │ │ ├── tsconfig.json │ │ └── tsconfig.build.json │ ├── did-resolver │ │ ├── src │ │ │ ├── methods.ts │ │ │ ├── util.ts │ │ │ ├── index.ts │ │ │ ├── did-method.ts │ │ │ └── did-resolver.ts │ │ ├── tsconfig.json │ │ └── tsconfig.build.json │ ├── fetch │ │ ├── tsconfig.json │ │ ├── tsconfig.build.json │ │ └── src │ │ │ ├── index.ts │ │ │ └── fetch-error.ts │ ├── fetch-node │ │ ├── tsconfig.json │ │ ├── src │ │ │ └── index.ts │ │ └── tsconfig.build.json │ ├── handle-resolver │ │ ├── tsconfig.json │ │ ├── src │ │ │ ├── handle-resolver-error.ts │ │ │ └── index.ts │ │ └── tsconfig.build.json │ ├── simple-store │ │ ├── tsconfig.json │ │ ├── src │ │ │ ├── index.ts │ │ │ └── util.ts │ │ └── tsconfig.build.json │ ├── simple-store-memory │ │ ├── tsconfig.json │ │ └── tsconfig.build.json │ ├── simple-store-redis │ │ ├── tsconfig.json │ │ ├── tsconfig.build.json │ │ └── CHANGELOG.md │ └── rollup-plugin-bundle-manifest │ │ ├── tsconfig.json │ │ └── tsconfig.build.json ├── ozone │ ├── test.env │ ├── src │ │ ├── sequencer │ │ │ └── index.ts │ │ ├── config │ │ │ ├── index.ts │ │ │ └── secrets.ts │ │ ├── setting │ │ │ ├── types.ts │ │ │ └── constants.ts │ │ ├── db │ │ │ ├── schema │ │ │ │ ├── signing_key.ts │ │ │ │ ├── job_cursor.ts │ │ │ │ ├── firehose_cursor.ts │ │ │ │ └── account_strike.ts │ │ │ └── migrations │ │ │ │ ├── 20240903T205730722Z-add-template-lang.ts │ │ │ │ ├── 20240814T003647759Z-event-created-at-index.ts │ │ │ │ ├── 20240904T205730722Z-add-subject-did-index.ts │ │ │ │ ├── 20240201T051104136Z-mod-event-blobs.ts │ │ │ │ ├── 20250715T000000000Z-add-mod-event-external-id.ts │ │ │ │ └── 20240408T192432676Z-mute-reporting.ts │ │ ├── api │ │ │ └── chat │ │ │ │ └── index.ts │ │ ├── communication-service │ │ │ └── util.ts │ │ ├── scheduled-action │ │ │ └── types.ts │ │ ├── image-invalidator.ts │ │ ├── error.ts │ │ └── tag-service │ │ │ └── util.ts │ ├── tsconfig.json │ ├── tsconfig.tests.json │ ├── tsconfig.build.json │ ├── jest.config.js │ └── tests │ │ └── __snapshots__ │ │ └── report-reason.test.ts.snap ├── api │ ├── scripts │ │ └── generate-code.mjs │ ├── src │ │ ├── const.ts │ │ ├── session-manager.ts │ │ └── bsky-agent.ts │ ├── tsconfig.json │ ├── tsconfig.build.json │ ├── tsconfig.tests.json │ └── jest.config.js ├── aws │ ├── README.md │ ├── tsconfig.json │ ├── src │ │ ├── index.ts │ │ ├── types.ts │ │ └── util.ts │ └── tsconfig.build.json ├── repo │ ├── src │ │ ├── sync │ │ │ └── index.ts │ │ ├── mst │ │ │ └── index.ts │ │ ├── storage │ │ │ └── index.ts │ │ ├── logger.ts │ │ └── index.ts │ ├── tsconfig.json │ ├── tsconfig.tests.json │ ├── tsconfig.build.json │ └── jest.config.js ├── crypto │ ├── tests │ │ └── signature-fixtures.json │ ├── tsconfig.json │ ├── tsconfig.tests.json │ ├── src │ │ ├── plugins.ts │ │ ├── const.ts │ │ ├── index.ts │ │ ├── p256 │ │ │ └── plugin.ts │ │ └── secp256k1 │ │ │ └── plugin.ts │ ├── tsconfig.build.json │ └── jest.config.js ├── did │ ├── src │ │ ├── methods.ts │ │ └── index.ts │ ├── tsconfig.json │ ├── tsconfig.build.json │ └── jest.config.js ├── lexicon-resolver │ ├── src │ │ ├── index.ts │ │ └── util.ts │ ├── tsconfig.json │ ├── tsconfig.tests.json │ ├── tsconfig.build.json │ └── jest.config.js ├── dev-env │ ├── assets │ │ ├── at.png │ │ ├── hd-key.jpg │ │ ├── key-alt.jpg │ │ ├── key-landscape-large.jpg │ │ ├── key-landscape-small.jpg │ │ ├── key-portrait-large.jpg │ │ └── key-portrait-small.jpg │ ├── tsconfig.json │ ├── src │ │ ├── const.ts │ │ ├── env.ts │ │ └── index.ts │ └── tsconfig.build.json ├── sync │ ├── src │ │ ├── index.ts │ │ ├── runner │ │ │ ├── index.ts │ │ │ └── types.ts │ │ └── util.ts │ ├── tsconfig.json │ ├── tsconfig.build.json │ └── jest.config.js ├── syntax │ ├── tests │ │ └── interop-files │ │ │ ├── aturi_syntax_valid.txt │ │ │ ├── did_syntax_invalid.txt │ │ │ ├── did_syntax_valid.txt │ │ │ ├── nsid_syntax_valid.txt │ │ │ ├── tid_syntax_invalid.txt │ │ │ ├── tid_syntax_valid.txt │ │ │ ├── aturi_syntax_invalid.txt │ │ │ ├── handle_syntax_valid.txt │ │ │ ├── nsid_syntax_invalid.txt │ │ │ ├── datetime_parse_invalid.txt │ │ │ ├── datetime_syntax_invalid.txt │ │ │ ├── datetime_syntax_valid.txt │ │ │ ├── handle_syntax_invalid.txt │ │ │ ├── recordkey_syntax_valid.txt │ │ │ └── recordkey_syntax_invalid.txt │ ├── tsconfig.json │ ├── tsconfig.tests.json │ ├── tsconfig.build.json │ ├── src │ │ └── index.ts │ └── jest.config.js ├── xrpc │ ├── tsconfig.json │ ├── tsconfig.build.json │ └── src │ │ └── index.ts ├── lex-cli │ ├── tsconfig.json │ ├── tsconfig.build.json │ └── src │ │ └── types.ts ├── lexicon │ ├── src │ │ └── index.ts │ ├── tsconfig.json │ ├── tsconfig.tests.json │ ├── tsconfig.build.json │ └── jest.config.js ├── bsync │ ├── tsconfig.json │ ├── tsconfig.tests.json │ ├── tsconfig.build.json │ ├── buf.gen.yaml │ ├── jest.config.js │ └── src │ │ └── db │ │ ├── migrations │ │ └── provider.ts │ │ ├── schema │ │ ├── notif_item.ts │ │ ├── mute_item.ts │ │ ├── notif_op.ts │ │ └── index.ts │ │ └── types.ts ├── common │ ├── tsconfig.json │ ├── tsconfig.tests.json │ ├── tsconfig.build.json │ ├── jest.config.js │ └── src │ │ ├── index.ts │ │ └── buffers.ts ├── common-web │ ├── tsconfig.json │ ├── tsconfig.tests.json │ ├── tsconfig.build.json │ ├── jest.config.js │ └── src │ │ └── index.ts ├── xrpc-server │ ├── tsconfig.json │ ├── tsconfig.tests.json │ ├── tsconfig.build.json │ ├── src │ │ ├── stream │ │ │ ├── index.ts │ │ │ └── logger.ts │ │ ├── logger.ts │ │ └── index.ts │ └── jest.config.js └── dev-infra │ ├── with-test-db.sh │ └── with-test-redis-and-db.sh ├── .dockerignore ├── .npmrc ├── jest.setup.ts ├── pnpm-workspace.yaml ├── jest.config.js ├── interop-test-files ├── syntax │ ├── tid_syntax_valid.txt │ ├── datetime_parse_invalid.txt │ ├── atidentifier_syntax_valid.txt │ ├── tid_syntax_invalid.txt │ └── atidentifier_syntax_invalid.txt ├── crypto │ └── w3c_didkey_P256.json └── README.md ├── tsconfig ├── node.json ├── browser.json ├── tests.json ├── nodenext.json ├── bundler.json └── expo.json ├── .gitignore ├── .vscode └── extensions.json ├── lexicons ├── com │ └── atproto │ │ ├── sync │ │ └── defs.json │ │ ├── server │ │ ├── deleteSession.json │ │ ├── requestAccountDelete.json │ │ ├── requestEmailConfirmation.json │ │ ├── activateAccount.json │ │ └── revokeAppPassword.json │ │ ├── identity │ │ └── requestPlcOperationSignature.json │ │ └── repo │ │ ├── defs.json │ │ ├── importRepo.json │ │ └── strongRef.json ├── chat │ └── bsky │ │ └── actor │ │ ├── exportAccountData.json │ │ └── deleteAccount.json ├── tools │ └── ozone │ │ └── signature │ │ └── defs.json └── app │ └── bsky │ └── embed │ └── defs.json ├── .changeset ├── config.json └── README.md ├── .eslintignore ├── .prettierrc ├── .gitattributes └── LICENSE.txt /.nvmrc: -------------------------------------------------------------------------------- 1 | 22 2 | -------------------------------------------------------------------------------- /services/pds/.gitignore: -------------------------------------------------------------------------------- 1 | data/* 2 | blobs/* 3 | -------------------------------------------------------------------------------- /packages/oauth/oauth-client-browser-example/.gitignore: -------------------------------------------------------------------------------- 1 | dist 2 | -------------------------------------------------------------------------------- /packages/oauth/oauth-client-expo/.gitignore: -------------------------------------------------------------------------------- 1 | /android/build 2 | -------------------------------------------------------------------------------- /packages/oauth/oauth-client-expo/src/polyfill.d.ts: -------------------------------------------------------------------------------- 1 | export {} 2 | -------------------------------------------------------------------------------- /packages/pds/test.env: -------------------------------------------------------------------------------- 1 | LOG_ENABLED=true 2 | LOG_DESTINATION=test.log -------------------------------------------------------------------------------- /.dockerignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | **/dist 3 | .DS_Store 4 | Dockerfile 5 | -------------------------------------------------------------------------------- /packages/bsky/test.env: -------------------------------------------------------------------------------- 1 | LOG_ENABLED=true 2 | LOG_DESTINATION=test.log 3 | -------------------------------------------------------------------------------- /packages/identity/test.env: -------------------------------------------------------------------------------- 1 | LOG_ENABLED=true 2 | LOG_DESTINATION=test.log -------------------------------------------------------------------------------- /packages/internal/xrpc-utils/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './accept.js' 2 | -------------------------------------------------------------------------------- /packages/oauth/jwk-jose/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './jose-key.js' 2 | -------------------------------------------------------------------------------- /packages/ozone/test.env: -------------------------------------------------------------------------------- 1 | LOG_ENABLED=true 2 | LOG_DESTINATION=test.log 3 | -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | enable-pre-post-scripts = true 2 | include-workspace-root = true 3 | -------------------------------------------------------------------------------- /packages/oauth/oauth-provider-ui/src/hydration-data.d.ts: -------------------------------------------------------------------------------- 1 | ../hydration-data.d.ts -------------------------------------------------------------------------------- /packages/oauth/jwk-webcrypto/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './webcrypto-key.js' 2 | -------------------------------------------------------------------------------- /packages/api/scripts/generate-code.mjs: -------------------------------------------------------------------------------- 1 | import './code/labels.mjs' 2 | 3 | export {} 4 | -------------------------------------------------------------------------------- /packages/aws/README.md: -------------------------------------------------------------------------------- 1 | # AWS KMS 2 | 3 | A Keypair-compatible wrapper for AWS KMS. 4 | -------------------------------------------------------------------------------- /packages/oauth/oauth-provider-frontend/src/hydration-data.d.ts: -------------------------------------------------------------------------------- 1 | ../hydration-data.d.ts -------------------------------------------------------------------------------- /packages/oauth/oauth-provider-ui/.gitignore: -------------------------------------------------------------------------------- 1 | src/locales/*/*.ts 2 | .swc 3 | dist 4 | -------------------------------------------------------------------------------- /packages/pds/src/repo/index.ts: -------------------------------------------------------------------------------- 1 | export * from './prepare' 2 | export * from './types' 3 | -------------------------------------------------------------------------------- /jest.setup.ts: -------------------------------------------------------------------------------- 1 | import dotenv from 'dotenv' 2 | 3 | dotenv.config({ path: './test.env' }) 4 | -------------------------------------------------------------------------------- /packages/oauth/oauth-client-expo/android/.editorconfig: -------------------------------------------------------------------------------- 1 | [*.{kt,kts}] 2 | indent_size=2 3 | -------------------------------------------------------------------------------- /packages/oauth/oauth-provider-frontend/.gitignore: -------------------------------------------------------------------------------- 1 | src/locales/*/*.ts 2 | .swc 3 | dist 4 | -------------------------------------------------------------------------------- /packages/repo/src/sync/index.ts: -------------------------------------------------------------------------------- 1 | export * from './consumer' 2 | export * from './provider' 3 | -------------------------------------------------------------------------------- /packages/api/src/const.ts: -------------------------------------------------------------------------------- 1 | export const BSKY_LABELER_DID = 'did:plc:ar7c4by46qjdydhdevvrndac' 2 | -------------------------------------------------------------------------------- /packages/ozone/src/sequencer/index.ts: -------------------------------------------------------------------------------- 1 | export * from './sequencer' 2 | export * from './outbox' 3 | -------------------------------------------------------------------------------- /packages/crypto/tests/signature-fixtures.json: -------------------------------------------------------------------------------- 1 | ../../../interop-test-files/crypto/signature-fixtures.json -------------------------------------------------------------------------------- /packages/did/src/methods.ts: -------------------------------------------------------------------------------- 1 | export * from './methods/plc.js' 2 | export * from './methods/web.js' 3 | -------------------------------------------------------------------------------- /packages/internal/identity-resolver/src/constants.ts: -------------------------------------------------------------------------------- 1 | export const HANDLE_INVALID = 'handle.invalid' 2 | -------------------------------------------------------------------------------- /packages/lexicon-resolver/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './record.js' 2 | export * from './lexicon.js' 3 | -------------------------------------------------------------------------------- /packages/oauth/oauth-client-expo/android/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /packages/internal/handle-resolver-node/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './atproto-handle-resolver-node.js' 2 | -------------------------------------------------------------------------------- /packages/bsky/src/image/index.ts: -------------------------------------------------------------------------------- 1 | export * from './sharp' 2 | export type { ImageInfo, Options } from './util' 3 | -------------------------------------------------------------------------------- /packages/oauth/oauth-client-expo/src/polyfill.web.ts: -------------------------------------------------------------------------------- 1 | import 'core-js/proposals/explicit-resource-management' 2 | -------------------------------------------------------------------------------- /packages/aws/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "include": [], 3 | "references": [{ "path": "./tsconfig.build.json" }] 4 | } 5 | -------------------------------------------------------------------------------- /packages/dev-env/assets/at.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mistydemeo/atproto/main/packages/dev-env/assets/at.png -------------------------------------------------------------------------------- /packages/did/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "include": [], 3 | "references": [{ "path": "./tsconfig.build.json" }] 4 | } 5 | -------------------------------------------------------------------------------- /packages/internal/pipe/src/index.ts: -------------------------------------------------------------------------------- 1 | export { pipe, pipeTwo } from './pipe.js' 2 | export type * from './type.js' 3 | -------------------------------------------------------------------------------- /packages/oauth/oauth-client-browser-example/.postcssrc.yml: -------------------------------------------------------------------------------- 1 | plugins: 2 | tailwindcss: {} 3 | autoprefixer: {} 4 | -------------------------------------------------------------------------------- /packages/pds/src/config/index.ts: -------------------------------------------------------------------------------- 1 | export * from './config' 2 | export * from './env' 3 | export * from './secrets' 4 | -------------------------------------------------------------------------------- /packages/sync/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './runner' 2 | export * from './firehose' 3 | export * from './events' 4 | -------------------------------------------------------------------------------- /packages/sync/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "include": [], 3 | "references": [{ "path": "./tsconfig.build.json" }] 4 | } 5 | -------------------------------------------------------------------------------- /packages/syntax/tests/interop-files/aturi_syntax_valid.txt: -------------------------------------------------------------------------------- 1 | ../../../../interop-test-files/syntax/aturi_syntax_valid.txt -------------------------------------------------------------------------------- /packages/syntax/tests/interop-files/did_syntax_invalid.txt: -------------------------------------------------------------------------------- 1 | ../../../../interop-test-files/syntax/did_syntax_invalid.txt -------------------------------------------------------------------------------- /packages/syntax/tests/interop-files/did_syntax_valid.txt: -------------------------------------------------------------------------------- 1 | ../../../../interop-test-files/syntax/did_syntax_valid.txt -------------------------------------------------------------------------------- /packages/syntax/tests/interop-files/nsid_syntax_valid.txt: -------------------------------------------------------------------------------- 1 | ../../../../interop-test-files/syntax/nsid_syntax_valid.txt -------------------------------------------------------------------------------- /packages/syntax/tests/interop-files/tid_syntax_invalid.txt: -------------------------------------------------------------------------------- 1 | ../../../../interop-test-files/syntax/tid_syntax_invalid.txt -------------------------------------------------------------------------------- /packages/syntax/tests/interop-files/tid_syntax_valid.txt: -------------------------------------------------------------------------------- 1 | ../../../../interop-test-files/syntax/tid_syntax_valid.txt -------------------------------------------------------------------------------- /packages/xrpc/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "include": [], 3 | "references": [{ "path": "./tsconfig.build.json" }] 4 | } 5 | -------------------------------------------------------------------------------- /packages/bsky/src/data-plane/index.ts: -------------------------------------------------------------------------------- 1 | export * from './server' 2 | export * from './client' 3 | export * from './bsync' 4 | -------------------------------------------------------------------------------- /packages/bsky/src/data-plane/server/db/index.ts: -------------------------------------------------------------------------------- 1 | export * from './db' 2 | export type { DatabaseSchema } from './db' 3 | -------------------------------------------------------------------------------- /packages/dev-env/assets/hd-key.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mistydemeo/atproto/main/packages/dev-env/assets/hd-key.jpg -------------------------------------------------------------------------------- /packages/dev-env/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "include": [], 3 | "references": [{ "path": "./tsconfig.build.json" }] 4 | } 5 | -------------------------------------------------------------------------------- /packages/internal/did-resolver/src/methods.ts: -------------------------------------------------------------------------------- 1 | export * from './methods/plc.js' 2 | export * from './methods/web.js' 3 | -------------------------------------------------------------------------------- /packages/internal/did-resolver/src/util.ts: -------------------------------------------------------------------------------- 1 | export type Simplify = { [K in keyof T]: T[K] } & NonNullable 2 | -------------------------------------------------------------------------------- /packages/lex-cli/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "include": [], 3 | "references": [{ "path": "./tsconfig.build.json" }] 4 | } 5 | -------------------------------------------------------------------------------- /packages/oauth/jwk/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "include": [], 3 | "references": [{ "path": "./tsconfig.build.json" }] 4 | } 5 | -------------------------------------------------------------------------------- /packages/oauth/oauth-scopes/src/lib/lexicon.ts: -------------------------------------------------------------------------------- 1 | export type { LexPermission, LexPermissionSet } from '@atproto/lexicon' 2 | -------------------------------------------------------------------------------- /packages/ozone/src/config/index.ts: -------------------------------------------------------------------------------- 1 | export * from './config' 2 | export * from './env' 3 | export * from './secrets' 4 | -------------------------------------------------------------------------------- /packages/syntax/tests/interop-files/aturi_syntax_invalid.txt: -------------------------------------------------------------------------------- 1 | ../../../../interop-test-files/syntax/aturi_syntax_invalid.txt -------------------------------------------------------------------------------- /packages/syntax/tests/interop-files/handle_syntax_valid.txt: -------------------------------------------------------------------------------- 1 | ../../../../interop-test-files/syntax/handle_syntax_valid.txt -------------------------------------------------------------------------------- /packages/syntax/tests/interop-files/nsid_syntax_invalid.txt: -------------------------------------------------------------------------------- 1 | ../../../../interop-test-files/syntax/nsid_syntax_invalid.txt -------------------------------------------------------------------------------- /packages/dev-env/assets/key-alt.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mistydemeo/atproto/main/packages/dev-env/assets/key-alt.jpg -------------------------------------------------------------------------------- /packages/internal/fetch/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "include": [], 3 | "references": [{ "path": "./tsconfig.build.json" }] 4 | } 5 | -------------------------------------------------------------------------------- /packages/internal/pipe/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "include": [], 3 | "references": [{ "path": "./tsconfig.build.json" }] 4 | } 5 | -------------------------------------------------------------------------------- /packages/oauth/jwk-jose/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "include": [], 3 | "references": [{ "path": "./tsconfig.build.json" }] 4 | } 5 | -------------------------------------------------------------------------------- /packages/oauth/oauth-client-browser-example/src/index.css: -------------------------------------------------------------------------------- 1 | @tailwind base; 2 | @tailwind components; 3 | @tailwind utilities; 4 | -------------------------------------------------------------------------------- /packages/pds/src/read-after-write/index.ts: -------------------------------------------------------------------------------- 1 | export * from './types' 2 | export * from './util' 3 | export * from './viewer' 4 | -------------------------------------------------------------------------------- /packages/pds/src/sequencer/index.ts: -------------------------------------------------------------------------------- 1 | export * from './sequencer' 2 | export * from './outbox' 3 | export * from './events' 4 | -------------------------------------------------------------------------------- /packages/syntax/tests/interop-files/datetime_parse_invalid.txt: -------------------------------------------------------------------------------- 1 | ../../../../interop-test-files/syntax/datetime_parse_invalid.txt -------------------------------------------------------------------------------- /packages/syntax/tests/interop-files/datetime_syntax_invalid.txt: -------------------------------------------------------------------------------- 1 | ../../../../interop-test-files/syntax/datetime_syntax_invalid.txt -------------------------------------------------------------------------------- /packages/syntax/tests/interop-files/datetime_syntax_valid.txt: -------------------------------------------------------------------------------- 1 | ../../../../interop-test-files/syntax/datetime_syntax_valid.txt -------------------------------------------------------------------------------- /packages/syntax/tests/interop-files/handle_syntax_invalid.txt: -------------------------------------------------------------------------------- 1 | ../../../../interop-test-files/syntax/handle_syntax_invalid.txt -------------------------------------------------------------------------------- /packages/syntax/tests/interop-files/recordkey_syntax_valid.txt: -------------------------------------------------------------------------------- 1 | ../../../../interop-test-files/syntax/recordkey_syntax_valid.txt -------------------------------------------------------------------------------- /packages/internal/fetch-node/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "include": [], 3 | "references": [{ "path": "./tsconfig.build.json" }] 4 | } 5 | -------------------------------------------------------------------------------- /packages/internal/xrpc-utils/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "include": [], 3 | "references": [{ "path": "./tsconfig.build.json" }] 4 | } 5 | -------------------------------------------------------------------------------- /packages/oauth/jwk-webcrypto/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "include": [], 3 | "references": [{ "path": "./tsconfig.build.json" }] 4 | } 5 | -------------------------------------------------------------------------------- /packages/oauth/oauth-client/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "include": [], 3 | "references": [{ "path": "./tsconfig.build.json" }] 4 | } 5 | -------------------------------------------------------------------------------- /packages/oauth/oauth-provider/src/oauth-dpop.ts: -------------------------------------------------------------------------------- 1 | export * from './dpop/dpop-nonce.js' 2 | export * from './dpop/dpop-manager.js' 3 | -------------------------------------------------------------------------------- /packages/oauth/oauth-types/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "include": [], 3 | "references": [{ "path": "./tsconfig.build.json" }] 4 | } 5 | -------------------------------------------------------------------------------- /packages/syntax/tests/interop-files/recordkey_syntax_invalid.txt: -------------------------------------------------------------------------------- 1 | ../../../../interop-test-files/syntax/recordkey_syntax_invalid.txt -------------------------------------------------------------------------------- /pnpm-workspace.yaml: -------------------------------------------------------------------------------- 1 | packages: 2 | - 'services/*' 3 | - 'packages/*' 4 | - 'packages/oauth/*' 5 | - 'packages/internal/*' 6 | -------------------------------------------------------------------------------- /packages/internal/did-resolver/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "include": [], 3 | "references": [{ "path": "./tsconfig.build.json" }] 4 | } 5 | -------------------------------------------------------------------------------- /packages/internal/handle-resolver/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "include": [], 3 | "references": [{ "path": "./tsconfig.build.json" }] 4 | } 5 | -------------------------------------------------------------------------------- /packages/internal/simple-store/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "include": [], 3 | "references": [{ "path": "./tsconfig.build.json" }] 4 | } 5 | -------------------------------------------------------------------------------- /packages/oauth/oauth-client-expo/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "include": [], 3 | "references": [{ "path": "./tsconfig.build.json" }] 4 | } 5 | -------------------------------------------------------------------------------- /packages/oauth/oauth-client-node/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "include": [], 3 | "references": [{ "path": "./tsconfig.build.json" }] 4 | } 5 | -------------------------------------------------------------------------------- /packages/oauth/oauth-client/src/errors/auth-method-unsatisfiable-error.ts: -------------------------------------------------------------------------------- 1 | export class AuthMethodUnsatisfiableError extends Error {} 2 | -------------------------------------------------------------------------------- /packages/oauth/oauth-provider-api/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "include": [], 3 | "references": [{ "path": "./tsconfig.build.json" }] 4 | } 5 | -------------------------------------------------------------------------------- /packages/oauth/oauth-provider/src/types/email-otp.ts: -------------------------------------------------------------------------------- 1 | import { z } from 'zod' 2 | 3 | export const emailOtpSchema = z.string().min(1) 4 | -------------------------------------------------------------------------------- /packages/oauth/oauth-provider/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "include": [], 3 | "references": [{ "path": "./tsconfig.build.json" }] 4 | } 5 | -------------------------------------------------------------------------------- /packages/pds/src/db/index.ts: -------------------------------------------------------------------------------- 1 | export * from './db' 2 | export * from './cast' 3 | export * from './migrator' 4 | export * from './util' 5 | -------------------------------------------------------------------------------- /packages/sync/src/runner/index.ts: -------------------------------------------------------------------------------- 1 | export * from './consecutive-list' 2 | export * from './memory-runner' 3 | export * from './types' 4 | -------------------------------------------------------------------------------- /jest.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('jest').Config} */ 2 | module.exports = { 3 | projects: ['/packages/*/jest.config.js'], 4 | } 5 | -------------------------------------------------------------------------------- /packages/internal/handle-resolver-node/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "include": [], 3 | "references": [{ "path": "./tsconfig.build.json" }] 4 | } 5 | -------------------------------------------------------------------------------- /packages/internal/identity-resolver/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "include": [], 3 | "references": [{ "path": "./tsconfig.build.json" }] 4 | } 5 | -------------------------------------------------------------------------------- /packages/internal/simple-store-memory/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "include": [], 3 | "references": [{ "path": "./tsconfig.build.json" }] 4 | } 5 | -------------------------------------------------------------------------------- /packages/internal/simple-store-redis/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "include": [], 3 | "references": [{ "path": "./tsconfig.build.json" }] 4 | } 5 | -------------------------------------------------------------------------------- /packages/oauth/oauth-client-browser/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "include": [], 3 | "references": [{ "path": "./tsconfig.build.json" }] 4 | } 5 | -------------------------------------------------------------------------------- /packages/pds/src/actor-store/db/migrations/index.ts: -------------------------------------------------------------------------------- 1 | import * as init from './001-init' 2 | 3 | export default { 4 | '001': init, 5 | } 6 | -------------------------------------------------------------------------------- /packages/pds/src/sequencer/db/migrations/index.ts: -------------------------------------------------------------------------------- 1 | import * as init from './001-init' 2 | 3 | export default { 4 | '001': init, 5 | } 6 | -------------------------------------------------------------------------------- /packages/dev-env/assets/key-landscape-large.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mistydemeo/atproto/main/packages/dev-env/assets/key-landscape-large.jpg -------------------------------------------------------------------------------- /packages/dev-env/assets/key-landscape-small.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mistydemeo/atproto/main/packages/dev-env/assets/key-landscape-small.jpg -------------------------------------------------------------------------------- /packages/dev-env/assets/key-portrait-large.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mistydemeo/atproto/main/packages/dev-env/assets/key-portrait-large.jpg -------------------------------------------------------------------------------- /packages/dev-env/assets/key-portrait-small.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mistydemeo/atproto/main/packages/dev-env/assets/key-portrait-small.jpg -------------------------------------------------------------------------------- /packages/oauth/oauth-client/src/constants.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Per ATProto spec (OpenID uses RS256) 3 | */ 4 | export const FALLBACK_ALG = 'ES256' 5 | -------------------------------------------------------------------------------- /packages/oauth/oauth-provider/src/types/color-hue.ts: -------------------------------------------------------------------------------- 1 | import { z } from 'zod' 2 | 3 | export const colorHueSchema = z.number().min(0).max(360) 4 | -------------------------------------------------------------------------------- /packages/ozone/src/setting/types.ts: -------------------------------------------------------------------------------- 1 | export type ProtectedTagSetting = { 2 | [key: string]: { roles?: string[]; moderators?: string[] } 3 | } 4 | -------------------------------------------------------------------------------- /packages/internal/rollup-plugin-bundle-manifest/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "include": [], 3 | "references": [{ "path": "./tsconfig.build.json" }] 4 | } 5 | -------------------------------------------------------------------------------- /packages/internal/simple-store/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './cached-getter.js' 2 | export * from './simple-store.js' 3 | export * from './util.js' 4 | -------------------------------------------------------------------------------- /packages/lexicon/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './types' 2 | export * from './lexicons' 3 | export * from './blob-refs' 4 | export * from './serialize' 5 | -------------------------------------------------------------------------------- /packages/repo/src/mst/index.ts: -------------------------------------------------------------------------------- 1 | export * from './mst' 2 | export * from './diff' 3 | export * from './walker' 4 | export * as mstUtil from './util' 5 | -------------------------------------------------------------------------------- /packages/internal/handle-resolver/src/handle-resolver-error.ts: -------------------------------------------------------------------------------- 1 | export class HandleResolverError extends Error { 2 | name = 'HandleResolverError' 3 | } 4 | -------------------------------------------------------------------------------- /packages/oauth/oauth-types/src/constants.ts: -------------------------------------------------------------------------------- 1 | export const CLIENT_ASSERTION_TYPE_JWT_BEARER = 2 | 'urn:ietf:params:oauth:client-assertion-type:jwt-bearer' 3 | -------------------------------------------------------------------------------- /interop-test-files/syntax/tid_syntax_valid.txt: -------------------------------------------------------------------------------- 1 | # 13 digits 2 | # 234567abcdefghijklmnopqrstuvwxyz 3 | 4 | 3jzfcijpj2z2a 5 | 7777777777777 6 | 3zzzzzzzzzzzz 7 | -------------------------------------------------------------------------------- /packages/oauth/oauth-types/README.md: -------------------------------------------------------------------------------- 1 | # @atproto/oauth-types 2 | 3 | This library exposes utilities for typing and validating OAuth related data structures. 4 | -------------------------------------------------------------------------------- /packages/internal/identity-resolver/src/identity-resolver-error.ts: -------------------------------------------------------------------------------- 1 | export class IdentityResolverError extends Error { 2 | name = 'IdentityResolverError' 3 | } 4 | -------------------------------------------------------------------------------- /packages/oauth/oauth-provider/src/access-token/access-token-mode.ts: -------------------------------------------------------------------------------- 1 | export enum AccessTokenMode { 2 | stateless = 'stateless', 3 | stateful = 'stateful', 4 | } 5 | -------------------------------------------------------------------------------- /packages/oauth/oauth-provider/src/dpop/dpop-proof.ts: -------------------------------------------------------------------------------- 1 | export type DpopProof = Readonly<{ 2 | jti: string 3 | jkt: string 4 | htm: string 5 | htu: string 6 | }> 7 | -------------------------------------------------------------------------------- /packages/oauth/oauth-provider/src/oidc/sub.ts: -------------------------------------------------------------------------------- 1 | import { z } from 'zod' 2 | 3 | export const subSchema = z.string().min(1) 4 | export type Sub = z.infer 5 | -------------------------------------------------------------------------------- /packages/oauth/oauth-types/src/oauth-code-challenge-method.ts: -------------------------------------------------------------------------------- 1 | import { z } from 'zod' 2 | 3 | export const oauthCodeChallengeMethodSchema = z.enum(['S256', 'plain']) 4 | -------------------------------------------------------------------------------- /packages/api/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "include": [], 3 | "references": [ 4 | { "path": "./tsconfig.build.json" }, 5 | { "path": "./tsconfig.tests.json" } 6 | ] 7 | } 8 | -------------------------------------------------------------------------------- /packages/dev-env/src/const.ts: -------------------------------------------------------------------------------- 1 | export const ADMIN_PASSWORD = 'admin-pass' 2 | export const JWT_SECRET = 'jwt-secret' 3 | export const EXAMPLE_LABELER = 'did:example:labeler' 4 | -------------------------------------------------------------------------------- /packages/identity/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './did' 2 | export * from './handle' 3 | export * from './id-resolver' 4 | export * from './errors' 5 | export * from './types' 6 | -------------------------------------------------------------------------------- /packages/oauth/oauth-provider-frontend/src/components/Divider.tsx: -------------------------------------------------------------------------------- 1 | export function Divider() { 2 | return
3 | } 4 | -------------------------------------------------------------------------------- /packages/oauth/oauth-provider/src/lib/html/index.ts: -------------------------------------------------------------------------------- 1 | export * from './html.js' 2 | export * from './tags.js' 3 | 4 | // Extra util 5 | export * from './build-document.js' 6 | -------------------------------------------------------------------------------- /packages/pds/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "include": [], 3 | "references": [ 4 | { "path": "./tsconfig.build.json" }, 5 | { "path": "./tsconfig.tests.json" } 6 | ] 7 | } 8 | -------------------------------------------------------------------------------- /packages/bsky/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "include": [], 3 | "references": [ 4 | { "path": "./tsconfig.build.json" }, 5 | { "path": "./tsconfig.tests.json" } 6 | ] 7 | } 8 | -------------------------------------------------------------------------------- /packages/bsync/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "include": [], 3 | "references": [ 4 | { "path": "./tsconfig.build.json" }, 5 | { "path": "./tsconfig.tests.json" } 6 | ] 7 | } 8 | -------------------------------------------------------------------------------- /packages/bsync/tsconfig.tests.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig/tests.json", 3 | "compilerOptions": { 4 | "rootDir": "." 5 | }, 6 | "include": ["./tests"] 7 | } 8 | -------------------------------------------------------------------------------- /packages/common/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "include": [], 3 | "references": [ 4 | { "path": "./tsconfig.build.json" }, 5 | { "path": "./tsconfig.tests.json" } 6 | ] 7 | } 8 | -------------------------------------------------------------------------------- /packages/common/tsconfig.tests.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig/tests.json", 3 | "compilerOptions": { 4 | "rootDir": "." 5 | }, 6 | "include": ["./tests"] 7 | } 8 | -------------------------------------------------------------------------------- /packages/crypto/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "include": [], 3 | "references": [ 4 | { "path": "./tsconfig.build.json" }, 5 | { "path": "./tsconfig.tests.json" } 6 | ] 7 | } 8 | -------------------------------------------------------------------------------- /packages/crypto/tsconfig.tests.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig/tests.json", 3 | "compilerOptions": { 4 | "rootDir": "." 5 | }, 6 | "include": ["./tests"] 7 | } 8 | -------------------------------------------------------------------------------- /packages/identity/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "include": [], 3 | "references": [ 4 | { "path": "./tsconfig.build.json" }, 5 | { "path": "./tsconfig.tests.json" } 6 | ] 7 | } 8 | -------------------------------------------------------------------------------- /packages/identity/tsconfig.tests.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig/tests.json", 3 | "compilerOptions": { 4 | "rootDir": "." 5 | }, 6 | "include": ["./tests"] 7 | } 8 | -------------------------------------------------------------------------------- /packages/internal/fetch-node/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from '@atproto-labs/fetch' 2 | 3 | export * from './safe.js' 4 | export * from './unicast.js' 5 | export * from './util.js' 6 | -------------------------------------------------------------------------------- /packages/lexicon/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "include": [], 3 | "references": [ 4 | { "path": "./tsconfig.build.json" }, 5 | { "path": "./tsconfig.tests.json" } 6 | ] 7 | } 8 | -------------------------------------------------------------------------------- /packages/lexicon/tsconfig.tests.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig/tests.json", 3 | "compilerOptions": { 4 | "rootDir": "." 5 | }, 6 | "include": ["./tests"] 7 | } 8 | -------------------------------------------------------------------------------- /packages/oauth/oauth-client-browser-example/src/lib/util.ts: -------------------------------------------------------------------------------- 1 | export const ifString = (value: unknown): string | undefined => 2 | typeof value === 'string' ? value : undefined 3 | -------------------------------------------------------------------------------- /packages/oauth/oauth-provider/src/oauth-client.ts: -------------------------------------------------------------------------------- 1 | export * from '@atproto/oauth-types' 2 | export type * from './client/client.js' 3 | export * from './client/client-utils.js' 4 | -------------------------------------------------------------------------------- /packages/ozone/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "include": [], 3 | "references": [ 4 | { "path": "./tsconfig.build.json" }, 5 | { "path": "./tsconfig.tests.json" } 6 | ] 7 | } 8 | -------------------------------------------------------------------------------- /packages/repo/src/storage/index.ts: -------------------------------------------------------------------------------- 1 | export * from './readable-blockstore' 2 | export * from './memory-blockstore' 3 | export * from './sync-storage' 4 | export * from './types' 5 | -------------------------------------------------------------------------------- /packages/repo/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "include": [], 3 | "references": [ 4 | { "path": "./tsconfig.build.json" }, 5 | { "path": "./tsconfig.tests.json" } 6 | ] 7 | } 8 | -------------------------------------------------------------------------------- /packages/repo/tsconfig.tests.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig/tests.json", 3 | "compilerOptions": { 4 | "rootDir": "." 5 | }, 6 | "include": ["./tests"] 7 | } 8 | -------------------------------------------------------------------------------- /packages/syntax/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "include": [], 3 | "references": [ 4 | { "path": "./tsconfig.build.json" }, 5 | { "path": "./tsconfig.tests.json" } 6 | ] 7 | } 8 | -------------------------------------------------------------------------------- /packages/syntax/tsconfig.tests.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig/tests.json", 3 | "compilerOptions": { 4 | "rootDir": "." 5 | }, 6 | "include": ["./tests"] 7 | } 8 | -------------------------------------------------------------------------------- /packages/common-web/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "include": [], 3 | "references": [ 4 | { "path": "./tsconfig.build.json" }, 5 | { "path": "./tsconfig.tests.json" } 6 | ] 7 | } 8 | -------------------------------------------------------------------------------- /packages/common-web/tsconfig.tests.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig/tests.json", 3 | "compilerOptions": { 4 | "rootDir": "." 5 | }, 6 | "include": ["./tests"] 7 | } 8 | -------------------------------------------------------------------------------- /packages/oauth/oauth-client-browser/src/indexed-db/schema.ts: -------------------------------------------------------------------------------- 1 | export type ObjectStoreSchema = NonNullable 2 | export type DatabaseSchema = Record 3 | -------------------------------------------------------------------------------- /packages/xrpc-server/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "include": [], 3 | "references": [ 4 | { "path": "./tsconfig.build.json" }, 5 | { "path": "./tsconfig.tests.json" } 6 | ] 7 | } 8 | -------------------------------------------------------------------------------- /packages/xrpc-server/tsconfig.tests.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig/tests.json", 3 | "compilerOptions": { 4 | "rootDir": "." 5 | }, 6 | "include": ["./tests"] 7 | } 8 | -------------------------------------------------------------------------------- /packages/aws/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './kms' 2 | export * from './s3' 3 | export * from './cloudfront' 4 | export * from './bunny' 5 | export * from './util' 6 | export * from './types' 7 | -------------------------------------------------------------------------------- /packages/did/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './atproto.js' 2 | export * from './did-document.js' 3 | export * from './did-error.js' 4 | export * from './did.js' 5 | export * from './methods.js' 6 | -------------------------------------------------------------------------------- /packages/lexicon-resolver/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "include": [], 3 | "references": [ 4 | { "path": "./tsconfig.build.json" }, 5 | { "path": "./tsconfig.tests.json" } 6 | ] 7 | } 8 | -------------------------------------------------------------------------------- /packages/oauth/oauth-client-expo/src/ExpoAtprotoOAuthClientModule.types.ts: -------------------------------------------------------------------------------- 1 | // eslint-disable-next-line @typescript-eslint/ban-types 2 | export type ExpoAtprotoOAuthClientModuleEvents = {} 3 | -------------------------------------------------------------------------------- /packages/oauth/oauth-provider-frontend/src/util/sleep.ts: -------------------------------------------------------------------------------- 1 | export async function sleep(delay: number): Promise { 2 | return new Promise((resolve) => setTimeout(resolve, delay)) 3 | } 4 | -------------------------------------------------------------------------------- /packages/oauth/oauth-scopes/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "include": [], 3 | "references": [ 4 | { "path": "./tsconfig.build.json" }, 5 | { "path": "./tsconfig.tests.json" } 6 | ] 7 | } 8 | -------------------------------------------------------------------------------- /packages/api/src/session-manager.ts: -------------------------------------------------------------------------------- 1 | import { FetchHandlerObject } from '@atproto/xrpc' 2 | 3 | export interface SessionManager extends FetchHandlerObject { 4 | readonly did?: string 5 | } 6 | -------------------------------------------------------------------------------- /packages/crypto/src/plugins.ts: -------------------------------------------------------------------------------- 1 | import { p256Plugin } from './p256/plugin' 2 | import { secp256k1Plugin } from './secp256k1/plugin' 3 | 4 | export const plugins = [p256Plugin, secp256k1Plugin] 5 | -------------------------------------------------------------------------------- /packages/oauth/oauth-client-expo/src/polyfill.native.ts: -------------------------------------------------------------------------------- 1 | import 'core-js/proposals/explicit-resource-management' 2 | import 'event-target-polyfill' 3 | import 'react-native-url-polyfill/auto' 4 | -------------------------------------------------------------------------------- /packages/oauth/oauth-provider-ui/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "include": [], 3 | "references": [ 4 | { "path": "./tsconfig.src.json" }, 5 | { "path": "./tsconfig.tools.json" } 6 | ] 7 | } 8 | -------------------------------------------------------------------------------- /packages/oauth/oauth-scopes/tsconfig.tests.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../../tsconfig/tests.json", 3 | "compilerOptions": { 4 | "rootDir": "src" 5 | }, 6 | "include": ["src"] 7 | } 8 | -------------------------------------------------------------------------------- /packages/pds/src/mailer/templates/update-email.d.ts: -------------------------------------------------------------------------------- 1 | import { TemplateDelegate } from 'handlebars' 2 | 3 | declare const template: TemplateDelegate<{ token: string }> 4 | export default template 5 | -------------------------------------------------------------------------------- /packages/oauth/oauth-client-browser/src/indexed-db/index.ts: -------------------------------------------------------------------------------- 1 | export * from './db.js' 2 | export * from './db-index.js' 3 | export * from './db-object-store.js' 4 | export * from './db-transaction.js' 5 | -------------------------------------------------------------------------------- /packages/oauth/oauth-provider-frontend/src/locales/setup.ts: -------------------------------------------------------------------------------- 1 | import { i18n } from '@lingui/core' 2 | import { messages } from './en/messages' 3 | 4 | i18n.load('en', messages) 5 | i18n.activate('en') 6 | -------------------------------------------------------------------------------- /packages/oauth/oauth-provider-frontend/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "include": [], 3 | "references": [ 4 | { "path": "./tsconfig.src.json" }, 5 | { "path": "./tsconfig.tools.json" } 6 | ] 7 | } 8 | -------------------------------------------------------------------------------- /packages/oauth/oauth-provider/src/types/invite-code.ts: -------------------------------------------------------------------------------- 1 | import { z } from 'zod' 2 | 3 | export const inviteCodeSchema = z.string().min(1) 4 | export type InviteCode = z.infer 5 | -------------------------------------------------------------------------------- /packages/pds/src/mailer/templates/confirm-email.d.ts: -------------------------------------------------------------------------------- 1 | import { TemplateDelegate } from 'handlebars' 2 | 3 | declare const template: TemplateDelegate<{ token: string }> 4 | export default template 5 | -------------------------------------------------------------------------------- /packages/pds/src/mailer/templates/delete-account.d.ts: -------------------------------------------------------------------------------- 1 | import { TemplateDelegate } from 'handlebars' 2 | 3 | declare const template: TemplateDelegate<{ token: string }> 4 | export default template 5 | -------------------------------------------------------------------------------- /packages/pds/src/mailer/templates/plc-operation.d.ts: -------------------------------------------------------------------------------- 1 | import { TemplateDelegate } from 'handlebars' 2 | 3 | declare const template: TemplateDelegate<{ token: string }> 4 | export default template 5 | -------------------------------------------------------------------------------- /packages/oauth/oauth-types/src/oauth-client-id.ts: -------------------------------------------------------------------------------- 1 | import { z } from 'zod' 2 | 3 | export const oauthClientIdSchema = z.string().min(1) 4 | export type OAuthClientId = z.infer 5 | -------------------------------------------------------------------------------- /packages/repo/tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig/node.json", 3 | "compilerOptions": { 4 | "rootDir": "./src", 5 | "outDir": "./dist" 6 | }, 7 | "include": ["./src"] 8 | } 9 | -------------------------------------------------------------------------------- /packages/sync/tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig/node.json", 3 | "compilerOptions": { 4 | "rootDir": "./src", 5 | "outDir": "./dist" 6 | }, 7 | "include": ["./src"] 8 | } 9 | -------------------------------------------------------------------------------- /packages/aws/tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig/isomorphic.json", 3 | "compilerOptions": { 4 | "rootDir": "./src", 5 | "outDir": "./dist" 6 | }, 7 | "include": ["./src"] 8 | } 9 | -------------------------------------------------------------------------------- /packages/bsky/tsconfig.tests.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig/tests.json", 3 | "compilerOptions": { 4 | "rootDir": ".", 5 | "noUnusedLocals": false 6 | }, 7 | "include": ["./tests"] 8 | } 9 | -------------------------------------------------------------------------------- /packages/bsync/tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig/node.json", 3 | "compilerOptions": { 4 | "rootDir": "./src", 5 | "outDir": "./dist" 6 | }, 7 | "include": ["./src"] 8 | } 9 | -------------------------------------------------------------------------------- /packages/common/tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig/node.json", 3 | "compilerOptions": { 4 | "rootDir": "./src", 5 | "outDir": "./dist" 6 | }, 7 | "include": ["./src"] 8 | } 9 | -------------------------------------------------------------------------------- /packages/dev-env/tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig/node.json", 3 | "compilerOptions": { 4 | "rootDir": "./src", 5 | "outDir": "./dist" 6 | }, 7 | "include": ["./src"] 8 | } 9 | -------------------------------------------------------------------------------- /packages/did/tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig/isomorphic.json", 3 | "compilerOptions": { 4 | "rootDir": "./src", 5 | "outDir": "./dist" 6 | }, 7 | "include": ["./src"] 8 | } 9 | -------------------------------------------------------------------------------- /packages/identity/src/did/index.ts: -------------------------------------------------------------------------------- 1 | export * from './web-resolver' 2 | export * from './plc-resolver' 3 | export * from './did-resolver' 4 | export * from './atproto-data' 5 | export * from './memory-cache' 6 | -------------------------------------------------------------------------------- /packages/lex-cli/tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig/node.json", 3 | "compilerOptions": { 4 | "rootDir": "./src", 5 | "outDir": "./dist" 6 | }, 7 | "include": ["./src"] 8 | } 9 | -------------------------------------------------------------------------------- /packages/oauth/oauth-client-browser-example/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "include": [], 3 | "references": [ 4 | { "path": "./tsconfig.build.json" }, 5 | { "path": "./tsconfig.tools.json" } 6 | ] 7 | } 8 | -------------------------------------------------------------------------------- /packages/oauth/oauth-provider/src/types/password.ts: -------------------------------------------------------------------------------- 1 | import { z } from 'zod' 2 | 3 | export const oldPasswordSchema = z.string().min(1).max(512) 4 | export const newPasswordSchema = z.string().min(8).max(256) 5 | -------------------------------------------------------------------------------- /packages/oauth/oauth-types/src/atproto-loopback-client-redirect-uris.ts: -------------------------------------------------------------------------------- 1 | export const DEFAULT_LOOPBACK_CLIENT_REDIRECT_URIS = Object.freeze([ 2 | `http://127.0.0.1/`, 3 | `http://[::1]/`, 4 | ] as const) 5 | -------------------------------------------------------------------------------- /packages/oauth/oauth-types/src/oauth-request-uri.ts: -------------------------------------------------------------------------------- 1 | import { z } from 'zod' 2 | 3 | export const oauthRequestUriSchema = z.string() 4 | 5 | export type OAuthRequestUri = z.infer 6 | -------------------------------------------------------------------------------- /packages/ozone/tsconfig.tests.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig/tests.json", 3 | "compilerOptions": { 4 | "rootDir": ".", 5 | "noUnusedLocals": false 6 | }, 7 | "include": ["./tests"] 8 | } 9 | -------------------------------------------------------------------------------- /packages/pds/tsconfig.tests.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig/tests.json", 3 | "compilerOptions": { 4 | "rootDir": ".", 5 | "noUnusedLocals": false 6 | }, 7 | "include": ["./tests"] 8 | } 9 | -------------------------------------------------------------------------------- /packages/repo/src/logger.ts: -------------------------------------------------------------------------------- 1 | import { subsystemLogger } from '@atproto/common' 2 | 3 | export const logger: ReturnType = 4 | subsystemLogger('repo') 5 | 6 | export default logger 7 | -------------------------------------------------------------------------------- /packages/crypto/tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig/isomorphic.json", 3 | "compilerOptions": { 4 | "rootDir": "./src", 5 | "outDir": "./dist" 6 | }, 7 | "include": ["./src"] 8 | } 9 | -------------------------------------------------------------------------------- /packages/identity/tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig/isomorphic.json", 3 | "compilerOptions": { 4 | "rootDir": "./src", 5 | "outDir": "./dist" 6 | }, 7 | "include": ["./src"] 8 | } 9 | -------------------------------------------------------------------------------- /packages/internal/simple-store/src/util.ts: -------------------------------------------------------------------------------- 1 | export type Awaitable = V | PromiseLike 2 | 3 | export type ContextOptions = C extends void | undefined 4 | ? { context?: undefined } 5 | : { context: C } 6 | -------------------------------------------------------------------------------- /packages/lexicon/tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig/isomorphic.json", 3 | "compilerOptions": { 4 | "rootDir": "./src", 5 | "outDir": "./dist" 6 | }, 7 | "include": ["./src"] 8 | } 9 | -------------------------------------------------------------------------------- /packages/oauth/jwk/tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["../../../tsconfig/isomorphic.json"], 3 | "compilerOptions": { 4 | "outDir": "dist", 5 | "rootDir": "src" 6 | }, 7 | "include": ["src"] 8 | } 9 | -------------------------------------------------------------------------------- /packages/oauth/oauth-provider-api/src/index.ts: -------------------------------------------------------------------------------- 1 | export type * from './api-endpoints.js' 2 | export type * from './customization-data.js' 3 | export type * from './types.js' 4 | 5 | export * from './contants.js' 6 | -------------------------------------------------------------------------------- /packages/pds/src/mailer/templates/reset-password.d.ts: -------------------------------------------------------------------------------- 1 | import { TemplateDelegate } from 'handlebars' 2 | 3 | declare const template: TemplateDelegate<{ token: string; handle: string }> 4 | export default template 5 | -------------------------------------------------------------------------------- /packages/syntax/tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig/isomorphic.json", 3 | "compilerOptions": { 4 | "rootDir": "./src", 5 | "outDir": "./dist" 6 | }, 7 | "include": ["./src"] 8 | } 9 | -------------------------------------------------------------------------------- /packages/xrpc-server/tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig/node.json", 3 | "compilerOptions": { 4 | "rootDir": "./src", 5 | "outDir": "./dist" 6 | }, 7 | "include": ["./src"] 8 | } 9 | -------------------------------------------------------------------------------- /packages/xrpc/tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig/isomorphic.json", 3 | "compilerOptions": { 4 | "rootDir": "./src", 5 | "outDir": "./dist" 6 | }, 7 | "include": ["./src"] 8 | } 9 | -------------------------------------------------------------------------------- /packages/bsky/src/image/logger.ts: -------------------------------------------------------------------------------- 1 | import { subsystemLogger } from '@atproto/common' 2 | 3 | export const logger: ReturnType = 4 | subsystemLogger('bsky:image') 5 | 6 | export default logger 7 | -------------------------------------------------------------------------------- /packages/common-web/tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig/isomorphic.json", 3 | "compilerOptions": { 4 | "rootDir": "./src", 5 | "outDir": "./dist" 6 | }, 7 | "include": ["./src"] 8 | } 9 | -------------------------------------------------------------------------------- /packages/internal/fetch-node/tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["../../../tsconfig/node.json"], 3 | "compilerOptions": { 4 | "outDir": "dist", 5 | "rootDir": "src" 6 | }, 7 | "include": ["src"] 8 | } 9 | -------------------------------------------------------------------------------- /packages/internal/fetch/tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["../../../tsconfig/isomorphic.json"], 3 | "compilerOptions": { 4 | "outDir": "dist", 5 | "rootDir": "src" 6 | }, 7 | "include": ["src"] 8 | } 9 | -------------------------------------------------------------------------------- /packages/internal/pipe/tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["../../../tsconfig/isomorphic.json"], 3 | "compilerOptions": { 4 | "outDir": "dist", 5 | "rootDir": "src" 6 | }, 7 | "include": ["src"] 8 | } 9 | -------------------------------------------------------------------------------- /packages/internal/xrpc-utils/tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["../../../tsconfig/node.json"], 3 | "compilerOptions": { 4 | "outDir": "dist", 5 | "rootDir": "src" 6 | }, 7 | "include": ["src"] 8 | } 9 | -------------------------------------------------------------------------------- /packages/oauth/jwk-jose/tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["../../../tsconfig/nodenext.json"], 3 | "compilerOptions": { 4 | "outDir": "dist", 5 | "rootDir": "src" 6 | }, 7 | "include": ["src"] 8 | } 9 | -------------------------------------------------------------------------------- /packages/oauth/oauth-types/src/oauth-access-token.ts: -------------------------------------------------------------------------------- 1 | import { z } from 'zod' 2 | 3 | export const oauthAccessTokenSchema = z.string().min(1) 4 | export type OAuthAccessToken = z.infer 5 | -------------------------------------------------------------------------------- /packages/oauth/oauth-types/src/oauth-refresh-token.ts: -------------------------------------------------------------------------------- 1 | import { z } from 'zod' 2 | 3 | export const oauthRefreshTokenSchema = z.string().min(1) 4 | export type OAuthRefreshToken = z.infer 5 | -------------------------------------------------------------------------------- /tsconfig/node.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json.schemastore.org/tsconfig", 3 | "extends": "./base.json", 4 | "compilerOptions": { 5 | "lib": ["ES2023", "ScriptHost"], 6 | "types": ["node"] 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /packages/lexicon-resolver/tsconfig.tests.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig/tests.json", 3 | "compilerOptions": { 4 | "rootDir": ".", 5 | "noUnusedLocals": false 6 | }, 7 | "include": ["./tests"] 8 | } 9 | -------------------------------------------------------------------------------- /packages/oauth/oauth-provider-api/src/contants.ts: -------------------------------------------------------------------------------- 1 | export const CSRF_COOKIE_NAME = 'csrf-token' 2 | export const CSRF_HEADER_NAME = 'x-csrf-token' 3 | 4 | export const API_ENDPOINT_PREFIX = '/@atproto/oauth-provider/~api' 5 | -------------------------------------------------------------------------------- /packages/oauth/oauth-provider/tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["../../../tsconfig/nodenext.json"], 3 | "compilerOptions": { 4 | "outDir": "dist", 5 | "rootDir": "src" 6 | }, 7 | "include": ["src"] 8 | } 9 | -------------------------------------------------------------------------------- /packages/syntax/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './handle' 2 | export * from './did' 3 | export * from './nsid' 4 | export * from './aturi' 5 | export * from './tid' 6 | export * from './recordkey' 7 | export * from './datetime' 8 | -------------------------------------------------------------------------------- /packages/oauth/oauth-client-expo/tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["../../../tsconfig/expo.json"], 3 | "compilerOptions": { 4 | "rootDir": "./src", 5 | "outDir": "./dist" 6 | }, 7 | "include": ["./src"] 8 | } 9 | -------------------------------------------------------------------------------- /packages/oauth/oauth-client-node/src/util.ts: -------------------------------------------------------------------------------- 1 | // eslint-disable-next-line @typescript-eslint/ban-types 2 | export type Simplify = { [K in keyof T]: T[K] } & {} 3 | export type Override = Simplify> 4 | -------------------------------------------------------------------------------- /packages/oauth/oauth-client-node/tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../../tsconfig/node.json", 3 | "compilerOptions": { 4 | "rootDir": "./src", 5 | "outDir": "./dist" 6 | }, 7 | "include": ["./src"] 8 | } 9 | -------------------------------------------------------------------------------- /packages/oauth/oauth-client/tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["../../../tsconfig/isomorphic.json"], 3 | "compilerOptions": { 4 | "rootDir": "./src", 5 | "outDir": "./dist" 6 | }, 7 | "include": ["./src"] 8 | } 9 | -------------------------------------------------------------------------------- /packages/oauth/oauth-provider/src/client/client-id.ts: -------------------------------------------------------------------------------- 1 | import { OAuthClientId, oauthClientIdSchema } from '@atproto/oauth-types' 2 | 3 | export type ClientId = OAuthClientId 4 | export const clientIdSchema = oauthClientIdSchema 5 | -------------------------------------------------------------------------------- /packages/oauth/oauth-types/src/oidc-entity-type.ts: -------------------------------------------------------------------------------- 1 | import { z } from 'zod' 2 | 3 | export const oidcEntityTypeSchema = z.enum(['userinfo', 'id_token']) 4 | 5 | export type OidcEntityType = z.infer 6 | -------------------------------------------------------------------------------- /packages/oauth/oauth-types/tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../../tsconfig/isomorphic.json", 3 | "compilerOptions": { 4 | "rootDir": "./src", 5 | "outDir": "./dist" 6 | }, 7 | "include": ["./src"] 8 | } 9 | -------------------------------------------------------------------------------- /packages/pds/src/util/types.ts: -------------------------------------------------------------------------------- 1 | export type Simplify = { 2 | [K in keyof T]: T[K] 3 | } & NonNullable 4 | 5 | export type WithRequired = Simplify< 6 | Omit & Required> 7 | > 8 | -------------------------------------------------------------------------------- /packages/xrpc-server/src/stream/index.ts: -------------------------------------------------------------------------------- 1 | export * from './types' 2 | export * from './frames' 3 | export * from './stream' 4 | export * from './subscription' 5 | export * from './server' 6 | export * from './websocket-keepalive' 7 | -------------------------------------------------------------------------------- /packages/xrpc-server/src/stream/logger.ts: -------------------------------------------------------------------------------- 1 | import { subsystemLogger } from '@atproto/common' 2 | 3 | export const logger: ReturnType = 4 | subsystemLogger('xrpc-stream') 5 | 6 | export default logger 7 | -------------------------------------------------------------------------------- /packages/internal/handle-resolver-node/tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["../../../tsconfig/node.json"], 3 | "compilerOptions": { 4 | "rootDir": "./src", 5 | "outDir": "./dist" 6 | }, 7 | "include": ["./src"] 8 | } 9 | -------------------------------------------------------------------------------- /packages/internal/handle-resolver/tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../../tsconfig/isomorphic.json", 3 | "compilerOptions": { 4 | "rootDir": "./src", 5 | "outDir": "./dist" 6 | }, 7 | "include": ["./src"] 8 | } 9 | -------------------------------------------------------------------------------- /packages/internal/identity-resolver/tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["../../../tsconfig/isomorphic.json"], 3 | "compilerOptions": { 4 | "outDir": "dist", 5 | "rootDir": "src" 6 | }, 7 | "include": ["src"] 8 | } 9 | -------------------------------------------------------------------------------- /packages/internal/simple-store-redis/tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../../tsconfig/node.json", 3 | "compilerOptions": { 4 | "rootDir": "./src", 5 | "outDir": "./dist" 6 | }, 7 | "include": ["./src"] 8 | } 9 | -------------------------------------------------------------------------------- /packages/internal/simple-store/tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../../tsconfig/isomorphic.json", 3 | "compilerOptions": { 4 | "rootDir": "./src", 5 | "outDir": "./dist" 6 | }, 7 | "include": ["./src"] 8 | } 9 | -------------------------------------------------------------------------------- /packages/oauth/jwk-webcrypto/tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["../../../tsconfig/isomorphic.json"], 3 | "compilerOptions": { 4 | "rootDir": "./src", 5 | "outDir": "./dist" 6 | }, 7 | "include": ["./src"] 8 | } 9 | -------------------------------------------------------------------------------- /packages/oauth/oauth-provider-api/tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../../tsconfig/isomorphic.json", 3 | "compilerOptions": { 4 | "rootDir": "./src", 5 | "outDir": "./dist" 6 | }, 7 | "include": ["./src"] 8 | } 9 | -------------------------------------------------------------------------------- /packages/oauth/oauth-provider-frontend/src/data/useCustomizationData.ts: -------------------------------------------------------------------------------- 1 | import { useHydrationData } from './useHydrationData' 2 | 3 | export function useCustomizationData() { 4 | return useHydrationData('__customizationData') 5 | } 6 | -------------------------------------------------------------------------------- /packages/oauth/oauth-scopes/jest.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('jest').Config} */ 2 | module.exports = { 3 | transform: { '^.+\\.(t|j)s$': '@swc/jest' }, 4 | moduleNameMapper: { '^(\\.\\.?\\/.+)\\.js$': ['$1.ts', '$1.js'] }, 5 | } 6 | -------------------------------------------------------------------------------- /interop-test-files/crypto/w3c_didkey_P256.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "privateKeyBytesBase58": "9p4VRzdmhsnq869vQjVCTrRry7u4TtfRxhvBFJTGU2Cp", 4 | "publicDidKey": "did:key:zDnaeTiq1PdzvZXUaMdezchcMJQpBdH2VN4pgrrEhMCCbmwSb" 5 | } 6 | ] 7 | -------------------------------------------------------------------------------- /packages/internal/rollup-plugin-bundle-manifest/tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["../../../tsconfig/node.json"], 3 | "compilerOptions": { 4 | "outDir": "dist", 5 | "rootDir": "src" 6 | }, 7 | "include": ["src"] 8 | } 9 | -------------------------------------------------------------------------------- /packages/internal/simple-store-memory/tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../../tsconfig/isomorphic.json", 3 | "compilerOptions": { 4 | "rootDir": "./src", 5 | "outDir": "./dist" 6 | }, 7 | "include": ["./src"] 8 | } 9 | -------------------------------------------------------------------------------- /packages/oauth/oauth-client-browser/tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../../tsconfig/isomorphic.json", 3 | "compilerOptions": { 4 | "rootDir": "./src", 5 | "outDir": "./dist" 6 | }, 7 | "include": ["./src"] 8 | } 9 | -------------------------------------------------------------------------------- /packages/sync/src/runner/types.ts: -------------------------------------------------------------------------------- 1 | export interface EventRunner { 2 | getCursor(): Awaited 3 | trackEvent( 4 | did: string, 5 | seq: number, 6 | handler: () => Promise, 7 | ): Promise 8 | } 9 | -------------------------------------------------------------------------------- /packages/internal/did-resolver/tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["../../../tsconfig/isomorphic.json"], 3 | "compilerOptions": { 4 | "rootDir": "./src", 5 | "outDir": "./dist" 6 | }, 7 | "include": ["./src/**/*.ts"] 8 | } 9 | -------------------------------------------------------------------------------- /packages/pds/src/actor-store/db/schema/record-blob.ts: -------------------------------------------------------------------------------- 1 | export interface RecordBlob { 2 | blobCid: string 3 | recordUri: string 4 | } 5 | 6 | export const tableName = 'record_blob' 7 | 8 | export type PartialDB = { [tableName]: RecordBlob } 9 | -------------------------------------------------------------------------------- /services/bsync/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "bsync-service", 3 | "private": true, 4 | "packageManager": "pnpm@8.15.9", 5 | "dependencies": { 6 | "@atproto/bsync": "workspace:^", 7 | "dd-trace": "3.13.2" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /packages/bsky/tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig/node.json", 3 | "compilerOptions": { 4 | "rootDir": "./src", 5 | "outDir": "./dist", 6 | "noUnusedLocals": false 7 | }, 8 | "include": ["./src"] 9 | } 10 | -------------------------------------------------------------------------------- /packages/internal/fetch/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './fetch-error.js' 2 | export * from './fetch-request.js' 3 | export * from './fetch-response.js' 4 | export * from './fetch-wrap.js' 5 | export * from './fetch.js' 6 | export * from './util.js' 7 | -------------------------------------------------------------------------------- /packages/oauth/oauth-provider-frontend/src/util/wait.ts: -------------------------------------------------------------------------------- 1 | import { sleep } from './sleep' 2 | 3 | export async function wait(delay: number, promise: T) { 4 | const [result] = await Promise.all([promise, sleep(delay)]) 5 | return result 6 | } 7 | -------------------------------------------------------------------------------- /packages/oauth/oauth-scopes/src/lib/nsid.ts: -------------------------------------------------------------------------------- 1 | import { isValidNsid } from '@atproto/syntax' 2 | 3 | export type Nsid = `${string}.${string}.${string}` 4 | export const isNsid = (v: unknown): v is Nsid => 5 | typeof v === 'string' && isValidNsid(v) 6 | -------------------------------------------------------------------------------- /packages/ozone/tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig/node.json", 3 | "compilerOptions": { 4 | "rootDir": "./src", 5 | "outDir": "./dist", 6 | "noUnusedLocals": false 7 | }, 8 | "include": ["./src"] 9 | } 10 | -------------------------------------------------------------------------------- /packages/pds/src/did-cache/db/schema.ts: -------------------------------------------------------------------------------- 1 | export interface DidDoc { 2 | did: string 3 | doc: string // json representation of DidDocument 4 | updatedAt: number 5 | } 6 | 7 | export type DidCacheSchema = { 8 | did_doc: DidDoc 9 | } 10 | -------------------------------------------------------------------------------- /packages/pds/tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig/node.json", 3 | "compilerOptions": { 4 | "rootDir": "./src", 5 | "outDir": "./dist", 6 | "noUnusedLocals": false 7 | }, 8 | "include": ["./src"] 9 | } 10 | -------------------------------------------------------------------------------- /packages/api/tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig/isomorphic.json", 3 | "compilerOptions": { 4 | "rootDir": "./src", 5 | "outDir": "./dist", 6 | "noUnusedLocals": false 7 | }, 8 | "include": ["./src"] 9 | } 10 | -------------------------------------------------------------------------------- /packages/internal/identity-resolver/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './atproto-identity-resolver.js' 2 | export * from './constants.js' 3 | export * from './identity-resolver-error.js' 4 | export * from './identity-resolver.js' 5 | export * from './util.js' 6 | -------------------------------------------------------------------------------- /packages/pds/src/scripts/util.ts: -------------------------------------------------------------------------------- 1 | export const parseIntArg = (arg: string): number => { 2 | const parsed = parseInt(arg, 10) 3 | if (isNaN(parsed)) { 4 | throw new Error(`Invalid arg, expected number: ${arg}`) 5 | } 6 | return parsed 7 | } 8 | -------------------------------------------------------------------------------- /tsconfig/browser.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json.schemastore.org/tsconfig", 3 | "extends": "./base.json", 4 | "compilerOptions": { 5 | "lib": ["ES2023", "DOM", "DOM.Iterable", "ESNext.Disposable"], 6 | "jsx": "react-jsx" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /packages/lexicon-resolver/src/util.ts: -------------------------------------------------------------------------------- 1 | import { ensureValidDid } from '@atproto/syntax' 2 | 3 | export function isValidDid(did: string) { 4 | try { 5 | ensureValidDid(did) 6 | return true 7 | } catch { 8 | return false 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /packages/lexicon-resolver/tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["../../tsconfig/node.json"], 3 | "compilerOptions": { 4 | "outDir": "./dist", 5 | "rootDir": "./src", 6 | "noUnusedLocals": false 7 | }, 8 | "include": ["src"] 9 | } 10 | -------------------------------------------------------------------------------- /packages/pds/src/actor-store/db/schema/backlink.ts: -------------------------------------------------------------------------------- 1 | export interface Backlink { 2 | uri: string 3 | path: string 4 | linkTo: string 5 | } 6 | 7 | export const tableName = 'backlink' 8 | 9 | export type PartialDB = { [tableName]: Backlink } 10 | -------------------------------------------------------------------------------- /packages/bsky/src/data-plane/server/db/tables/mute.ts: -------------------------------------------------------------------------------- 1 | export interface Mute { 2 | subjectDid: string 3 | mutedByDid: string 4 | createdAt: string 5 | } 6 | 7 | export const tableName = 'mute' 8 | 9 | export type PartialDB = { [tableName]: Mute } 10 | -------------------------------------------------------------------------------- /packages/oauth/oauth-provider-ui/src/hooks/use-bound-dispatch.ts: -------------------------------------------------------------------------------- 1 | import { Dispatch, useCallback } from 'react' 2 | 3 | export function useBoundDispatch(dispatch: Dispatch, value: A) { 4 | return useCallback(() => dispatch(value), [dispatch, value]) 5 | } 6 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | lerna-debug.log 3 | npm-debug.log 4 | yarn-error.log 5 | packages/**/dist 6 | .idea 7 | packages/*/coverage 8 | test.sqlite 9 | .DS_Store 10 | *.log 11 | *.tsbuildinfo 12 | .*.env 13 | .env.* 14 | .env 15 | \#*\# 16 | *~ 17 | *.swp 18 | -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": [ 3 | "dbaeumer.vscode-eslint", 4 | "expo.vscode-expo-tools", 5 | "wengerk.highlight-bad-chars", 6 | "esbenp.prettier-vscode", 7 | "streetsidesoftware.code-spell-checker" 8 | ] 9 | } 10 | -------------------------------------------------------------------------------- /packages/oauth/oauth-client-node/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from '@atproto-labs/handle-resolver-node' 2 | export * from '@atproto/jwk-webcrypto' 3 | export * from '@atproto/oauth-client' 4 | export * from '@atproto/jwk-jose' 5 | 6 | export * from './node-oauth-client.js' 7 | -------------------------------------------------------------------------------- /packages/oauth/oauth-scopes/tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["../../../tsconfig/isomorphic.json"], 3 | "compilerOptions": { 4 | "outDir": "dist", 5 | "rootDir": "src" 6 | }, 7 | "include": ["src"], 8 | "exclude": ["**/*.test.ts"] 9 | } 10 | -------------------------------------------------------------------------------- /packages/ozone/src/setting/constants.ts: -------------------------------------------------------------------------------- 1 | export const ProtectedTagSettingKey = 'tools.ozone.setting.protectedTags' 2 | export const PolicyListSettingKey = 'tools.ozone.setting.policyList' 3 | export const SeverityLevelSettingKey = 'tools.ozone.setting.severityLevels' 4 | -------------------------------------------------------------------------------- /packages/xrpc-server/src/logger.ts: -------------------------------------------------------------------------------- 1 | import { subsystemLogger } from '@atproto/common' 2 | 3 | export const LOGGER_NAME = 'xrpc-server' 4 | 5 | export const logger: ReturnType = 6 | subsystemLogger(LOGGER_NAME) 7 | 8 | export default logger 9 | -------------------------------------------------------------------------------- /packages/dev-infra/with-test-db.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | # Example usage: 4 | # ./with-test-db.sh psql postgresql://pg:password@localhost:5433/postgres -c 'select 1;' 5 | 6 | dir=$(dirname $0) 7 | . ${dir}/_common.sh 8 | 9 | SERVICES="db_test" main "$@" 10 | -------------------------------------------------------------------------------- /packages/oauth/oauth-client-browser-example/tsconfig.tools.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../../tsconfig/node.json", 3 | "compilerOptions": { 4 | "rootDir": ".", 5 | "noEmit": true 6 | }, 7 | "include": ["./*.js", "./*.ts"], 8 | "exclude": [] 9 | } 10 | -------------------------------------------------------------------------------- /packages/pds/src/actor-store/db/schema/repo-root.ts: -------------------------------------------------------------------------------- 1 | export interface RepoRoot { 2 | did: string 3 | cid: string 4 | rev: string 5 | indexedAt: string 6 | } 7 | 8 | const tableName = 'repo_root' 9 | 10 | export type PartialDB = { [tableName]: RepoRoot } 11 | -------------------------------------------------------------------------------- /tsconfig/tests.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json.schemastore.org/tsconfig", 3 | "extends": "./node.json", 4 | "compilerOptions": { 5 | "types": ["node", "jest"], 6 | "lib": ["ES2023", "DOM", "DOM.Iterable"], 7 | "noEmit": true 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /lexicons/com/atproto/sync/defs.json: -------------------------------------------------------------------------------- 1 | { 2 | "lexicon": 1, 3 | "id": "com.atproto.sync.defs", 4 | "defs": { 5 | "hostStatus": { 6 | "type": "string", 7 | "knownValues": ["active", "idle", "offline", "throttled", "banned"] 8 | } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /packages/aws/src/types.ts: -------------------------------------------------------------------------------- 1 | // @NOTE keep in sync with same interface in bsky/src/image/invalidator.ts 2 | // this is separate to avoid the dependency on @atproto/bsky. 3 | export interface ImageInvalidator { 4 | invalidate(subject: string, paths: string[]): Promise 5 | } 6 | -------------------------------------------------------------------------------- /packages/bsky/src/data-plane/server/db/tables/list-mute.ts: -------------------------------------------------------------------------------- 1 | export const tableName = 'list_mute' 2 | 3 | export interface ListMute { 4 | listUri: string 5 | mutedByDid: string 6 | createdAt: string 7 | } 8 | 9 | export type PartialDB = { [tableName]: ListMute } 10 | -------------------------------------------------------------------------------- /packages/bsky/src/data-plane/server/db/tables/suggested-feed.ts: -------------------------------------------------------------------------------- 1 | export const tableName = 'suggested_feed' 2 | 3 | export interface SuggestedFeed { 4 | uri: string 5 | order: number 6 | } 7 | 8 | export type PartialDB = { 9 | [tableName]: SuggestedFeed 10 | } 11 | -------------------------------------------------------------------------------- /packages/bsky/src/data-plane/server/db/types.ts: -------------------------------------------------------------------------------- 1 | import { Pool as PgPool } from 'pg' 2 | 3 | export type PgOptions = { 4 | url: string 5 | pool?: PgPool 6 | schema?: string 7 | poolSize?: number 8 | poolMaxUses?: number 9 | poolIdleTimeoutMs?: number 10 | } 11 | -------------------------------------------------------------------------------- /packages/oauth/oauth-provider-frontend/src/data/useHasAccounts.ts: -------------------------------------------------------------------------------- 1 | import { useDeviceSessionsQuery } from '#/data/useDeviceSessionsQuery' 2 | 3 | export function useHasAccounts() { 4 | const { data: accounts } = useDeviceSessionsQuery() 5 | return accounts?.length > 0 6 | } 7 | -------------------------------------------------------------------------------- /packages/oauth/oauth-provider-ui/tsconfig.tools.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["../../../tsconfig/nodenext.json"], 3 | "compilerOptions": { 4 | "rootDir": ".", 5 | "noEmit": true 6 | }, 7 | "include": ["./*.js", "./*.cjs", "./*.mjs", "./*.ts", "./*.cts", "./*.mts"] 8 | } 9 | -------------------------------------------------------------------------------- /packages/oauth/oauth-provider/src/lib/nsid.ts: -------------------------------------------------------------------------------- 1 | import { NSID } from '@atproto/syntax' 2 | export { NSID } 3 | 4 | export function parseNSID(value: string): NSID | null { 5 | try { 6 | return NSID.parse(value) 7 | } catch { 8 | return null 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /packages/api/tsconfig.tests.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig/tests.json", 3 | "compilerOptions": { 4 | "rootDir": ".", 5 | "types": ["jest", "./jest.d.ts"], 6 | "noEmit": true, 7 | "noUnusedLocals": false 8 | }, 9 | "include": ["./tests"] 10 | } 11 | -------------------------------------------------------------------------------- /packages/bsky/src/data-plane/server/db/tables/actor-sync.ts: -------------------------------------------------------------------------------- 1 | export interface ActorSync { 2 | did: string 3 | commitCid: string 4 | repoRev: string | null 5 | } 6 | 7 | export const tableName = 'actor_sync' 8 | 9 | export type PartialDB = { [tableName]: ActorSync } 10 | -------------------------------------------------------------------------------- /packages/bsky/src/data-plane/server/db/tables/subscription.ts: -------------------------------------------------------------------------------- 1 | export const tableName = 'subscription' 2 | 3 | export interface Subscription { 4 | service: string 5 | method: string 6 | state: string 7 | } 8 | 9 | export type PartialDB = { [tableName]: Subscription } 10 | -------------------------------------------------------------------------------- /packages/bsky/src/data-plane/server/db/tables/suggested-follow.ts: -------------------------------------------------------------------------------- 1 | export const tableName = 'suggested_follow' 2 | 3 | export interface SuggestedFollow { 4 | did: string 5 | order: number 6 | } 7 | 8 | export type PartialDB = { 9 | [tableName]: SuggestedFollow 10 | } 11 | -------------------------------------------------------------------------------- /packages/oauth/oauth-types/src/oauth-endpoint-name.ts: -------------------------------------------------------------------------------- 1 | export const OAUTH_ENDPOINT_NAMES = [ 2 | 'token', 3 | 'revocation', 4 | 'introspection', 5 | 'pushed_authorization_request', 6 | ] as const 7 | 8 | export type OAuthEndpointName = (typeof OAUTH_ENDPOINT_NAMES)[number] 9 | -------------------------------------------------------------------------------- /packages/oauth/oauth-types/src/oauth-response-mode.ts: -------------------------------------------------------------------------------- 1 | import { z } from 'zod' 2 | 3 | export const oauthResponseModeSchema = z.enum([ 4 | 'query', 5 | 'fragment', 6 | 'form_post', 7 | ]) 8 | 9 | export type OAuthResponseMode = z.infer 10 | -------------------------------------------------------------------------------- /packages/pds/src/account-manager/db/schema/repo-root.ts: -------------------------------------------------------------------------------- 1 | export interface RepoRoot { 2 | did: string 3 | cid: string 4 | rev: string 5 | indexedAt: string 6 | } 7 | 8 | export const tableName = 'repo_root' 9 | 10 | export type PartialDB = { [tableName]: RepoRoot } 11 | -------------------------------------------------------------------------------- /services/ozone/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ozone-service", 3 | "private": true, 4 | "packageManager": "pnpm@8.15.9", 5 | "dependencies": { 6 | "@atproto/aws": "workspace:^", 7 | "@atproto/ozone": "workspace:^", 8 | "dd-trace": "3.13.2" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /lexicons/com/atproto/server/deleteSession.json: -------------------------------------------------------------------------------- 1 | { 2 | "lexicon": 1, 3 | "id": "com.atproto.server.deleteSession", 4 | "defs": { 5 | "main": { 6 | "type": "procedure", 7 | "description": "Delete the current session. Requires auth." 8 | } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /packages/bsky/buf.gen.yaml: -------------------------------------------------------------------------------- 1 | version: v1 2 | plugins: 3 | - plugin: es 4 | opt: 5 | - target=ts 6 | - import_extension= 7 | out: src/proto 8 | - plugin: connect-es 9 | opt: 10 | - target=ts 11 | - import_extension= 12 | out: src/proto 13 | -------------------------------------------------------------------------------- /packages/bsky/src/data-plane/server/db/tables/blob-takedown.ts: -------------------------------------------------------------------------------- 1 | export interface BlobTakedown { 2 | did: string 3 | cid: string 4 | takedownRef: string 5 | } 6 | 7 | export const tableName = 'blob_takedown' 8 | 9 | export type PartialDB = { [tableName]: BlobTakedown } 10 | -------------------------------------------------------------------------------- /packages/bsky/src/data-plane/server/db/tables/thread-mute.ts: -------------------------------------------------------------------------------- 1 | export const tableName = 'thread_mute' 2 | 3 | export interface ThreadMute { 4 | rootUri: string 5 | mutedByDid: string 6 | createdAt: string 7 | } 8 | 9 | export type PartialDB = { [tableName]: ThreadMute } 10 | -------------------------------------------------------------------------------- /packages/bsync/buf.gen.yaml: -------------------------------------------------------------------------------- 1 | version: v1 2 | plugins: 3 | - plugin: es 4 | opt: 5 | - target=ts 6 | - import_extension= 7 | out: src/proto 8 | - plugin: connect-es 9 | opt: 10 | - target=ts 11 | - import_extension= 12 | out: src/proto 13 | -------------------------------------------------------------------------------- /packages/oauth/oauth-provider-frontend/tsconfig.tools.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["../../../tsconfig/nodenext.json"], 3 | "compilerOptions": { 4 | "rootDir": ".", 5 | "noEmit": true 6 | }, 7 | "include": ["./*.js", "./*.cjs", "./*.mjs", "./*.ts", "./*.cts", "./*.mts"] 8 | } 9 | -------------------------------------------------------------------------------- /packages/oauth/oauth-provider/src/lib/util/date.ts: -------------------------------------------------------------------------------- 1 | export function dateToEpoch(date: Date = new Date()) { 2 | return Math.floor(date.getTime() / 1000) 3 | } 4 | 5 | export function dateToRelativeSeconds(date: Date) { 6 | return Math.floor((date.getTime() - Date.now()) / 1000) 7 | } 8 | -------------------------------------------------------------------------------- /packages/ozone/src/db/schema/signing_key.ts: -------------------------------------------------------------------------------- 1 | import { Generated } from 'kysely' 2 | 3 | export const tableName = 'signing_key' 4 | 5 | export interface SigningKey { 6 | id: Generated 7 | key: string 8 | } 9 | 10 | export type PartialDB = { [tableName]: SigningKey } 11 | -------------------------------------------------------------------------------- /services/bsky/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "bsky-app-view-service", 3 | "private": true, 4 | "packageManager": "pnpm@8.15.9", 5 | "dependencies": { 6 | "@atproto/bsky": "workspace:^", 7 | "@atproto/crypto": "workspace:^", 8 | "dd-trace": "3.13.2" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /lexicons/chat/bsky/actor/exportAccountData.json: -------------------------------------------------------------------------------- 1 | { 2 | "lexicon": 1, 3 | "id": "chat.bsky.actor.exportAccountData", 4 | "defs": { 5 | "main": { 6 | "type": "query", 7 | "output": { 8 | "encoding": "application/jsonl" 9 | } 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /packages/oauth/oauth-client/src/errors/token-refresh-error.ts: -------------------------------------------------------------------------------- 1 | export class TokenRefreshError extends Error { 2 | constructor( 3 | public readonly sub: string, 4 | message: string, 5 | options?: { cause?: unknown }, 6 | ) { 7 | super(message, options) 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /packages/oauth/oauth-provider/src/lexicon/lexicon-data.ts: -------------------------------------------------------------------------------- 1 | import { LexiconDoc } from '@atproto/lexicon' 2 | 3 | export type LexiconData = { 4 | createdAt: Date 5 | updatedAt: Date 6 | lastSucceededAt: null | Date 7 | uri: null | string 8 | lexicon: null | LexiconDoc 9 | } 10 | -------------------------------------------------------------------------------- /packages/pds/src/actor-store/db/schema/repo-block.ts: -------------------------------------------------------------------------------- 1 | export interface RepoBlock { 2 | cid: string 3 | repoRev: string 4 | size: number 5 | content: Uint8Array 6 | } 7 | 8 | export const tableName = 'repo_block' 9 | 10 | export type PartialDB = { [tableName]: RepoBlock } 11 | -------------------------------------------------------------------------------- /packages/oauth/oauth-types/src/oauth-par-response.ts: -------------------------------------------------------------------------------- 1 | import { z } from 'zod' 2 | 3 | export const oauthParResponseSchema = z.object({ 4 | request_uri: z.string(), 5 | expires_in: z.number().int().positive(), 6 | }) 7 | 8 | export type OAuthParResponse = z.infer 9 | -------------------------------------------------------------------------------- /packages/repo/jest.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('jest').Config} */ 2 | module.exports = { 3 | displayName: 'Repo', 4 | transform: { '^.+\\.(t|j)s$': '@swc/jest' }, 5 | setupFiles: ['/../../jest.setup.ts'], 6 | moduleNameMapper: { '^(\\.\\.?\\/.+)\\.js$': ['$1.ts', '$1.js'] }, 7 | } 8 | -------------------------------------------------------------------------------- /lexicons/com/atproto/server/requestAccountDelete.json: -------------------------------------------------------------------------------- 1 | { 2 | "lexicon": 1, 3 | "id": "com.atproto.server.requestAccountDelete", 4 | "defs": { 5 | "main": { 6 | "type": "procedure", 7 | "description": "Initiate a user account deletion via email." 8 | } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /packages/bsync/jest.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('jest').Config} */ 2 | module.exports = { 3 | displayName: 'Bsync', 4 | transform: { '^.+\\.(t|j)s$': '@swc/jest' }, 5 | setupFiles: ['/../../jest.setup.ts'], 6 | moduleNameMapper: { '^(\\.\\.?\\/.+)\\.js$': ['$1.ts', '$1.js'] }, 7 | } 8 | -------------------------------------------------------------------------------- /packages/common/jest.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('jest').Config} */ 2 | module.exports = { 3 | displayName: 'Common', 4 | transform: { '^.+\\.(t|j)s$': '@swc/jest' }, 5 | setupFiles: ['/../../jest.setup.ts'], 6 | moduleNameMapper: { '^(\\.\\.?\\/.+)\\.js$': ['$1.ts', '$1.js'] }, 7 | } 8 | -------------------------------------------------------------------------------- /packages/crypto/jest.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('jest').Config} */ 2 | module.exports = { 3 | displayName: 'Crypto', 4 | transform: { '^.+\\.(t|j)s$': '@swc/jest' }, 5 | setupFiles: ['/../../jest.setup.ts'], 6 | moduleNameMapper: { '^(\\.\\.?\\/.+)\\.js$': ['$1.ts', '$1.js'] }, 7 | } 8 | -------------------------------------------------------------------------------- /packages/lexicon/jest.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('jest').Config} */ 2 | module.exports = { 3 | displayName: 'Lexicon', 4 | transform: { '^.+\\.ts$': '@swc/jest' }, 5 | setupFiles: ['/../../jest.setup.ts'], 6 | moduleNameMapper: { '^(\\.\\.?\\/.+)\\.js$': ['$1.ts', '$1.js'] }, 7 | } 8 | -------------------------------------------------------------------------------- /packages/pds/src/api/app/bsky/notification/index.ts: -------------------------------------------------------------------------------- 1 | import { AppContext } from '../../../../context' 2 | import { Server } from '../../../../lexicon' 3 | import registerPush from './registerPush' 4 | 5 | export default function (server: Server, ctx: AppContext) { 6 | registerPush(server, ctx) 7 | } 8 | -------------------------------------------------------------------------------- /packages/pds/src/api/com/atproto/moderation/index.ts: -------------------------------------------------------------------------------- 1 | import { AppContext } from '../../../../context' 2 | import { Server } from '../../../../lexicon' 3 | import createReport from './createReport' 4 | 5 | export default function (server: Server, ctx: AppContext) { 6 | createReport(server, ctx) 7 | } 8 | -------------------------------------------------------------------------------- /packages/syntax/jest.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('jest').Config} */ 2 | module.exports = { 3 | displayName: 'Syntax', 4 | transform: { '^.+\\.(t|j)s$': '@swc/jest' }, 5 | setupFiles: ['/../../jest.setup.ts'], 6 | moduleNameMapper: { '^(\\.\\.?\\/.+)\\.js$': ['$1.ts', '$1.js'] }, 7 | } 8 | -------------------------------------------------------------------------------- /packages/internal/did-resolver/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from '@atproto/did' 2 | 3 | export * from './did-cache-memory.js' 4 | export * from './did-cache.js' 5 | export * from './did-method.js' 6 | export * from './did-resolver-common.js' 7 | export * from './did-resolver.js' 8 | export * from './methods.js' 9 | -------------------------------------------------------------------------------- /packages/oauth/oauth-provider-frontend/src/util/format2FACode.ts: -------------------------------------------------------------------------------- 1 | export function format2FACode(value: string) { 2 | const normalized = value.toUpperCase().replace(/[^A-Z2-7]/g, '') 3 | if (normalized.length <= 5) return normalized 4 | return `${normalized.slice(0, 5)}-${normalized.slice(5, 10)}` 5 | } 6 | -------------------------------------------------------------------------------- /packages/oauth/oauth-provider/src/client/client-data.ts: -------------------------------------------------------------------------------- 1 | import { Jwks } from '@atproto/jwk' 2 | import { OAuthClientMetadata } from '@atproto/oauth-types' 3 | 4 | export type { OAuthClientMetadata } 5 | 6 | export type ClientData = { 7 | metadata: OAuthClientMetadata 8 | jwks?: Jwks 9 | } 10 | -------------------------------------------------------------------------------- /packages/oauth/oauth-provider/src/lib/util/error.ts: -------------------------------------------------------------------------------- 1 | import { ZodError } from 'zod' 2 | import { formatZodError } from './zod-error.js' 3 | 4 | export function formatError(err: unknown, prefix: string): string { 5 | if (err instanceof ZodError) return formatZodError(err, prefix) 6 | return prefix 7 | } 8 | -------------------------------------------------------------------------------- /packages/oauth/oauth-provider/src/lib/util/well-known.ts: -------------------------------------------------------------------------------- 1 | export function buildWellknownUrl(url: URL, name: string): URL { 2 | const path = 3 | url.pathname === '/' 4 | ? `/.well-known/${name}` 5 | : `${url.pathname.replace(/\/+$/, '')}/${name}` 6 | 7 | return new URL(path, url) 8 | } 9 | -------------------------------------------------------------------------------- /packages/pds/src/api/com/atproto/temp/index.ts: -------------------------------------------------------------------------------- 1 | import { AppContext } from '../../../../context' 2 | import { Server } from '../../../../lexicon' 3 | import checkSignupQueue from './checkSignupQueue' 4 | 5 | export default function (server: Server, ctx: AppContext) { 6 | checkSignupQueue(server, ctx) 7 | } 8 | -------------------------------------------------------------------------------- /packages/common-web/jest.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('jest').Config} */ 2 | module.exports = { 3 | displayName: 'Common Web', 4 | transform: { '^.+\\.(t|j)s$': '@swc/jest' }, 5 | setupFiles: ['/../../jest.setup.ts'], 6 | moduleNameMapper: { '^(\\.\\.?\\/.+)\\.js$': ['$1.ts', '$1.js'] }, 7 | } 8 | -------------------------------------------------------------------------------- /packages/oauth/oauth-client-expo/expo-module.config.json: -------------------------------------------------------------------------------- 1 | { 2 | "platforms": ["apple", "android", "web"], 3 | "apple": { 4 | "modules": ["ExpoAtprotoOAuthClientModule"] 5 | }, 6 | "android": { 7 | "modules": ["expo.modules.atprotooauthclient.ExpoAtprotoOAuthClientModule"] 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /packages/pds/src/actor-store/actor-store-resources.ts: -------------------------------------------------------------------------------- 1 | import { BlobStore } from '@atproto/repo' 2 | import { BackgroundQueue } from '../background' 3 | 4 | export type ActorStoreResources = { 5 | blobstore: (did: string) => BlobStore 6 | backgroundQueue: BackgroundQueue 7 | reservedKeyDir?: string 8 | } 9 | -------------------------------------------------------------------------------- /packages/bsky/src/data-plane/server/db/tables/tagged-suggestion.ts: -------------------------------------------------------------------------------- 1 | export const tableName = 'tagged_suggestion' 2 | 3 | export interface TaggedSuggestion { 4 | tag: string 5 | subject: string 6 | subjectType: string 7 | } 8 | 9 | export type PartialDB = { 10 | [tableName]: TaggedSuggestion 11 | } 12 | -------------------------------------------------------------------------------- /packages/lex-cli/src/types.ts: -------------------------------------------------------------------------------- 1 | export interface GeneratedFile { 2 | path: string 3 | content: string 4 | } 5 | 6 | export interface GeneratedAPI { 7 | files: GeneratedFile[] 8 | } 9 | 10 | export interface FileDiff { 11 | act: 'add' | 'mod' | 'del' 12 | path: string 13 | content?: string 14 | } 15 | -------------------------------------------------------------------------------- /packages/bsky/src/data-plane/server/db/tables/algo.ts: -------------------------------------------------------------------------------- 1 | export const whatsHotViewTableName = 'algo_whats_hot_view' 2 | 3 | export interface AlgoWhatsHotView { 4 | uri: string 5 | cid: string 6 | score: number 7 | } 8 | 9 | export type PartialDB = { 10 | [whatsHotViewTableName]: AlgoWhatsHotView 11 | } 12 | -------------------------------------------------------------------------------- /packages/bsky/src/data-plane/server/db/tables/bookmark.ts: -------------------------------------------------------------------------------- 1 | export interface Bookmark { 2 | creator: string 3 | key: string 4 | subjectUri: string 5 | subjectCid: string 6 | indexedAt: string 7 | } 8 | 9 | export const tableName = 'bookmark' 10 | 11 | export type PartialDB = { [tableName]: Bookmark } 12 | -------------------------------------------------------------------------------- /packages/lexicon-resolver/jest.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('jest').Config} */ 2 | module.exports = { 3 | displayName: 'Lexicon Resolver', 4 | transform: { '^.+\\.(t|j)s$': '@swc/jest' }, 5 | setupFiles: ['/../../jest.setup.ts'], 6 | moduleNameMapper: { '^(\\.\\.?\\/.+)\\.js$': ['$1.ts', '$1.js'] }, 7 | } 8 | -------------------------------------------------------------------------------- /packages/sync/jest.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('jest').Config} */ 2 | module.exports = { 3 | displayName: 'Sync', 4 | transform: { '^.+\\.ts$': '@swc/jest' }, 5 | testTimeout: 60000, 6 | setupFiles: ['/../../jest.setup.ts'], 7 | moduleNameMapper: { '^(\\.\\.?\\/.+)\\.js$': ['$1.ts', '$1.js'] }, 8 | } 9 | -------------------------------------------------------------------------------- /interop-test-files/syntax/datetime_parse_invalid.txt: -------------------------------------------------------------------------------- 1 | # superficial syntax parses ok, but are not valid datetimes for semantic reasons (eg, "month zero") 2 | 1985-00-12T23:20:50.123Z 3 | 1985-04-00T23:20:50.123Z 4 | 1985-13-12T23:20:50.123Z 5 | 1985-04-12T25:20:50.123Z 6 | 1985-04-12T23:99:50.123Z 7 | 1985-04-12T23:20:61.123Z 8 | -------------------------------------------------------------------------------- /lexicons/com/atproto/server/requestEmailConfirmation.json: -------------------------------------------------------------------------------- 1 | { 2 | "lexicon": 1, 3 | "id": "com.atproto.server.requestEmailConfirmation", 4 | "defs": { 5 | "main": { 6 | "type": "procedure", 7 | "description": "Request an email with a code to confirm ownership of email." 8 | } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /packages/oauth/oauth-client/src/errors/token-invalid-error.ts: -------------------------------------------------------------------------------- 1 | export class TokenInvalidError extends Error { 2 | constructor( 3 | public readonly sub: string, 4 | message = `The session for "${sub}" is invalid`, 5 | options?: { cause?: unknown }, 6 | ) { 7 | super(message, options) 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /packages/oauth/oauth-provider/src/router/error-handler.ts: -------------------------------------------------------------------------------- 1 | import type { IncomingMessage, ServerResponse } from 'node:http' 2 | 3 | export type ErrorHandler< 4 | Req extends IncomingMessage = IncomingMessage, 5 | Res extends ServerResponse = ServerResponse, 6 | > = (req: Req, res: Res, err: unknown, message: string) => void 7 | -------------------------------------------------------------------------------- /tsconfig/nodenext.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json.schemastore.org/tsconfig", 3 | "extends": "./base.json", 4 | "compilerOptions": { 5 | "lib": ["ES2023", "ScriptHost"], 6 | "types": ["node"], 7 | "module": "Node16", 8 | "target": "ES2023", 9 | "moduleResolution": "Node16" 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /packages/bsky/src/data-plane/server/db/tables/duplicate-record.ts: -------------------------------------------------------------------------------- 1 | export interface DuplicateRecord { 2 | uri: string 3 | cid: string 4 | duplicateOf: string 5 | indexedAt: string 6 | } 7 | 8 | export const tableName = 'duplicate_record' 9 | 10 | export type PartialDB = { 11 | [tableName]: DuplicateRecord 12 | } 13 | -------------------------------------------------------------------------------- /packages/bsky/src/data-plane/server/db/tables/label.ts: -------------------------------------------------------------------------------- 1 | export const tableName = 'label' 2 | 3 | export interface Label { 4 | src: string 5 | uri: string 6 | cid: string 7 | val: string 8 | neg: boolean 9 | cts: string 10 | exp: string | null 11 | } 12 | 13 | export type PartialDB = { [tableName]: Label } 14 | -------------------------------------------------------------------------------- /packages/bsky/src/data-plane/server/db/tables/post-gate.ts: -------------------------------------------------------------------------------- 1 | const tableName = 'post_gate' 2 | 3 | export interface Postgate { 4 | uri: string 5 | cid: string 6 | creator: string 7 | postUri: string 8 | createdAt: string 9 | indexedAt: string 10 | } 11 | 12 | export type PartialDB = { [tableName]: Postgate } 13 | -------------------------------------------------------------------------------- /packages/oauth/oauth-provider-ui/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | In dev, use `pnpm dev:ui` to start a mock ui server. This will serve the ui through Vite at `http://localhost:5173`. 2 | 3 | Use the following urls to live-preview the various ui pages: 4 | 5 | http://localhost:5173/authorization-page.html 6 | http://localhost:5173/error-page.html 7 | -------------------------------------------------------------------------------- /packages/pds/src/account-manager/db/schema/app-password.ts: -------------------------------------------------------------------------------- 1 | export interface AppPassword { 2 | did: string 3 | name: string 4 | passwordScrypt: string 5 | createdAt: string 6 | privileged: 0 | 1 7 | } 8 | 9 | export const tableName = 'app_password' 10 | 11 | export type PartialDB = { [tableName]: AppPassword } 12 | -------------------------------------------------------------------------------- /tsconfig/bundler.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json.schemastore.org/tsconfig", 3 | "compilerOptions": { 4 | "module": "ESNext", 5 | "moduleResolution": "Bundler", 6 | "allowImportingTsExtensions": true, 7 | "declaration": false, 8 | "declarationMap": false, 9 | "noEmit": true 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /interop-test-files/syntax/atidentifier_syntax_valid.txt: -------------------------------------------------------------------------------- 1 | 2 | # allows valid handles 3 | XX.LCS.MIT.EDU 4 | john.test 5 | jan.test 6 | a234567890123456789.test 7 | john2.test 8 | john-john.test 9 | 10 | # allows valid DIDs 11 | did:method:val 12 | did:method:VAL 13 | did:method:val123 14 | did:method:123 15 | did:method:val-two 16 | -------------------------------------------------------------------------------- /packages/bsky/src/data-plane/server/db/tables/thread-gate.ts: -------------------------------------------------------------------------------- 1 | const tableName = 'thread_gate' 2 | 3 | export interface ThreadGate { 4 | uri: string 5 | cid: string 6 | creator: string 7 | postUri: string 8 | createdAt: string 9 | indexedAt: string 10 | } 11 | 12 | export type PartialDB = { [tableName]: ThreadGate } 13 | -------------------------------------------------------------------------------- /packages/common/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from '@atproto/common-web' 2 | export * from './buffers' 3 | export * from './dates' 4 | export * from './env' 5 | export * from './fs' 6 | export * from './ipld' 7 | export * from './ipld-multi' 8 | export * from './logger' 9 | export * from './obfuscate' 10 | export * from './streams' 11 | -------------------------------------------------------------------------------- /packages/internal/fetch/src/fetch-error.ts: -------------------------------------------------------------------------------- 1 | export abstract class FetchError extends Error { 2 | constructor( 3 | public readonly statusCode: number, 4 | message?: string, 5 | options?: ErrorOptions, 6 | ) { 7 | super(message, options) 8 | } 9 | 10 | get expose() { 11 | return true 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /packages/oauth/oauth-client-browser-example/tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": [ 3 | "../../../tsconfig/browser.json", 4 | "../../../tsconfig/bundler.json" 5 | ], 6 | "compilerOptions": { 7 | "rootDir": "./src", 8 | "outDir": "./dist" 9 | }, 10 | "include": ["./src/**/*.ts", "./src/**/*.tsx"] 11 | } 12 | -------------------------------------------------------------------------------- /packages/oauth/oauth-provider-frontend/src/util/getAccountName.ts: -------------------------------------------------------------------------------- 1 | import { Account } from '#/api' 2 | import { sanitizeHandle } from '#/util/sanitizeHandle' 3 | 4 | export function getAccountName(account: Account): string { 5 | return ( 6 | account.name || sanitizeHandle(account.preferred_username) || account.sub 7 | ) 8 | } 9 | -------------------------------------------------------------------------------- /interop-test-files/syntax/tid_syntax_invalid.txt: -------------------------------------------------------------------------------- 1 | 2 | # not base32 3 | 3jzfcijpj2z21 4 | 0000000000000 5 | 6 | # too long/short 7 | 3jzfcijpj2z2aa 8 | 3jzfcijpj2z2 9 | 10 | # old dashes syntax not actually supported (TTTT-TTT-TTTT-CC) 11 | 3jzf-cij-pj2z-2a 12 | 13 | # high bit can't be high 14 | zzzzzzzzzzzzz 15 | kjzfcijpj2z2a 16 | -------------------------------------------------------------------------------- /packages/bsky/src/data-plane/server/db/tables/actor-state.ts: -------------------------------------------------------------------------------- 1 | export interface ActorState { 2 | did: string 3 | lastSeenNotifs: string 4 | priorityNotifs: boolean 5 | lastSeenPriorityNotifs: string | undefined 6 | } 7 | 8 | export const tableName = 'actor_state' 9 | 10 | export type PartialDB = { [tableName]: ActorState } 11 | -------------------------------------------------------------------------------- /packages/bsky/src/data-plane/server/db/tables/did-cache.ts: -------------------------------------------------------------------------------- 1 | import { DidDocument } from '@atproto/identity' 2 | 3 | export interface DidCache { 4 | did: string 5 | doc: DidDocument 6 | updatedAt: number 7 | } 8 | 9 | export const tableName = 'did_cache' 10 | 11 | export type PartialDB = { 12 | [tableName]: DidCache 13 | } 14 | -------------------------------------------------------------------------------- /packages/crypto/src/const.ts: -------------------------------------------------------------------------------- 1 | export const P256_DID_PREFIX = new Uint8Array([0x80, 0x24]) 2 | export const SECP256K1_DID_PREFIX = new Uint8Array([0xe7, 0x01]) 3 | export const BASE58_MULTIBASE_PREFIX = 'z' 4 | export const DID_KEY_PREFIX = 'did:key:' 5 | 6 | export const P256_JWT_ALG = 'ES256' 7 | export const SECP256K1_JWT_ALG = 'ES256K' 8 | -------------------------------------------------------------------------------- /packages/oauth/oauth-client-expo/src/index.ts: -------------------------------------------------------------------------------- 1 | import './polyfill' 2 | 3 | export * from '@atproto/oauth-client' 4 | 5 | export type { ExpoOAuthClientInterface } from './expo-oauth-client-interface' 6 | export type { ExpoOAuthClientOptions } from './expo-oauth-client-options' 7 | 8 | export { ExpoOAuthClient } from './expo-oauth-client' 9 | -------------------------------------------------------------------------------- /packages/oauth/oauth-client/src/errors/token-revoked-error.ts: -------------------------------------------------------------------------------- 1 | export class TokenRevokedError extends Error { 2 | constructor( 3 | public readonly sub: string, 4 | message = `The session for "${sub}" was successfully revoked`, 5 | options?: { cause?: unknown }, 6 | ) { 7 | super(message, options) 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /packages/oauth/oauth-provider-frontend/src/api/index.ts: -------------------------------------------------------------------------------- 1 | import { useMemo } from 'react' 2 | import { Api } from '#/api/api' 3 | 4 | export type * from '@atproto/oauth-provider-api' 5 | export * from '#/api/api' 6 | export * from '#/api/json-client' 7 | 8 | export function useApi() { 9 | return useMemo(() => new Api(), []) 10 | } 11 | -------------------------------------------------------------------------------- /packages/oauth/oauth-provider-frontend/src/components/forms/index.tsx: -------------------------------------------------------------------------------- 1 | export * from '#/components/forms/Fieldset' 2 | export * from '#/components/forms/Item' 3 | export * from '#/components/forms/Label' 4 | export * from '#/components/forms/Text' 5 | export * from '#/components/forms/Errors' 6 | export * from '#/components/forms/Checkbox' 7 | -------------------------------------------------------------------------------- /packages/bsky/src/data-plane/server/db/tables/feed-item.ts: -------------------------------------------------------------------------------- 1 | export const tableName = 'feed_item' 2 | 3 | export interface FeedItem { 4 | uri: string 5 | cid: string 6 | type: 'post' | 'repost' 7 | postUri: string 8 | originatorDid: string 9 | sortAt: string 10 | } 11 | 12 | export type PartialDB = { [tableName]: FeedItem } 13 | -------------------------------------------------------------------------------- /packages/oauth/oauth-client-browser-example/src/index.tsx: -------------------------------------------------------------------------------- 1 | import './index.css' 2 | 3 | import { StrictMode } from 'react' 4 | import { createRoot } from 'react-dom/client' 5 | import { App } from './_app.tsx' 6 | 7 | createRoot(document.getElementById('root')!).render( 8 | 9 | 10 | , 11 | ) 12 | -------------------------------------------------------------------------------- /packages/oauth/oauth-client-expo/src/expo-oauth-client.d.ts: -------------------------------------------------------------------------------- 1 | import { ExpoOAuthClientInterface } from './expo-oauth-client-interface' 2 | import { ExpoOAuthClientOptions } from './expo-oauth-client-options' 3 | 4 | export declare class ExpoOAuthClient implements ExpoOAuthClientInterface { 5 | constructor(options: ExpoOAuthClientOptions) 6 | } 7 | -------------------------------------------------------------------------------- /packages/pds/src/account-manager/db/schema/refresh-token.ts: -------------------------------------------------------------------------------- 1 | export interface RefreshToken { 2 | id: string 3 | did: string 4 | expiresAt: string 5 | appPasswordName: string | null 6 | nextId: string | null 7 | } 8 | 9 | export const tableName = 'refresh_token' 10 | 11 | export type PartialDB = { [tableName]: RefreshToken } 12 | -------------------------------------------------------------------------------- /packages/pds/src/actor-store/db/schema/account-pref.ts: -------------------------------------------------------------------------------- 1 | import { GeneratedAlways } from 'kysely' 2 | 3 | export interface AccountPref { 4 | id: GeneratedAlways 5 | name: string 6 | valueJson: string // json 7 | } 8 | 9 | export const tableName = 'account_pref' 10 | 11 | export type PartialDB = { [tableName]: AccountPref } 12 | -------------------------------------------------------------------------------- /packages/repo/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './block-map' 2 | export * from './cid-set' 3 | export * from './repo' 4 | export * from './mst' 5 | export * from './parse' 6 | export * from './storage' 7 | export * from './sync' 8 | export * from './types' 9 | export * from './data-diff' 10 | export * from './car' 11 | export * from './util' 12 | -------------------------------------------------------------------------------- /services/pds/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "plc-service", 3 | "private": true, 4 | "packageManager": "pnpm@8.15.9", 5 | "dependencies": { 6 | "@atproto/pds": "workspace:^", 7 | "@opentelemetry/instrumentation": "^0.45.0", 8 | "dd-trace": "^4.18.0", 9 | "opentelemetry-plugin-better-sqlite3": "^1.1.0" 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /packages/bsky/src/util/debug.ts: -------------------------------------------------------------------------------- 1 | export const debugCatch = any>(fn: Func) => { 2 | return async (...args: Parameters) => { 3 | try { 4 | return (await fn(...args)) as Awaited> 5 | } catch (err) { 6 | console.error(err) 7 | throw err 8 | } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /packages/bsync/src/db/migrations/provider.ts: -------------------------------------------------------------------------------- 1 | import { Migration, MigrationProvider } from 'kysely' 2 | 3 | export class DbMigrationProvider implements MigrationProvider { 4 | constructor(private migrations: Record) {} 5 | async getMigrations(): Promise> { 6 | return this.migrations 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /packages/oauth/oauth-provider-ui/src/locales/load.ts: -------------------------------------------------------------------------------- 1 | import { Messages } from '@lingui/core' 2 | 3 | // @NOTE run "pnpm run po:compile" to compile the messages from the PO files 4 | 5 | export async function loadMessages(locale: string): Promise { 6 | const { messages } = await import(`./${locale}/messages.ts`) 7 | return messages 8 | } 9 | -------------------------------------------------------------------------------- /packages/oauth/oauth-provider-ui/tsconfig.src.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": [ 3 | "../../../tsconfig/browser.json", 4 | "../../../tsconfig/bundler.json" 5 | ], 6 | "compilerOptions": { 7 | "rootDir": "src", 8 | "paths": { 9 | "#/*": ["./src/*"] 10 | } 11 | }, 12 | "include": ["src/**/*.ts", "src/**/*.tsx"] 13 | } 14 | -------------------------------------------------------------------------------- /packages/ozone/src/db/schema/job_cursor.ts: -------------------------------------------------------------------------------- 1 | import { Generated } from 'kysely' 2 | 3 | export const jobCursorTableName = 'job_cursor' 4 | 5 | export interface JobCursor { 6 | job: string 7 | cursor: string | null 8 | updatedAt: Generated 9 | } 10 | 11 | export type PartialDB = { 12 | [jobCursorTableName]: JobCursor 13 | } 14 | -------------------------------------------------------------------------------- /packages/pds/src/api/index.ts: -------------------------------------------------------------------------------- 1 | import { AppContext } from '../context' 2 | import { Server } from '../lexicon' 3 | import appBsky from './app/bsky' 4 | import comAtproto from './com/atproto' 5 | 6 | export default function (server: Server, ctx: AppContext) { 7 | comAtproto(server, ctx) 8 | appBsky(server, ctx) 9 | return server 10 | } 11 | -------------------------------------------------------------------------------- /packages/pds/src/util/debug.ts: -------------------------------------------------------------------------------- 1 | export const debugCatch = any>(fn: Func) => { 2 | return async (...args: Parameters) => { 3 | try { 4 | return (await fn(...args)) as Awaited> 5 | } catch (err) { 6 | console.error(err) 7 | throw err 8 | } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /packages/oauth/oauth-client-browser-example/src/lib/use-bsky-client.ts: -------------------------------------------------------------------------------- 1 | import { useMemo } from 'react' 2 | import { Agent } from '@atproto/api' 3 | import { useOAuthSession } from '../providers/OAuthProvider.tsx' 4 | 5 | export function useBskyClient() { 6 | const session = useOAuthSession() 7 | return useMemo(() => new Agent(session), [session]) 8 | } 9 | -------------------------------------------------------------------------------- /packages/oauth/oauth-provider-frontend/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | OAuth mock pages 7 | 8 | 9 | My Account 10 | 11 | 12 | -------------------------------------------------------------------------------- /packages/oauth/oauth-provider-frontend/tsconfig.src.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": [ 3 | "../../../tsconfig/browser.json", 4 | "../../../tsconfig/bundler.json" 5 | ], 6 | "compilerOptions": { 7 | "rootDir": "src", 8 | "paths": { 9 | "#/*": ["./src/*"] 10 | } 11 | }, 12 | "include": ["src/**/*.ts", "src/**/*.tsx"] 13 | } 14 | -------------------------------------------------------------------------------- /packages/bsky/src/data-plane/server/db/tables/notification-push-token.ts: -------------------------------------------------------------------------------- 1 | export const tableName = 'notification_push_token' 2 | 3 | export interface NotificationPushToken { 4 | did: string 5 | platform: 'ios' | 'android' | 'web' 6 | token: string 7 | appId: string 8 | } 9 | 10 | export type PartialDB = { [tableName]: NotificationPushToken } 11 | -------------------------------------------------------------------------------- /packages/oauth/oauth-provider-frontend/src/components/forms/Item.tsx: -------------------------------------------------------------------------------- 1 | import { clsx } from 'clsx' 2 | import { ReactNode } from 'react' 3 | 4 | export function Item({ 5 | children, 6 | className, 7 | }: { 8 | children: ReactNode 9 | className?: string 10 | }) { 11 | return
{children}
12 | } 13 | -------------------------------------------------------------------------------- /lexicons/com/atproto/identity/requestPlcOperationSignature.json: -------------------------------------------------------------------------------- 1 | { 2 | "lexicon": 1, 3 | "id": "com.atproto.identity.requestPlcOperationSignature", 4 | "defs": { 5 | "main": { 6 | "type": "procedure", 7 | "description": "Request an email with a code to in order to request a signed PLC operation. Requires Auth." 8 | } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /packages/bsync/src/db/schema/notif_item.ts: -------------------------------------------------------------------------------- 1 | import { Selectable } from 'kysely' 2 | 3 | export interface NotifItem { 4 | actorDid: string 5 | priority: boolean 6 | fromId: number 7 | } 8 | 9 | export type NotifItemEntry = Selectable 10 | 11 | export const tableName = 'notif_item' 12 | 13 | export type PartialDB = { [tableName]: NotifItem } 14 | -------------------------------------------------------------------------------- /packages/common/src/buffers.ts: -------------------------------------------------------------------------------- 1 | export function ui8ToBuffer(bytes: Uint8Array): Buffer { 2 | return Buffer.from(bytes.buffer, bytes.byteOffset, bytes.byteLength) 3 | } 4 | 5 | export function ui8ToArrayBuffer(bytes: Uint8Array): ArrayBuffer { 6 | return bytes.buffer.slice( 7 | bytes.byteOffset, 8 | bytes.byteLength + bytes.byteOffset, 9 | ) 10 | } 11 | -------------------------------------------------------------------------------- /packages/dev-env/src/env.ts: -------------------------------------------------------------------------------- 1 | // NOTE: this file should be imported first, particularly before `@atproto/common` (for logging), to ensure that environment variables are respected in library code 2 | import dotenv from 'dotenv' 3 | 4 | const env = process.env.ENV 5 | if (env) { 6 | dotenv.config({ path: `./.${env}.env` }) 7 | } else { 8 | dotenv.config() 9 | } 10 | -------------------------------------------------------------------------------- /packages/dev-infra/with-test-redis-and-db.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | # Example usage: 4 | # ./with-test-redis-and-db.sh psql postgresql://pg:password@localhost:5433/postgres -c 'select 1;' 5 | # ./with-test-redis-and-db.sh redis-cli -h localhost -p 6380 ping 6 | 7 | dir=$(dirname $0) 8 | . ${dir}/_common.sh 9 | 10 | SERVICES="db_test redis_test" main "$@" 11 | -------------------------------------------------------------------------------- /packages/identity/jest.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('jest').Config} */ 2 | module.exports = { 3 | displayName: 'Identity', 4 | transform: { '^.+\\.(t|j)s$': '@swc/jest' }, 5 | transformIgnorePatterns: ['/node_modules/.pnpm/(?!(get-port)@)'], 6 | setupFiles: ['/../../jest.setup.ts'], 7 | moduleNameMapper: { '^(\\.\\.?\\/.+)\\.js$': ['$1.ts', '$1.js'] }, 8 | } 9 | -------------------------------------------------------------------------------- /lexicons/tools/ozone/signature/defs.json: -------------------------------------------------------------------------------- 1 | { 2 | "lexicon": 1, 3 | "id": "tools.ozone.signature.defs", 4 | "defs": { 5 | "sigDetail": { 6 | "type": "object", 7 | "required": ["property", "value"], 8 | "properties": { 9 | "property": { "type": "string" }, 10 | "value": { "type": "string" } 11 | } 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /packages/api/jest.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('jest').Config} */ 2 | module.exports = { 3 | displayName: 'API', 4 | transform: { '^.+\\.ts$': '@swc/jest' }, 5 | testTimeout: 60000, 6 | setupFiles: ['/../../jest.setup.ts'], 7 | setupFilesAfterEnv: ['/jest.setup.ts'], 8 | moduleNameMapper: { '^(\\.\\.?\\/.+)\\.js$': ['$1.ts', '$1.js'] }, 9 | } 10 | -------------------------------------------------------------------------------- /packages/bsky/src/api/external.ts: -------------------------------------------------------------------------------- 1 | import { Router } from 'express' 2 | import { AppContext } from '../context' 3 | import * as kwsApi from './kws' 4 | 5 | export const createRouter = (ctx: AppContext): Router => { 6 | const router = Router() 7 | 8 | if (ctx.kwsClient) { 9 | router.use('/kws', kwsApi.createRouter(ctx)) 10 | } 11 | 12 | return router 13 | } 14 | -------------------------------------------------------------------------------- /packages/bsky/src/data-plane/server/db/tables/private-data.ts: -------------------------------------------------------------------------------- 1 | export interface PrivateData { 2 | actorDid: string 3 | namespace: string 4 | key: string 5 | // JSON-encoded 6 | payload: string 7 | indexedAt: string 8 | updatedAt: string 9 | } 10 | 11 | export const tableName = 'private_data' 12 | 13 | export type PartialDB = { [tableName]: PrivateData } 14 | -------------------------------------------------------------------------------- /packages/xrpc-server/jest.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('jest').Config} */ 2 | module.exports = { 3 | displayName: 'XRPC Server', 4 | transform: { '^.+\\.(j|t)s$': '@swc/jest' }, 5 | transformIgnorePatterns: ['/node_modules/.pnpm/(?!(get-port)@)'], 6 | setupFiles: ['/../../jest.setup.ts'], 7 | moduleNameMapper: { '^(\\.\\.?\\/.+)\\.js$': ['$1.ts', '$1.js'] }, 8 | } 9 | -------------------------------------------------------------------------------- /.changeset/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://unpkg.com/@changesets/config@2.3.1/schema.json", 3 | "changelog": ["@changesets/changelog-github", { "repo": "bluesky-social/atproto" }], 4 | "commit": false, 5 | "fixed": [], 6 | "linked": [], 7 | "access": "public", 8 | "baseBranch": "main", 9 | "updateInternalDependencies": "patch", 10 | "ignore": [] 11 | } 12 | -------------------------------------------------------------------------------- /lexicons/com/atproto/server/activateAccount.json: -------------------------------------------------------------------------------- 1 | { 2 | "lexicon": 1, 3 | "id": "com.atproto.server.activateAccount", 4 | "defs": { 5 | "main": { 6 | "type": "procedure", 7 | "description": "Activates a currently deactivated account. Used to finalize account migration after the account's repo is imported and identity is setup." 8 | } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /packages/bsync/src/db/schema/mute_item.ts: -------------------------------------------------------------------------------- 1 | import { Selectable } from 'kysely' 2 | 3 | export interface MuteItem { 4 | actorDid: string 5 | subject: string // did or aturi for list 6 | fromId: number 7 | } 8 | 9 | export type MuteItemEntry = Selectable 10 | 11 | export const tableName = 'mute_item' 12 | 13 | export type PartialDB = { [tableName]: MuteItem } 14 | -------------------------------------------------------------------------------- /packages/oauth/oauth-client-browser/src/index.ts: -------------------------------------------------------------------------------- 1 | import 'core-js/modules/esnext.symbol.async-dispose' 2 | import 'core-js/modules/esnext.symbol.dispose' 3 | 4 | export * from '@atproto/jwk-webcrypto' 5 | export * from '@atproto/oauth-client' 6 | 7 | export * from './browser-oauth-client.js' 8 | export * from './errors.js' 9 | export { buildLoopbackClientId } from './util.js' 10 | -------------------------------------------------------------------------------- /packages/oauth/oauth-provider/src/lib/http/index.ts: -------------------------------------------------------------------------------- 1 | export * from './accept.js' 2 | export * from './context.js' 3 | export * from './headers.js' 4 | export * from './middleware.js' 5 | export * from './parser.js' 6 | export * from './request.js' 7 | export * from './response.js' 8 | export * from './router.js' 9 | export * from './stream.js' 10 | export * from './types.js' 11 | -------------------------------------------------------------------------------- /packages/oauth/oauth-types/src/oauth-client-credentials-grant-token-request.ts: -------------------------------------------------------------------------------- 1 | import { z } from 'zod' 2 | 3 | export const oauthClientCredentialsGrantTokenRequestSchema = z.object({ 4 | grant_type: z.literal('client_credentials'), 5 | }) 6 | 7 | export type OAuthClientCredentialsGrantTokenRequest = z.infer< 8 | typeof oauthClientCredentialsGrantTokenRequestSchema 9 | > 10 | -------------------------------------------------------------------------------- /packages/ozone/src/db/schema/firehose_cursor.ts: -------------------------------------------------------------------------------- 1 | import { Generated } from 'kysely' 2 | 3 | export const firehoseCursorTableName = 'firehose_cursor' 4 | 5 | export interface FirehoseCursor { 6 | service: string 7 | cursor: number | null 8 | updatedAt: Generated 9 | } 10 | 11 | export type PartialDB = { 12 | [firehoseCursorTableName]: FirehoseCursor 13 | } 14 | -------------------------------------------------------------------------------- /packages/pds/src/actor-store/db/schema/blob.ts: -------------------------------------------------------------------------------- 1 | export interface Blob { 2 | cid: string 3 | mimeType: string 4 | size: number 5 | tempKey: string | null 6 | width: number | null 7 | height: number | null 8 | createdAt: string 9 | takedownRef: string | null 10 | } 11 | 12 | export const tableName = 'blob' 13 | 14 | export type PartialDB = { [tableName]: Blob } 15 | -------------------------------------------------------------------------------- /lexicons/com/atproto/repo/defs.json: -------------------------------------------------------------------------------- 1 | { 2 | "lexicon": 1, 3 | "id": "com.atproto.repo.defs", 4 | "defs": { 5 | "commitMeta": { 6 | "type": "object", 7 | "required": ["cid", "rev"], 8 | "properties": { 9 | "cid": { "type": "string", "format": "cid" }, 10 | "rev": { "type": "string", "format": "tid" } 11 | } 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /packages/oauth/oauth-client-browser-example/tailwind.config.mjs: -------------------------------------------------------------------------------- 1 | /** @type {import('tailwindcss').Config} */ 2 | export default { 3 | content: ['./src/**/*.{js,ts,jsx,tsx}'], 4 | theme: { 5 | extend: {}, 6 | }, 7 | plugins: [], 8 | // See rollup.config.js for classes used in the HTML template 9 | safelist: ['bg-slate-100', 'dark:bg-slate-800', 'min-h-screen'], 10 | } 11 | -------------------------------------------------------------------------------- /packages/pds/src/mailer/templates.ts: -------------------------------------------------------------------------------- 1 | export { default as resetPassword } from './templates/reset-password' 2 | export { default as deleteAccount } from './templates/delete-account' 3 | export { default as confirmEmail } from './templates/confirm-email' 4 | export { default as updateEmail } from './templates/update-email' 5 | export { default as plcOperation } from './templates/plc-operation' 6 | -------------------------------------------------------------------------------- /lexicons/chat/bsky/actor/deleteAccount.json: -------------------------------------------------------------------------------- 1 | { 2 | "lexicon": 1, 3 | "id": "chat.bsky.actor.deleteAccount", 4 | "defs": { 5 | "main": { 6 | "type": "procedure", 7 | "output": { 8 | "encoding": "application/json", 9 | "schema": { 10 | "type": "object", 11 | "properties": {} 12 | } 13 | } 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /packages/oauth/oauth-provider/src/router/middleware-options.ts: -------------------------------------------------------------------------------- 1 | import type { IncomingMessage, ServerResponse } from 'node:http' 2 | import type { ErrorHandler } from './error-handler.js' 3 | 4 | export type MiddlewareOptions< 5 | Req extends IncomingMessage = IncomingMessage, 6 | Res extends ServerResponse = ServerResponse, 7 | > = { 8 | onError?: ErrorHandler 9 | } 10 | -------------------------------------------------------------------------------- /packages/oauth/oauth-types/src/oauth-password-grant-token-request.ts: -------------------------------------------------------------------------------- 1 | import { z } from 'zod' 2 | 3 | export const oauthPasswordGrantTokenRequestSchema = z.object({ 4 | grant_type: z.literal('password'), 5 | username: z.string(), 6 | password: z.string(), 7 | }) 8 | 9 | export type OAuthPasswordGrantTokenRequest = z.infer< 10 | typeof oauthPasswordGrantTokenRequestSchema 11 | > 12 | -------------------------------------------------------------------------------- /packages/xrpc-server/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './auth' 2 | export * from './errors' 3 | export * from './rate-limiter' 4 | export * from './server' 5 | export * from './stream' 6 | export * from './types' 7 | 8 | export { 9 | ServerTimer, 10 | parseReqEncoding, 11 | parseReqNsid, 12 | serverTimingHeader, 13 | } from './util' 14 | export type { ServerTiming } from './util' 15 | -------------------------------------------------------------------------------- /packages/common-web/src/index.ts: -------------------------------------------------------------------------------- 1 | export * as check from './check' 2 | export * as util from './util' 3 | 4 | export * from './arrays' 5 | export * from './async' 6 | export * from './util' 7 | export * from './tid' 8 | export * from './ipld' 9 | export * from './retry' 10 | export * from './types' 11 | export * from './times' 12 | export * from './strings' 13 | export * from './did-doc' 14 | -------------------------------------------------------------------------------- /packages/oauth/oauth-provider/src/device/device-data.ts: -------------------------------------------------------------------------------- 1 | import { z } from 'zod' 2 | import { sessionIdSchema } from './session-id.js' 3 | 4 | export const deviceDataSchema = z.object({ 5 | sessionId: sessionIdSchema, 6 | lastSeenAt: z.date(), 7 | userAgent: z.string().nullable(), 8 | ipAddress: z.string(), 9 | }) 10 | 11 | export type DeviceData = z.infer 12 | -------------------------------------------------------------------------------- /packages/oauth/oauth-provider/src/errors/invalid-invite-code-error.ts: -------------------------------------------------------------------------------- 1 | import { InvalidRequestError } from './invalid-request-error' 2 | 3 | export class InvalidInviteCodeError extends InvalidRequestError { 4 | constructor(details?: string, cause?: unknown) { 5 | super( 6 | 'This invite code is invalid.' + (details ? ` ${details}` : ''), 7 | cause, 8 | ) 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /packages/oauth/oauth-types/src/oauth-authorization-request-uri.ts: -------------------------------------------------------------------------------- 1 | import { z } from 'zod' 2 | import { oauthRequestUriSchema } from './oauth-request-uri.js' 3 | 4 | export const oauthAuthorizationRequestUriSchema = z.object({ 5 | request_uri: oauthRequestUriSchema, 6 | }) 7 | 8 | export type OAuthAuthorizationRequestUri = z.infer< 9 | typeof oauthAuthorizationRequestUriSchema 10 | > 11 | -------------------------------------------------------------------------------- /packages/pds/src/actor-store/db/schema/record.ts: -------------------------------------------------------------------------------- 1 | // @NOTE also used by app-view (moderation) 2 | export interface Record { 3 | uri: string 4 | cid: string 5 | collection: string 6 | rkey: string 7 | repoRev: string 8 | indexedAt: string 9 | takedownRef: string | null 10 | } 11 | 12 | export const tableName = 'record' 13 | 14 | export type PartialDB = { [tableName]: Record } 15 | -------------------------------------------------------------------------------- /tsconfig/expo.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json.schemastore.org/tsconfig", 3 | "extends": ["./browser.json"], 4 | "compilerOptions": { 5 | "jsx": "react-native", 6 | "target": "ES2023", 7 | "module": "ESNext", 8 | "moduleResolution": "Bundler", 9 | "moduleDetection": "force", 10 | "esModuleInterop": true, 11 | 12 | "skipLibCheck": true 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /lexicons/com/atproto/repo/importRepo.json: -------------------------------------------------------------------------------- 1 | { 2 | "lexicon": 1, 3 | "id": "com.atproto.repo.importRepo", 4 | "defs": { 5 | "main": { 6 | "type": "procedure", 7 | "description": "Import a repo in the form of a CAR file. Requires Content-Length HTTP header to be set.", 8 | "input": { 9 | "encoding": "application/vnd.ipld.car" 10 | } 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /packages/bsky/src/data-plane/server/db/tables/profile-agg.ts: -------------------------------------------------------------------------------- 1 | import { Generated } from 'kysely' 2 | 3 | export const tableName = 'profile_agg' 4 | 5 | export interface ProfileAgg { 6 | did: string 7 | followersCount: Generated 8 | followsCount: Generated 9 | postsCount: Generated 10 | } 11 | 12 | export type PartialDB = { 13 | [tableName]: ProfileAgg 14 | } 15 | -------------------------------------------------------------------------------- /packages/oauth/oauth-provider-frontend/src/data/useHydrationData.ts: -------------------------------------------------------------------------------- 1 | import type { HydrationData } from '../hydration-data.d.ts' 2 | 3 | const hydrationData = window as typeof window & HydrationData['account-page'] 4 | 5 | export function useHydrationData( 6 | key: T, 7 | ): HydrationData['account-page'][T] { 8 | return hydrationData[key] 9 | } 10 | -------------------------------------------------------------------------------- /packages/oauth/oauth-provider-frontend/src/util/sanitizeHandle.ts: -------------------------------------------------------------------------------- 1 | export function isInvalidHandle(handle: string): boolean { 2 | return handle === 'handle.invalid' 3 | } 4 | 5 | export function sanitizeHandle(handle?: string): string | undefined { 6 | if (!handle) return undefined 7 | return isInvalidHandle(handle) 8 | ? '⚠Invalid Handle' 9 | : `@${handle.replace(/^@/, '')}` 10 | } 11 | -------------------------------------------------------------------------------- /packages/pds/src/api/app/bsky/index.ts: -------------------------------------------------------------------------------- 1 | import { AppContext } from '../../../context' 2 | import { Server } from '../../../lexicon' 3 | import actor from './actor' 4 | import feed from './feed' 5 | import notification from './notification' 6 | 7 | export default function (server: Server, ctx: AppContext) { 8 | actor(server, ctx) 9 | feed(server, ctx) 10 | notification(server, ctx) 11 | } 12 | -------------------------------------------------------------------------------- /packages/bsky/src/data-plane/server/db/tables/labeler.ts: -------------------------------------------------------------------------------- 1 | import { GeneratedAlways } from 'kysely' 2 | 3 | export const tableName = 'labeler' 4 | 5 | export interface Labeler { 6 | uri: string 7 | cid: string 8 | creator: string 9 | createdAt: string 10 | indexedAt: string 11 | sortAt: GeneratedAlways 12 | } 13 | 14 | export type PartialDB = { 15 | [tableName]: Labeler 16 | } 17 | -------------------------------------------------------------------------------- /packages/bsky/src/data-plane/server/db/tables/quote.ts: -------------------------------------------------------------------------------- 1 | import { GeneratedAlways } from 'kysely' 2 | 3 | const tableName = 'quote' 4 | 5 | export interface Quote { 6 | uri: string 7 | cid: string 8 | subject: string 9 | subjectCid: string 10 | createdAt: string 11 | indexedAt: string 12 | sortAt: GeneratedAlways 13 | } 14 | 15 | export type PartialDB = { [tableName]: Quote } 16 | -------------------------------------------------------------------------------- /packages/oauth/oauth-client-expo/src/expo-oauth-client-interface.ts: -------------------------------------------------------------------------------- 1 | import type { 2 | AuthorizeOptions, 3 | OAuthClient, 4 | OAuthSession, 5 | } from '@atproto/oauth-client' 6 | 7 | export interface ExpoOAuthClientInterface extends OAuthClient, Disposable { 8 | signIn(input: string, options?: AuthorizeOptions): Promise 9 | handleCallback(): Promise 10 | } 11 | -------------------------------------------------------------------------------- /packages/oauth/oauth-provider/src/client/client-info.ts: -------------------------------------------------------------------------------- 1 | export type ClientInfo = { 2 | /** 3 | * Defaults to `false` 4 | */ 5 | isFirstParty: boolean 6 | 7 | /** 8 | * Defaults to `true` if the client is isFirstParty, or if the client was 9 | * loaded from the store. (i.e. false in case of "loopback" & "discoverable" 10 | * clients) 11 | */ 12 | isTrusted: boolean 13 | } 14 | -------------------------------------------------------------------------------- /packages/ozone/src/api/chat/index.ts: -------------------------------------------------------------------------------- 1 | import { AppContext } from '../../context' 2 | import { Server } from '../../lexicon' 3 | import getActorMetadata from './getActorMetadata' 4 | import getMessageContext from './getMessageContext' 5 | 6 | export default function (server: Server, ctx: AppContext) { 7 | getActorMetadata(server, ctx) 8 | getMessageContext(server, ctx) 9 | return server 10 | } 11 | -------------------------------------------------------------------------------- /packages/pds/src/util/params.ts: -------------------------------------------------------------------------------- 1 | import { CID } from 'multiformats/cid' 2 | import { InvalidRequestError } from '@atproto/xrpc-server' 3 | 4 | export const parseCidParam = (cid: string): CID => { 5 | try { 6 | return CID.parse(cid) 7 | } catch (err) { 8 | if (err instanceof SyntaxError) { 9 | throw new InvalidRequestError('Invalid cid') 10 | } 11 | throw err 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /packages/bsky/jest.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('jest').Config} */ 2 | module.exports = { 3 | displayName: 'Bsky App View', 4 | transform: { '^.+\\.(t|j)s$': '@swc/jest' }, 5 | transformIgnorePatterns: ['/node_modules/.pnpm/(?!(get-port)@)'], 6 | testTimeout: 60000, 7 | setupFiles: ['/../../jest.setup.ts'], 8 | moduleNameMapper: { '^(\\.\\.?\\/.+)\\.js$': ['$1.ts', '$1.js'] }, 9 | } 10 | -------------------------------------------------------------------------------- /packages/bsky/src/data-plane/server/db/tables/activity-subscription.ts: -------------------------------------------------------------------------------- 1 | export const tableName = 'activity_subscription' 2 | export interface ActivitySubscription { 3 | creator: string 4 | subjectDid: string 5 | // key from the bsync stash. 6 | key: string 7 | indexedAt: string 8 | post: boolean 9 | reply: boolean 10 | } 11 | 12 | export type PartialDB = { [tableName]: ActivitySubscription } 13 | -------------------------------------------------------------------------------- /packages/internal/handle-resolver/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './handle-resolver-error.js' 2 | export * from './types.js' 3 | 4 | // Main Handle Resolvers strategies 5 | export * from './xrpc-handle-resolver.js' 6 | export * from './atproto-doh-handle-resolver.js' 7 | export * from './atproto-handle-resolver.js' 8 | 9 | // Handle Resolver Caching utility 10 | export * from './cached-handle-resolver.js' 11 | -------------------------------------------------------------------------------- /packages/internal/pipe/src/type.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Generic, potentially async, function. Parametrized for convenience reasons. 3 | */ 4 | export type Fn = ( 5 | ...args: A 6 | ) => O | PromiseLike 7 | 8 | /** 9 | * Single input, single output, potentially async transformer function. 10 | */ 11 | export type Transformer = (...args: [I]) => O | PromiseLike 12 | -------------------------------------------------------------------------------- /packages/oauth/oauth-provider-frontend/src/components/forms/Fieldset.tsx: -------------------------------------------------------------------------------- 1 | import { ReactNode } from 'react' 2 | 3 | export function Fieldset({ 4 | children, 5 | label, 6 | }: { 7 | children: ReactNode 8 | label: string 9 | }) { 10 | return ( 11 |
12 | {label} 13 | {children} 14 |
15 | ) 16 | } 17 | -------------------------------------------------------------------------------- /packages/ozone/src/db/schema/account_strike.ts: -------------------------------------------------------------------------------- 1 | export const accountStrikeTableName = 'account_strike' 2 | 3 | export interface AccountStrike { 4 | did: string // Primary key 5 | firstStrikeAt: string | null 6 | lastStrikeAt: string | null 7 | activeStrikeCount: number 8 | totalStrikeCount: number 9 | } 10 | 11 | export type PartialDB = { 12 | [accountStrikeTableName]: AccountStrike 13 | } 14 | -------------------------------------------------------------------------------- /packages/bsky/src/data-plane/server/db/tables/follow.ts: -------------------------------------------------------------------------------- 1 | import { GeneratedAlways } from 'kysely' 2 | 3 | export const tableName = 'follow' 4 | 5 | export interface Follow { 6 | uri: string 7 | cid: string 8 | creator: string 9 | subjectDid: string 10 | createdAt: string 11 | indexedAt: string 12 | sortAt: GeneratedAlways 13 | } 14 | 15 | export type PartialDB = { [tableName]: Follow } 16 | -------------------------------------------------------------------------------- /packages/crypto/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './const' 2 | export * from './did' 3 | export * from './multibase' 4 | export * from './random' 5 | export * from './sha' 6 | export * from './types' 7 | export * from './verify' 8 | export * from './utils' 9 | 10 | export * from './p256/keypair' 11 | export * from './p256/plugin' 12 | 13 | export * from './secp256k1/keypair' 14 | export * from './secp256k1/plugin' 15 | -------------------------------------------------------------------------------- /packages/oauth/oauth-provider/src/result/authorization-result-redirect.ts: -------------------------------------------------------------------------------- 1 | import { OAuthAuthorizationRequestParameters } from '@atproto/oauth-types' 2 | import { AuthorizationRedirectParameters } from './authorization-redirect-parameters.js' 3 | 4 | export type AuthorizationResultRedirect = { 5 | issuer: string 6 | parameters: OAuthAuthorizationRequestParameters 7 | redirect: AuthorizationRedirectParameters 8 | } 9 | -------------------------------------------------------------------------------- /packages/oauth/oauth-provider-frontend/src/util/upsert.ts: -------------------------------------------------------------------------------- 1 | export function upsert( 2 | arr: undefined | readonly T[], 3 | item: T, 4 | predicate: (value: T, index: number, obj: readonly T[]) => boolean, 5 | ): T[] { 6 | if (!arr) return [item] 7 | const idx = arr.findIndex(predicate) 8 | return idx === -1 9 | ? [...arr, item] 10 | : [...arr.slice(0, idx), item, ...arr.slice(idx + 1)] 11 | } 12 | -------------------------------------------------------------------------------- /packages/oauth/oauth-scopes/src/lib/resource-permission.ts: -------------------------------------------------------------------------------- 1 | import { ScopeStringFor } from './syntax.js' 2 | import { Matchable } from './util.js' 3 | 4 | /** 5 | * Interface destined to provide consistency across parsed permission scopes for 6 | * resources (blob, repo, etc.). 7 | */ 8 | export interface ResourcePermission extends Matchable { 9 | toString(): ScopeStringFor 10 | } 11 | -------------------------------------------------------------------------------- /packages/pds/src/account-manager/db/schema/account-device.ts: -------------------------------------------------------------------------------- 1 | import { DeviceId } from '@atproto/oauth-provider' 2 | import { DateISO } from '../../../db' 3 | 4 | export interface AccountDevice { 5 | did: string 6 | deviceId: DeviceId 7 | 8 | createdAt: DateISO 9 | updatedAt: DateISO 10 | } 11 | 12 | export const tableName = 'account_device' 13 | 14 | export type PartialDB = { [tableName]: AccountDevice } 15 | -------------------------------------------------------------------------------- /packages/bsky/src/data-plane/server/db/migrations/20230620T161134972Z-post-langs.ts: -------------------------------------------------------------------------------- 1 | import { Kysely } from 'kysely' 2 | 3 | export async function up(db: Kysely): Promise { 4 | await db.schema.alterTable('post').addColumn('langs', 'jsonb').execute() 5 | } 6 | 7 | export async function down(db: Kysely): Promise { 8 | await db.schema.alterTable('post').dropColumn('langs').execute() 9 | } 10 | -------------------------------------------------------------------------------- /packages/bsky/src/data-plane/server/db/tables/actor-block.ts: -------------------------------------------------------------------------------- 1 | import { GeneratedAlways } from 'kysely' 2 | 3 | export const tableName = 'actor_block' 4 | export interface ActorBlock { 5 | uri: string 6 | cid: string 7 | creator: string 8 | subjectDid: string 9 | createdAt: string 10 | indexedAt: string 11 | sortAt: GeneratedAlways 12 | } 13 | 14 | export type PartialDB = { [tableName]: ActorBlock } 15 | -------------------------------------------------------------------------------- /packages/oauth/oauth-provider-ui/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | OAuth mock pages 7 | 8 | 9 |
authorization-page 10 |
11 | error-page 12 | 13 | 14 | -------------------------------------------------------------------------------- /packages/oauth/oauth-types/src/oauth-endpoint-auth-method.ts: -------------------------------------------------------------------------------- 1 | import { z } from 'zod' 2 | 3 | export const oauthEndpointAuthMethod = z.enum([ 4 | 'client_secret_basic', 5 | 'client_secret_jwt', 6 | 'client_secret_post', 7 | 'none', 8 | 'private_key_jwt', 9 | 'self_signed_tls_client_auth', 10 | 'tls_client_auth', 11 | ]) 12 | 13 | export type OauthEndpointAuthMethod = z.infer 14 | -------------------------------------------------------------------------------- /packages/bsky/src/data-plane/server/db/migrations/20230920T213858047Z-add-tags-to-post.ts: -------------------------------------------------------------------------------- 1 | import { Kysely } from 'kysely' 2 | 3 | export async function up(db: Kysely): Promise { 4 | await db.schema.alterTable('post').addColumn('tags', 'jsonb').execute() 5 | } 6 | 7 | export async function down(db: Kysely): Promise { 8 | await db.schema.alterTable('post').dropColumn('tags').execute() 9 | } 10 | -------------------------------------------------------------------------------- /packages/bsky/src/data-plane/server/db/migrations/20250207T174822012Z-add-label-exp.ts: -------------------------------------------------------------------------------- 1 | import { Kysely } from 'kysely' 2 | 3 | export async function up(db: Kysely): Promise { 4 | await db.schema.alterTable('label').addColumn('exp', 'varchar').execute() 5 | } 6 | 7 | export async function down(db: Kysely): Promise { 8 | await db.schema.alterTable('label').dropColumn('exp').execute() 9 | } 10 | -------------------------------------------------------------------------------- /packages/bsky/src/data-plane/server/db/tables/list-block.ts: -------------------------------------------------------------------------------- 1 | import { GeneratedAlways } from 'kysely' 2 | 3 | export const tableName = 'list_block' 4 | 5 | export interface ListBlock { 6 | uri: string 7 | cid: string 8 | creator: string 9 | subjectUri: string 10 | createdAt: string 11 | indexedAt: string 12 | sortAt: GeneratedAlways 13 | } 14 | 15 | export type PartialDB = { [tableName]: ListBlock } 16 | -------------------------------------------------------------------------------- /packages/internal/simple-store-redis/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # @atproto-labs/simple-store-redis 2 | 3 | ## 0.0.1 4 | 5 | ### Patch Changes 6 | 7 | - [#4149](https://github.com/bluesky-social/atproto/pull/4149) [`8914f9abd`](https://github.com/bluesky-social/atproto/commit/8914f9abde2059c551d7e4c8d104227986098b82) Thanks [@matthieusieben](https://github.com/matthieusieben)! - Initial implementation of redis based `SimpleStore` implementation 8 | -------------------------------------------------------------------------------- /packages/bsky/src/api/com/atproto/temp/fetchLabels.ts: -------------------------------------------------------------------------------- 1 | import { InvalidRequestError } from '@atproto/xrpc-server' 2 | import { AppContext } from '../../../../context' 3 | import { Server } from '../../../../lexicon' 4 | 5 | export default function (server: Server, _ctx: AppContext) { 6 | server.com.atproto.temp.fetchLabels(async (_reqCtx) => { 7 | throw new InvalidRequestError('not implemented on dataplane') 8 | }) 9 | } 10 | -------------------------------------------------------------------------------- /packages/bsky/src/data-plane/server/db/migrations/20250528T221913281Z-add-record-tags.ts: -------------------------------------------------------------------------------- 1 | import { Kysely } from 'kysely' 2 | 3 | export async function up(db: Kysely): Promise { 4 | await db.schema.alterTable('record').addColumn('tags', 'jsonb').execute() 5 | } 6 | 7 | export async function down(db: Kysely): Promise { 8 | await db.schema.alterTable('record').dropColumn('tags').execute() 9 | } 10 | -------------------------------------------------------------------------------- /packages/oauth/oauth-client-browser-example/src/queries/use-get-token-info-query.ts: -------------------------------------------------------------------------------- 1 | import { useQuery } from '@tanstack/react-query' 2 | import { useOAuthSession } from '../providers/OAuthProvider.tsx' 3 | 4 | export function useGetTokenInfoQuery() { 5 | const session = useOAuthSession() 6 | return useQuery({ 7 | queryKey: ['tokenInfo', session.did], 8 | queryFn: async () => session.getTokenInfo(true), 9 | }) 10 | } 11 | -------------------------------------------------------------------------------- /packages/oauth/oauth-provider/src/lib/util/locale.ts: -------------------------------------------------------------------------------- 1 | import { z } from 'zod' 2 | 3 | export const localeSchema = z 4 | .string() 5 | .regex(/^[a-z]{2,3}(-[A-Z]{2})?$/, 'Invalid locale') 6 | export type Locale = z.infer 7 | 8 | export const multiLangStringSchema = z.record( 9 | localeSchema, 10 | z.string().optional(), 11 | ) 12 | export type MultiLangString = z.infer 13 | -------------------------------------------------------------------------------- /packages/ozone/jest.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('jest').Config} */ 2 | module.exports = { 3 | displayName: 'Ozone', 4 | transform: { '^.+\\.(t|j)s$': '@swc/jest' }, 5 | transformIgnorePatterns: [ 6 | `/node_modules/.pnpm/(?!(get-port|lande|toygrad)@)`, 7 | ], 8 | testTimeout: 60000, 9 | setupFiles: ['/../../jest.setup.ts'], 10 | moduleNameMapper: { '^(\\.\\.?\\/.+)\\.js$': ['$1.ts', '$1.js'] }, 11 | } 12 | -------------------------------------------------------------------------------- /packages/ozone/src/communication-service/util.ts: -------------------------------------------------------------------------------- 1 | // Postgresql will throw a specific error code with the constraint when trying to create a template with duplicate name 2 | // see https://www.postgresql.org/docs/current/errcodes-appendix.html 3 | export const isDuplicateTemplateNameError = (err: any) => { 4 | return ( 5 | err?.['code'] === '23505' && 6 | err?.['constraint'] === 'communication_template_unique_name' 7 | ) 8 | } 9 | -------------------------------------------------------------------------------- /packages/oauth/oauth-client-browser/src/errors.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Special error class destined to be thrown when the login process was 3 | * performed in a popup and should be continued in the parent/initiating window. 4 | */ 5 | export class LoginContinuedInParentWindowError extends Error { 6 | code = 'LOGIN_CONTINUED_IN_PARENT_WINDOW' 7 | constructor() { 8 | super('Login complete, please close the popup window.') 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /packages/ozone/src/scheduled-action/types.ts: -------------------------------------------------------------------------------- 1 | import { ScheduledActionType } from '../api/util' 2 | 3 | export type ExecutionSchedule = 4 | | { 5 | executeAt: Date 6 | } 7 | | { 8 | executeAfter: Date 9 | executeUntil?: Date 10 | } 11 | 12 | export type SchedulingParams = { 13 | action: ScheduledActionType 14 | eventData: unknown 15 | did: string 16 | createdBy: string 17 | } & ExecutionSchedule 18 | -------------------------------------------------------------------------------- /packages/bsky/src/data-plane/server/db/tables/record.ts: -------------------------------------------------------------------------------- 1 | import { ColumnType } from 'kysely' 2 | 3 | export interface Record { 4 | uri: string 5 | cid: string 6 | did: string 7 | json: string 8 | indexedAt: string 9 | takedownRef: string | null 10 | tags: ColumnType | null 11 | } 12 | 13 | export const tableName = 'record' 14 | 15 | export type PartialDB = { [tableName]: Record } 16 | -------------------------------------------------------------------------------- /packages/bsky/src/data-plane/server/db/tables/starter-pack.ts: -------------------------------------------------------------------------------- 1 | import { GeneratedAlways } from 'kysely' 2 | 3 | export const tableName = 'starter_pack' 4 | 5 | export interface StarterPack { 6 | uri: string 7 | cid: string 8 | creator: string 9 | name: string 10 | createdAt: string 11 | indexedAt: string 12 | sortAt: GeneratedAlways 13 | } 14 | 15 | export type PartialDB = { 16 | [tableName]: StarterPack 17 | } 18 | -------------------------------------------------------------------------------- /packages/oauth/oauth-client-browser/src/indexed-db/README.md: -------------------------------------------------------------------------------- 1 | # IndexedDB utilities 2 | 3 | This is a small wrapper around the IndexedDB API that provides a simple way to 4 | store and retrieve data from an IndexedDB database. 5 | 6 | This _could_ be used as a standalone library, but the Bluesky dev team does not 7 | want to maintain it as such. As it is currently only used by the 8 | `@atproto/oauth-client-browser` package, it is included here. 9 | -------------------------------------------------------------------------------- /packages/bsky/src/data-plane/server/db/tables/list-item.ts: -------------------------------------------------------------------------------- 1 | import { GeneratedAlways } from 'kysely' 2 | 3 | export const tableName = 'list_item' 4 | 5 | export interface ListItem { 6 | uri: string 7 | cid: string 8 | creator: string 9 | subjectDid: string 10 | listUri: string 11 | createdAt: string 12 | indexedAt: string 13 | sortAt: GeneratedAlways 14 | } 15 | 16 | export type PartialDB = { [tableName]: ListItem } 17 | -------------------------------------------------------------------------------- /packages/oauth/oauth-provider/src/lib/util/ui8.ts: -------------------------------------------------------------------------------- 1 | export function parseUi8Hex(v: string) { 2 | return asUi8(parseInt(v, 16)) 3 | } 4 | 5 | export function parseUi8Dec(v: string) { 6 | return asUi8(parseInt(v, 10)) 7 | } 8 | 9 | export function asUi8(v: number) { 10 | if (v >= 0 && v <= 255 && Number.isInteger(v)) return v 11 | throw new TypeError( 12 | `Invalid value "${v}" (expected an integer between 0 and 255)`, 13 | ) 14 | } 15 | -------------------------------------------------------------------------------- /lexicons/com/atproto/repo/strongRef.json: -------------------------------------------------------------------------------- 1 | { 2 | "lexicon": 1, 3 | "id": "com.atproto.repo.strongRef", 4 | "description": "A URI with a content-hash fingerprint.", 5 | "defs": { 6 | "main": { 7 | "type": "object", 8 | "required": ["uri", "cid"], 9 | "properties": { 10 | "uri": { "type": "string", "format": "at-uri" }, 11 | "cid": { "type": "string", "format": "cid" } 12 | } 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /packages/bsky/src/data-plane/server/db/tables/notification.ts: -------------------------------------------------------------------------------- 1 | import { Generated } from 'kysely' 2 | 3 | export const tableName = 'notification' 4 | 5 | export interface Notification { 6 | id: Generated 7 | did: string 8 | recordUri: string 9 | recordCid: string 10 | author: string 11 | reason: string 12 | reasonSubject: string | null 13 | sortAt: string 14 | } 15 | 16 | export type PartialDB = { [tableName]: Notification } 17 | -------------------------------------------------------------------------------- /packages/ozone/src/image-invalidator.ts: -------------------------------------------------------------------------------- 1 | // Invalidation is a general interface for propagating an image blob 2 | // takedown through any caches where a representation of it may be stored. 3 | // @NOTE this does not remove the blob from storage: just invalidates it from caches. 4 | // @NOTE keep in sync with same interface in aws/src/cloudfront.ts 5 | export interface ImageInvalidator { 6 | invalidate(subject: string, paths: string[]): Promise 7 | } 8 | -------------------------------------------------------------------------------- /packages/pds/src/account-manager/db/schema/account.ts: -------------------------------------------------------------------------------- 1 | import { Generated, Selectable } from 'kysely' 2 | 3 | export interface Account { 4 | did: string 5 | email: string 6 | passwordScrypt: string 7 | emailConfirmedAt: string | null 8 | invitesDisabled: Generated<0 | 1> 9 | } 10 | 11 | export type AccountEntry = Selectable 12 | 13 | export const tableName = 'account' 14 | 15 | export type PartialDB = { [tableName]: Account } 16 | -------------------------------------------------------------------------------- /packages/bsky/src/data-plane/server/db/tables/post-agg.ts: -------------------------------------------------------------------------------- 1 | import { Generated } from 'kysely' 2 | 3 | export const tableName = 'post_agg' 4 | 5 | export interface PostAgg { 6 | uri: string 7 | likeCount: Generated 8 | replyCount: Generated 9 | repostCount: Generated 10 | quoteCount: Generated 11 | bookmarkCount: Generated 12 | } 13 | 14 | export type PartialDB = { 15 | [tableName]: PostAgg 16 | } 17 | -------------------------------------------------------------------------------- /packages/crypto/src/p256/plugin.ts: -------------------------------------------------------------------------------- 1 | import { P256_DID_PREFIX, P256_JWT_ALG } from '../const' 2 | import { DidKeyPlugin } from '../types' 3 | import { compressPubkey, decompressPubkey } from './encoding' 4 | import { verifyDidSig } from './operations' 5 | 6 | export const p256Plugin: DidKeyPlugin = { 7 | prefix: P256_DID_PREFIX, 8 | jwtAlg: P256_JWT_ALG, 9 | verifySignature: verifyDidSig, 10 | 11 | compressPubkey, 12 | decompressPubkey, 13 | } 14 | -------------------------------------------------------------------------------- /packages/pds/src/account-manager/db/schema/actor.ts: -------------------------------------------------------------------------------- 1 | import { Selectable } from 'kysely' 2 | 3 | export interface Actor { 4 | did: string 5 | handle: string | null 6 | createdAt: string 7 | takedownRef: string | null 8 | deactivatedAt: string | null 9 | deleteAfter: string | null 10 | } 11 | 12 | export type ActorEntry = Selectable 13 | 14 | export const tableName = 'actor' 15 | 16 | export type PartialDB = { [tableName]: Actor } 17 | -------------------------------------------------------------------------------- /packages/xrpc/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './client' 2 | export * from './fetch-handler' 3 | export * from './types' 4 | export * from './util' 5 | export * from './xrpc-client' 6 | 7 | /* eslint-disable import/no-deprecated */ 8 | import { Client } from './client' 9 | /** @deprecated create a local {@link XrpcClient} instance instead */ 10 | const defaultInst = new Client() 11 | export default defaultInst 12 | /* eslint-enable import/no-deprecated */ 13 | -------------------------------------------------------------------------------- /packages/oauth/oauth-types/src/oauth-grant-type.ts: -------------------------------------------------------------------------------- 1 | import { z } from 'zod' 2 | 3 | export const oauthGrantTypeSchema = z.enum([ 4 | 'authorization_code', 5 | 'implicit', 6 | 'refresh_token', 7 | 'password', // Not part of OAuth 2.1 8 | 'client_credentials', 9 | 'urn:ietf:params:oauth:grant-type:jwt-bearer', 10 | 'urn:ietf:params:oauth:grant-type:saml2-bearer', 11 | ]) 12 | 13 | export type OAuthGrantType = z.infer 14 | -------------------------------------------------------------------------------- /packages/oauth/oauth-types/src/oauth-token-type.ts: -------------------------------------------------------------------------------- 1 | import { z } from 'zod' 2 | 3 | // Case insensitive input, normalized output 4 | export const oauthTokenTypeSchema = z.union([ 5 | z 6 | .string() 7 | .regex(/^DPoP$/i) 8 | .transform(() => 'DPoP' as const), 9 | z 10 | .string() 11 | .regex(/^Bearer$/i) 12 | .transform(() => 'Bearer' as const), 13 | ]) 14 | 15 | export type OAuthTokenType = z.infer 16 | -------------------------------------------------------------------------------- /packages/bsky/src/data-plane/server/db/migrations/20230808T172902639Z-repo-rev.ts: -------------------------------------------------------------------------------- 1 | import { Kysely } from 'kysely' 2 | 3 | export async function up(db: Kysely): Promise { 4 | await db.schema 5 | .alterTable('actor_sync') 6 | .addColumn('repoRev', 'varchar') 7 | .execute() 8 | } 9 | 10 | export async function down(db: Kysely): Promise { 11 | await db.schema.alterTable('actor_sync').dropColumn('repoRev').execute() 12 | } 13 | -------------------------------------------------------------------------------- /packages/bsky/src/data-plane/server/db/tables/view-param.ts: -------------------------------------------------------------------------------- 1 | // @NOTE postgres-only 2 | export const tableName = 'view_param' 3 | 4 | // materialized views are difficult to change, 5 | // so we parameterize them at runtime with contents of this table. 6 | // its contents are set in migrations, available param names are static. 7 | export interface ViewParam { 8 | name: string 9 | value: string 10 | } 11 | 12 | export type PartialDB = { [tableName]: ViewParam } 13 | -------------------------------------------------------------------------------- /packages/oauth/oauth-types/src/oidc-claims-properties.ts: -------------------------------------------------------------------------------- 1 | import { z } from 'zod' 2 | 3 | const oidcClaimsValueSchema = z.union([z.string(), z.number(), z.boolean()]) 4 | 5 | export const oidcClaimsPropertiesSchema = z.object({ 6 | essential: z.boolean().optional(), 7 | value: oidcClaimsValueSchema.optional(), 8 | values: z.array(oidcClaimsValueSchema).optional(), 9 | }) 10 | 11 | export type OidcClaimsProperties = z.infer 12 | -------------------------------------------------------------------------------- /packages/pds/src/account-manager/db/schema/email-token.ts: -------------------------------------------------------------------------------- 1 | export type EmailTokenPurpose = 2 | | 'confirm_email' 3 | | 'update_email' 4 | | 'reset_password' 5 | | 'delete_account' 6 | | 'plc_operation' 7 | 8 | export interface EmailToken { 9 | purpose: EmailTokenPurpose 10 | did: string 11 | token: string 12 | requestedAt: string 13 | } 14 | 15 | export const tableName = 'email_token' 16 | 17 | export type PartialDB = { [tableName]: EmailToken } 18 | -------------------------------------------------------------------------------- /packages/pds/src/account-manager/db/schema/used-refresh-token.ts: -------------------------------------------------------------------------------- 1 | import { Selectable } from 'kysely' 2 | import { RefreshToken } from '@atproto/oauth-provider' 3 | 4 | export interface UsedRefreshToken { 5 | tokenId: number 6 | refreshToken: RefreshToken 7 | } 8 | 9 | export type UsedRefreshTokenEntry = Selectable 10 | 11 | export const tableName = 'used_refresh_token' 12 | 13 | export type PartialDB = { [tableName]: UsedRefreshToken } 14 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | dist 2 | node_modules 3 | 4 | # buf 5 | packages/bsky/src/proto 6 | packages/bsync/src/proto 7 | 8 | # codegen 9 | packages/api/src/client 10 | packages/lexicon-resolver/src/client 11 | packages/bsky/src/lexicon 12 | packages/pds/src/lexicon 13 | packages/ozone/src/lexicon 14 | 15 | # others 16 | packages/oauth/*/src/locales/*/messages.ts 17 | packages/oauth/oauth-provider-frontend/src/routeTree.gen.ts 18 | packages/oauth/oauth-client-expo/android/build 19 | -------------------------------------------------------------------------------- /packages/bsync/src/db/types.ts: -------------------------------------------------------------------------------- 1 | import { DynamicModule, RawBuilder, SelectQueryBuilder } from 'kysely' 2 | import { Pool as PgPool } from 'pg' 3 | 4 | export type DbRef = RawBuilder | ReturnType 5 | 6 | export type AnyQb = SelectQueryBuilder 7 | 8 | export type PgOptions = { 9 | url: string 10 | pool?: PgPool 11 | schema?: string 12 | poolSize?: number 13 | poolMaxUses?: number 14 | poolIdleTimeoutMs?: number 15 | } 16 | -------------------------------------------------------------------------------- /packages/oauth/oauth-provider/src/errors/invalid-dpop-proof-error.ts: -------------------------------------------------------------------------------- 1 | import { WWWAuthenticateError } from './www-authenticate-error.js' 2 | 3 | export class InvalidDpopProofError extends WWWAuthenticateError { 4 | constructor(error_description: string, cause?: unknown) { 5 | const error = 'invalid_dpop_proof' 6 | super( 7 | error, 8 | error_description, 9 | { DPoP: { error, error_description } }, 10 | cause, 11 | ) 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /packages/oauth/oauth-types/src/oauth-refresh-token-grant-token-request.ts: -------------------------------------------------------------------------------- 1 | import { z } from 'zod' 2 | import { oauthRefreshTokenSchema } from './oauth-refresh-token.js' 3 | 4 | export const oauthRefreshTokenGrantTokenRequestSchema = z.object({ 5 | grant_type: z.literal('refresh_token'), 6 | refresh_token: oauthRefreshTokenSchema, 7 | }) 8 | 9 | export type OAuthRefreshTokenGrantTokenRequest = z.infer< 10 | typeof oauthRefreshTokenGrantTokenRequestSchema 11 | > 12 | -------------------------------------------------------------------------------- /packages/ozone/src/db/migrations/20240903T205730722Z-add-template-lang.ts: -------------------------------------------------------------------------------- 1 | import { Kysely } from 'kysely' 2 | 3 | export async function up(db: Kysely): Promise { 4 | await db.schema 5 | .alterTable('communication_template') 6 | .addColumn('lang', 'varchar') 7 | .execute() 8 | } 9 | 10 | export async function down(db: Kysely): Promise { 11 | await db.schema.alterTable('moderation_event').dropColumn('lang').execute() 12 | } 13 | -------------------------------------------------------------------------------- /packages/pds/src/util/compression.ts: -------------------------------------------------------------------------------- 1 | import compression from 'compression' 2 | import express from 'express' 3 | 4 | export default function () { 5 | return compression({ 6 | filter, 7 | }) 8 | } 9 | 10 | function filter(_req: express.Request, res: express.Response) { 11 | const contentType = res.getHeader('Content-type') 12 | if (contentType === 'application/vnd.ipld.car') { 13 | return true 14 | } 15 | return compression.filter(_req, res) 16 | } 17 | -------------------------------------------------------------------------------- /packages/bsky/src/data-plane/server/db/tables/like.ts: -------------------------------------------------------------------------------- 1 | import { GeneratedAlways } from 'kysely' 2 | 3 | const tableName = 'like' 4 | 5 | export interface Like { 6 | uri: string 7 | cid: string 8 | creator: string 9 | subject: string 10 | subjectCid: string 11 | via: string | null 12 | viaCid: string | null 13 | createdAt: string 14 | indexedAt: string 15 | sortAt: GeneratedAlways 16 | } 17 | 18 | export type PartialDB = { [tableName]: Like } 19 | -------------------------------------------------------------------------------- /packages/oauth/oauth-provider/src/customization/links.ts: -------------------------------------------------------------------------------- 1 | import { z } from 'zod' 2 | import { isLinkRel } from '../lib/html/build-document.js' 3 | import { multiLangStringSchema } from '../lib/util/locale.js' 4 | 5 | export const linksSchema = z.object({ 6 | title: z.union([z.string(), multiLangStringSchema]), 7 | href: z.string().url(), 8 | rel: z.string().refine(isLinkRel, 'Invalid link rel').optional(), 9 | }) 10 | export type Links = z.infer 11 | -------------------------------------------------------------------------------- /packages/sync/src/util.ts: -------------------------------------------------------------------------------- 1 | import { 2 | RepoEvent, 3 | isAccount, 4 | isCommit, 5 | isIdentity, 6 | isSync, 7 | } from './firehose/lexicons' 8 | 9 | export const didAndSeqForEvt = ( 10 | evt: RepoEvent, 11 | ): { did: string; seq: number } | undefined => { 12 | if (isCommit(evt)) return { seq: evt.seq, did: evt.repo } 13 | else if (isAccount(evt) || isIdentity(evt) || isSync(evt)) 14 | return { seq: evt.seq, did: evt.did } 15 | return undefined 16 | } 17 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "trailingComma": "all", 3 | "tabWidth": 2, 4 | "semi": false, 5 | "singleQuote": true, 6 | "plugins": ["prettier-plugin-tailwindcss"], 7 | "overrides": [ 8 | { 9 | "files": "*.hbs", 10 | "options": { 11 | "singleQuote": false 12 | } 13 | }, 14 | { 15 | "files": [".eslintrc"], 16 | "options": { 17 | "parser": "json", 18 | "trailingComma": "none" 19 | } 20 | } 21 | ] 22 | } 23 | -------------------------------------------------------------------------------- /packages/aws/src/util.ts: -------------------------------------------------------------------------------- 1 | import { allFulfilled } from '@atproto/common' 2 | import { ImageInvalidator } from './types' 3 | 4 | export class MultiImageInvalidator implements ImageInvalidator { 5 | constructor(public invalidators: ImageInvalidator[]) {} 6 | async invalidate(subject: string, paths: string[]) { 7 | await allFulfilled( 8 | this.invalidators.map((invalidator) => 9 | invalidator.invalidate(subject, paths), 10 | ), 11 | ) 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /packages/ozone/src/config/secrets.ts: -------------------------------------------------------------------------------- 1 | import assert from 'node:assert' 2 | import { OzoneEnvironment } from './env' 3 | 4 | export const envToSecrets = (env: OzoneEnvironment): OzoneSecrets => { 5 | assert(env.adminPassword) 6 | assert(env.signingKeyHex) 7 | 8 | return { 9 | adminPassword: env.adminPassword, 10 | signingKeyHex: env.signingKeyHex, 11 | } 12 | } 13 | 14 | export type OzoneSecrets = { 15 | adminPassword: string 16 | signingKeyHex: string 17 | } 18 | -------------------------------------------------------------------------------- /packages/pds/src/actor-store/preference/util.ts: -------------------------------------------------------------------------------- 1 | const FULL_ACCESS_ONLY_PREFS = new Set([ 2 | 'app.bsky.actor.defs#personalDetailsPref', 3 | ]) 4 | 5 | export type PrefAllowedOptions = { 6 | hasAccessFull?: boolean 7 | } 8 | 9 | export function prefAllowed( 10 | prefType: string, 11 | options?: PrefAllowedOptions, 12 | ): boolean { 13 | if (options?.hasAccessFull === true) { 14 | return true 15 | } 16 | 17 | return !FULL_ACCESS_ONLY_PREFS.has(prefType) 18 | } 19 | -------------------------------------------------------------------------------- /packages/bsky/src/data-plane/server/db/migrations/20240530T170337073Z-account-deactivation.ts: -------------------------------------------------------------------------------- 1 | import { Kysely } from 'kysely' 2 | 3 | export async function up(db: Kysely): Promise { 4 | await db.schema 5 | .alterTable('actor') 6 | .addColumn('upstreamStatus', 'varchar') 7 | .execute() 8 | } 9 | 10 | export async function down(db: Kysely): Promise { 11 | await db.schema.alterTable('actor').dropColumn('upstreamStatus').execute() 12 | } 13 | -------------------------------------------------------------------------------- /packages/crypto/src/secp256k1/plugin.ts: -------------------------------------------------------------------------------- 1 | import { SECP256K1_DID_PREFIX, SECP256K1_JWT_ALG } from '../const' 2 | import { DidKeyPlugin } from '../types' 3 | import { compressPubkey, decompressPubkey } from './encoding' 4 | import { verifyDidSig } from './operations' 5 | 6 | export const secp256k1Plugin: DidKeyPlugin = { 7 | prefix: SECP256K1_DID_PREFIX, 8 | jwtAlg: SECP256K1_JWT_ALG, 9 | verifySignature: verifyDidSig, 10 | 11 | compressPubkey, 12 | decompressPubkey, 13 | } 14 | -------------------------------------------------------------------------------- /packages/pds/tests/seeds/likes.ts: -------------------------------------------------------------------------------- 1 | import { SeedClient } from '@atproto/dev-env' 2 | import basicSeed from './basic' 3 | 4 | export default async (sc: SeedClient) => { 5 | await basicSeed(sc) 6 | await sc.createAccount('eve', { 7 | email: 'eve@test.com', 8 | handle: 'eve.test', 9 | password: 'eve-pass', 10 | }) 11 | await sc.like(sc.dids.eve, sc.posts[sc.dids.alice][1].ref) 12 | await sc.like(sc.dids.carol, sc.replies[sc.dids.bob][0].ref) 13 | return sc 14 | } 15 | -------------------------------------------------------------------------------- /packages/bsky/src/data-plane/server/db/tables/repost.ts: -------------------------------------------------------------------------------- 1 | import { GeneratedAlways } from 'kysely' 2 | 3 | export const tableName = 'repost' 4 | 5 | export interface Repost { 6 | uri: string 7 | cid: string 8 | creator: string 9 | subject: string 10 | subjectCid: string 11 | via: string | null 12 | viaCid: string | null 13 | createdAt: string 14 | indexedAt: string 15 | sortAt: GeneratedAlways 16 | } 17 | 18 | export type PartialDB = { [tableName]: Repost } 19 | -------------------------------------------------------------------------------- /packages/internal/did-resolver/src/did-method.ts: -------------------------------------------------------------------------------- 1 | import { Did, DidDocument } from '@atproto/did' 2 | 3 | export type ResolveDidOptions = { 4 | signal?: AbortSignal 5 | noCache?: boolean 6 | } 7 | 8 | export interface DidMethod { 9 | resolve: ( 10 | did: Did, 11 | options?: ResolveDidOptions, 12 | ) => DidDocument | PromiseLike 13 | } 14 | 15 | export type DidMethods = { 16 | [K in M]: DidMethod 17 | } 18 | -------------------------------------------------------------------------------- /packages/oauth/oauth-provider-frontend/hydration-data.d.ts: -------------------------------------------------------------------------------- 1 | import { 2 | ActiveDeviceSession, 3 | CustomizationData, 4 | } from '@atproto/oauth-provider-api' 5 | 6 | export type HydrationData = { 7 | 'account-page': { 8 | /** 9 | * needed by `useCustomizationData.ts` 10 | */ 11 | __customizationData: CustomizationData 12 | /** 13 | * needed by `useDeviceSessionsQuery.ts` 14 | */ 15 | __deviceSessions: readonly ActiveDeviceSession[] 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /packages/oauth/oauth-provider-frontend/src/locales/activateLocale.ts: -------------------------------------------------------------------------------- 1 | import { i18n } from '@lingui/core' 2 | import * as en from '#/locales/en/messages' 3 | import { Locale } from './locales' 4 | 5 | export async function activateLocale(locale: Locale) { 6 | const { messages } = await import(`./${locale}/messages.ts`).catch((e) => { 7 | console.error('Error loading locale', e) 8 | return en 9 | }) 10 | 11 | i18n.load(locale, messages) 12 | i18n.activate(locale) 13 | } 14 | -------------------------------------------------------------------------------- /packages/api/src/bsky-agent.ts: -------------------------------------------------------------------------------- 1 | import { AtpAgent } from './atp-agent' 2 | 3 | /** @deprecated use {@link AtpAgent} instead */ 4 | export class BskyAgent extends AtpAgent { 5 | clone(): this { 6 | if (this.constructor === BskyAgent) { 7 | const agent = new BskyAgent(this.sessionManager) 8 | return this.copyInto(agent as this) 9 | } 10 | 11 | // sub-classes should override this method 12 | throw new TypeError('Cannot clone a subclass of BskyAgent') 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /packages/bsky/src/error.ts: -------------------------------------------------------------------------------- 1 | import { ErrorRequestHandler } from 'express' 2 | import { XRPCError } from '@atproto/xrpc-server' 3 | import { httpLogger as log } from './logger' 4 | 5 | export const handler: ErrorRequestHandler = (err, _req, res, next) => { 6 | log.error({ err }, 'unexpected internal server error') 7 | if (res.headersSent) { 8 | return next(err) 9 | } 10 | const serverError = XRPCError.fromError(err) 11 | res.status(serverError.type).json(serverError.payload) 12 | } 13 | -------------------------------------------------------------------------------- /packages/oauth/oauth-client/src/state-store.ts: -------------------------------------------------------------------------------- 1 | import { Key } from '@atproto/jwk' 2 | import { SimpleStore } from '@atproto-labs/simple-store' 3 | import { ClientAuthMethod } from './oauth-client-auth.js' 4 | 5 | export type InternalStateData = { 6 | iss: string 7 | dpopKey: Key 8 | /** @note optional for legacy reasons */ 9 | authMethod?: ClientAuthMethod 10 | verifier?: string 11 | appState?: string 12 | } 13 | 14 | export type StateStore = SimpleStore 15 | -------------------------------------------------------------------------------- /packages/oauth/oauth-scopes/src/scope-missing-error.ts: -------------------------------------------------------------------------------- 1 | export class ScopeMissingError extends Error { 2 | name = 'ScopeMissingError' 3 | 4 | // compatibility layer with http-errors package. The goal if to make 5 | // isHttpError(new ScopeMissingError) return true. 6 | status = 403 7 | expose = true 8 | get statusCode() { 9 | return this.status 10 | } 11 | 12 | constructor(public readonly scope: string) { 13 | super(`Missing required scope "${scope}"`) 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /packages/ozone/tests/__snapshots__/report-reason.test.ts.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`report reason createReport only passes for allowed reason types 1`] = ` 4 | Object { 5 | "createdAt": "1970-01-01T00:00:00.000Z", 6 | "id": 1, 7 | "reasonType": "tools.ozone.report.defs#reasonHarassmentTroll", 8 | "reportedBy": "user(0)", 9 | "subject": Object { 10 | "$type": "com.atproto.admin.defs#repoRef", 11 | "did": "user(1)", 12 | }, 13 | } 14 | `; 15 | -------------------------------------------------------------------------------- /packages/pds/src/account-manager/db/schema/lexicon.ts: -------------------------------------------------------------------------------- 1 | import type { LexiconDoc } from '@atproto/oauth-provider' 2 | import { DateISO, JsonEncoded } from '../../../db/cast' 3 | 4 | export interface Lexicon { 5 | nsid: string 6 | createdAt: DateISO 7 | updatedAt: DateISO 8 | lastSucceededAt: null | DateISO 9 | uri: null | string 10 | lexicon: null | JsonEncoded 11 | } 12 | 13 | export const tableName = 'lexicon' 14 | 15 | export type PartialDB = { [tableName]: Lexicon } 16 | -------------------------------------------------------------------------------- /packages/bsky/src/data-plane/server/db/tables/actor.ts: -------------------------------------------------------------------------------- 1 | import { Generated } from 'kysely' 2 | 3 | export interface Actor { 4 | did: string 5 | handle: string | null 6 | indexedAt: string 7 | takedownRef: string | null 8 | upstreamStatus: string | null 9 | trustedVerifier: Generated 10 | ageAssuranceStatus: string | null 11 | ageAssuranceLastInitiatedAt: string | null 12 | } 13 | 14 | export const tableName = 'actor' 15 | 16 | export type PartialDB = { [tableName]: Actor } 17 | -------------------------------------------------------------------------------- /packages/ozone/src/error.ts: -------------------------------------------------------------------------------- 1 | import { ErrorRequestHandler } from 'express' 2 | import { XRPCError } from '@atproto/xrpc-server' 3 | import { httpLogger as log } from './logger' 4 | 5 | export const handler: ErrorRequestHandler = (err, _req, res, next) => { 6 | log.error({ err }, 'unexpected internal server error') 7 | if (res.headersSent) { 8 | return next(err) 9 | } 10 | const serverError = XRPCError.fromError(err) 11 | res.status(serverError.type).json(serverError.payload) 12 | } 13 | -------------------------------------------------------------------------------- /packages/ozone/src/db/migrations/20240814T003647759Z-event-created-at-index.ts: -------------------------------------------------------------------------------- 1 | import { Kysely } from 'kysely' 2 | 3 | export async function up(db: Kysely): Promise { 4 | await db.schema 5 | .createIndex('moderation_event_created_at_idx') 6 | .on('moderation_event') 7 | .column('createdAt') 8 | .execute() 9 | } 10 | 11 | export async function down(db: Kysely): Promise { 12 | await db.schema.dropIndex('moderation_event_created_at_idx').execute() 13 | } 14 | -------------------------------------------------------------------------------- /packages/ozone/src/db/migrations/20240904T205730722Z-add-subject-did-index.ts: -------------------------------------------------------------------------------- 1 | import { Kysely } from 'kysely' 2 | 3 | export async function up(db: Kysely): Promise { 4 | await db.schema 5 | .createIndex('moderation_event_subject_did_idx') 6 | .on('moderation_event') 7 | .column('subjectDid') 8 | .execute() 9 | } 10 | 11 | export async function down(db: Kysely): Promise { 12 | await db.schema.dropIndex('moderation_event_subject_did_idx').execute() 13 | } 14 | -------------------------------------------------------------------------------- /packages/ozone/src/tag-service/util.ts: -------------------------------------------------------------------------------- 1 | import { ReasonType } from '../lexicon/types/com/atproto/moderation/defs' 2 | 3 | export const getTagForReport = (reasonType: ReasonType) => { 4 | const reasonWithoutPrefix = reasonType 5 | .replace('com.atproto.moderation.defs#reason', '') 6 | .replace('tools.ozone.report.defs#reason', '') 7 | 8 | const kebabCase = reasonWithoutPrefix 9 | .replace(/([a-z])([A-Z])/g, '$1-$2') 10 | .toLowerCase() 11 | 12 | return `report:${kebabCase}` 13 | } 14 | -------------------------------------------------------------------------------- /packages/oauth/oauth-client-browser-example/src/queries/use-get-session-query.ts: -------------------------------------------------------------------------------- 1 | import { useQuery } from '@tanstack/react-query' 2 | import { useBskyClient } from '../lib/use-bsky-client.ts' 3 | 4 | export function useGetSessionQuery() { 5 | const client = useBskyClient() 6 | 7 | return useQuery({ 8 | queryKey: ['session', client.assertDid], 9 | queryFn: async () => { 10 | const { data } = await client.com.atproto.server.getSession() 11 | return data 12 | }, 13 | }) 14 | } 15 | -------------------------------------------------------------------------------- /packages/pds/src/account-manager/db/migrations/003-privileged-app-passwords.ts: -------------------------------------------------------------------------------- 1 | import { Kysely } from 'kysely' 2 | 3 | export async function up(db: Kysely): Promise { 4 | await db.schema 5 | .alterTable('app_password') 6 | .addColumn('privileged', 'integer', (col) => col.notNull().defaultTo(0)) 7 | .execute() 8 | } 9 | 10 | export async function down(db: Kysely): Promise { 11 | await db.schema.alterTable('app_password').dropColumn('privileged').execute() 12 | } 13 | -------------------------------------------------------------------------------- /interop-test-files/syntax/atidentifier_syntax_invalid.txt: -------------------------------------------------------------------------------- 1 | 2 | # invalid handles 3 | did:thing.test 4 | did:thing 5 | john-.test 6 | john.0 7 | john.- 8 | xn--bcher-.tld 9 | john..test 10 | jo_hn.test 11 | 12 | # invalid DIDs 13 | did 14 | didmethodval 15 | method:did:val 16 | did:method: 17 | didmethod:val 18 | did:methodval) 19 | :did:method:val 20 | did:method:val: 21 | did:method:val% 22 | DID:method:val 23 | 24 | # other invalid stuff 25 | email@example.com 26 | @handle@example.com 27 | @handle 28 | blah 29 | -------------------------------------------------------------------------------- /packages/bsky/src/data-plane/server/db/migrations/20240723T220700077Z-quotes-post-aggs.ts: -------------------------------------------------------------------------------- 1 | import { Kysely } from 'kysely' 2 | 3 | export async function up(db: Kysely): Promise { 4 | await db.schema 5 | .alterTable('post_agg') 6 | .addColumn('quoteCount', 'bigint', (col) => col.notNull().defaultTo(0)) 7 | .execute() 8 | } 9 | 10 | export async function down(db: Kysely): Promise { 11 | await db.schema.alterTable('post_agg').dropColumn('quoteCount').execute() 12 | } 13 | -------------------------------------------------------------------------------- /packages/bsky/src/data-plane/server/db/tables/verification.ts: -------------------------------------------------------------------------------- 1 | import { GeneratedAlways } from 'kysely' 2 | 3 | export const tableName = 'verification' 4 | 5 | export interface Verification { 6 | uri: string 7 | cid: string 8 | rkey: string 9 | creator: string 10 | subject: string 11 | handle: string 12 | displayName: string 13 | createdAt: string 14 | indexedAt: string 15 | sortedAt: GeneratedAlways 16 | } 17 | 18 | export type PartialDB = { 19 | [tableName]: Verification 20 | } 21 | -------------------------------------------------------------------------------- /packages/bsync/src/db/schema/notif_op.ts: -------------------------------------------------------------------------------- 1 | import { GeneratedAlways, Selectable } from 'kysely' 2 | 3 | export interface NotifOp { 4 | id: GeneratedAlways 5 | actorDid: string 6 | priority: boolean | null 7 | createdAt: GeneratedAlways 8 | } 9 | 10 | export type NotifOpEntry = Selectable 11 | 12 | export const tableName = 'notif_op' 13 | 14 | export type PartialDB = { [tableName]: NotifOp } 15 | 16 | export const createNotifOpChannel = 'notif_op_create' // used with listen/notify 17 | -------------------------------------------------------------------------------- /packages/identity/src/did/util.ts: -------------------------------------------------------------------------------- 1 | export async function timed unknown>( 2 | ms: number, 3 | fn: F, 4 | ): Promise>> { 5 | const abortController = new AbortController() 6 | const timer = setTimeout(() => abortController.abort(), ms) 7 | const signal = abortController.signal 8 | 9 | try { 10 | return (await fn(signal)) as Awaited> 11 | } finally { 12 | clearTimeout(timer) 13 | abortController.abort() 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /packages/oauth/oauth-provider-ui/src/lib/ref.ts: -------------------------------------------------------------------------------- 1 | import { ForwardedRef } from 'react' 2 | 3 | export function updateRef(ref: ForwardedRef, value: T | null) { 4 | if (typeof ref === 'function') { 5 | ref(value) 6 | } else if (ref) { 7 | ref.current = value 8 | } 9 | } 10 | 11 | export function mergeRefs(refs: readonly (ForwardedRef | undefined)[]) { 12 | return (value: T | null) => { 13 | for (const ref of refs) { 14 | if (ref) updateRef(ref, value) 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /packages/oauth/oauth-provider/src/customization/branding.ts: -------------------------------------------------------------------------------- 1 | import { z } from 'zod' 2 | import { colorsSchema } from './colors.js' 3 | import { linksSchema } from './links.js' 4 | 5 | export const brandingSchema = z.object({ 6 | name: z.string().optional(), 7 | logo: z.string().url().optional(), 8 | colors: colorsSchema.optional(), 9 | links: z.array(linksSchema).optional(), 10 | }) 11 | export type BrandingInput = z.input 12 | export type Branding = z.infer 13 | -------------------------------------------------------------------------------- /packages/oauth/oauth-provider/src/errors/access-denied-error.ts: -------------------------------------------------------------------------------- 1 | import { OAuthAuthorizationRequestParameters } from '@atproto/oauth-types' 2 | import { AuthorizationError } from './authorization-error.js' 3 | 4 | export class AccessDeniedError extends AuthorizationError { 5 | constructor( 6 | parameters: OAuthAuthorizationRequestParameters, 7 | error_description = 'Access denied', 8 | cause?: unknown, 9 | ) { 10 | super(parameters, error_description, 'access_denied', cause) 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /packages/oauth/oauth-provider/src/lib/http/headers.ts: -------------------------------------------------------------------------------- 1 | import type { ServerResponse } from 'node:http' 2 | 3 | export function appendHeader( 4 | res: ServerResponse, 5 | header: string, 6 | value: string | readonly string[], 7 | ): void { 8 | const existing = res.getHeader(header) 9 | if (existing == null) { 10 | res.setHeader(header, value) 11 | } else { 12 | const arr = Array.isArray(existing) ? existing : [String(existing)] 13 | res.setHeader(header, arr.concat(value)) 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /packages/ozone/src/db/migrations/20240201T051104136Z-mod-event-blobs.ts: -------------------------------------------------------------------------------- 1 | import { Kysely } from 'kysely' 2 | 3 | export async function up(db: Kysely): Promise { 4 | await db.schema 5 | .alterTable('moderation_event') 6 | .addColumn('subjectBlobCids', 'jsonb') 7 | .execute() 8 | } 9 | 10 | export async function down(db: Kysely): Promise { 11 | await db.schema 12 | .alterTable('moderation_event') 13 | .dropColumn('subjectBlobCids') 14 | .execute() 15 | } 16 | -------------------------------------------------------------------------------- /packages/ozone/src/db/migrations/20250715T000000000Z-add-mod-event-external-id.ts: -------------------------------------------------------------------------------- 1 | import { Kysely } from 'kysely' 2 | 3 | export async function up(db: Kysely): Promise { 4 | await db.schema 5 | .alterTable('moderation_event') 6 | .addColumn('externalId', 'varchar') 7 | .execute() 8 | } 9 | 10 | export async function down(db: Kysely): Promise { 11 | await db.schema 12 | .alterTable('moderation_event') 13 | .dropColumn('externalId') 14 | .execute() 15 | } 16 | -------------------------------------------------------------------------------- /packages/bsky/src/api/app/bsky/bookmark/util.ts: -------------------------------------------------------------------------------- 1 | import { AtUri } from '@atproto/syntax' 2 | import { InvalidRequestError } from '@atproto/xrpc-server' 3 | import { ids } from '../../../../lexicon/lexicons' 4 | 5 | export const validateUri = (uri: string) => { 6 | const atUri = new AtUri(uri) 7 | if (atUri.collection !== ids.AppBskyFeedPost) { 8 | throw new InvalidRequestError( 9 | `Only '${ids.AppBskyFeedPost}' records can be bookmarked`, 10 | 'UnsupportedCollection', 11 | ) 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /packages/oauth/oauth-provider/src/errors/login-required-error.ts: -------------------------------------------------------------------------------- 1 | import { OAuthAuthorizationRequestParameters } from '@atproto/oauth-types' 2 | import { AuthorizationError } from './authorization-error.js' 3 | 4 | export class LoginRequiredError extends AuthorizationError { 5 | constructor( 6 | parameters: OAuthAuthorizationRequestParameters, 7 | error_description = 'Login is required', 8 | cause?: unknown, 9 | ) { 10 | super(parameters, error_description, 'login_required', cause) 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /packages/oauth/oauth-provider/src/lib/util/cast.ts: -------------------------------------------------------------------------------- 1 | export function asArray(value: T | T[]): T[] { 2 | if (value == null) return [] 3 | return Array.isArray(value) ? value : [value] 4 | } 5 | 6 | export function asURL(value: string | { toString: () => string }): URL { 7 | return new URL(value) 8 | } 9 | 10 | export function ifURL( 11 | value: string | { toString: () => string }, 12 | ): URL | undefined { 13 | try { 14 | return asURL(value) 15 | } catch { 16 | return undefined 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /packages/bsky/src/data-plane/server/db/migrations/20250813T174955711Z-add-post-agg-bookmarks.ts: -------------------------------------------------------------------------------- 1 | import { Kysely } from 'kysely' 2 | 3 | export async function up(db: Kysely): Promise { 4 | await db.schema 5 | .alterTable('post_agg') 6 | .addColumn('bookmarkCount', 'bigint', (col) => col.notNull().defaultTo(0)) 7 | .execute() 8 | } 9 | 10 | export async function down(db: Kysely): Promise { 11 | await db.schema.alterTable('post_agg').dropColumn('bookmarkCount').execute() 12 | } 13 | -------------------------------------------------------------------------------- /packages/bsky/src/data-plane/server/db/tables/list.ts: -------------------------------------------------------------------------------- 1 | import { GeneratedAlways } from 'kysely' 2 | 3 | export const tableName = 'list' 4 | 5 | export interface List { 6 | uri: string 7 | cid: string 8 | creator: string 9 | name: string 10 | purpose: string 11 | description: string | null 12 | descriptionFacets: string | null 13 | avatarCid: string | null 14 | createdAt: string 15 | indexedAt: string 16 | sortAt: GeneratedAlways 17 | } 18 | 19 | export type PartialDB = { [tableName]: List } 20 | -------------------------------------------------------------------------------- /packages/bsky/src/util/retry.ts: -------------------------------------------------------------------------------- 1 | import { createRetryable } from '@atproto/common' 2 | import { ResponseType, XRPCError } from '@atproto/xrpc' 3 | 4 | export const RETRYABLE_HTTP_STATUS_CODES = new Set([ 5 | 408, 425, 429, 500, 502, 503, 504, 522, 524, 6 | ]) 7 | 8 | export const retryXrpc = createRetryable((err: unknown) => { 9 | if (err instanceof XRPCError) { 10 | if (err.status === ResponseType.Unknown) return true 11 | return RETRYABLE_HTTP_STATUS_CODES.has(err.status) 12 | } 13 | return false 14 | }) 15 | -------------------------------------------------------------------------------- /packages/bsky/src/data-plane/server/db/migrations/20230627T212437895Z-optional-handle.ts: -------------------------------------------------------------------------------- 1 | import { Kysely } from 'kysely' 2 | 3 | export async function up(db: Kysely): Promise { 4 | await db.schema 5 | .alterTable('actor') 6 | .alterColumn('handle') 7 | .dropNotNull() 8 | .execute() 9 | } 10 | 11 | export async function down(db: Kysely): Promise { 12 | await db.schema 13 | .alterTable('actor') 14 | .alterColumn('handle') 15 | .setNotNull() 16 | .execute() 17 | } 18 | -------------------------------------------------------------------------------- /packages/oauth/oauth-provider/src/errors/consent-required-error.ts: -------------------------------------------------------------------------------- 1 | import { OAuthAuthorizationRequestParameters } from '@atproto/oauth-types' 2 | import { AuthorizationError } from './authorization-error.js' 3 | 4 | export class ConsentRequiredError extends AuthorizationError { 5 | constructor( 6 | parameters: OAuthAuthorizationRequestParameters, 7 | error_description = 'User consent required', 8 | cause?: unknown, 9 | ) { 10 | super(parameters, error_description, 'consent_required', cause) 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /packages/oauth/oauth-provider/src/lib/http/types.ts: -------------------------------------------------------------------------------- 1 | import type { IncomingMessage, ServerResponse } from 'node:http' 2 | 3 | export type NextFunction = (err?: unknown) => void 4 | 5 | export type Middleware< 6 | T = void, 7 | Req = IncomingMessage, 8 | Res = ServerResponse, 9 | > = (this: T, req: Req, res: Res, next: NextFunction) => void 10 | 11 | export type Handler = ( 12 | this: T, 13 | req: Req, 14 | res: Res, 15 | next?: NextFunction, 16 | ) => void 17 | -------------------------------------------------------------------------------- /packages/oauth/oauth-provider/src/oauth-store.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Every store file exports all the types needed to implement that store. This 3 | * files re-exports all the types from the x-store files. 4 | */ 5 | 6 | export * from './account/account-store.js' 7 | export * from './client/client-store.js' 8 | export * from './device/device-store.js' 9 | export * from './lexicon/lexicon-store.js' 10 | export * from './replay/replay-store.js' 11 | export * from './request/request-store.js' 12 | export * from './token/token-store.js' 13 | -------------------------------------------------------------------------------- /packages/pds/src/account-manager/db/schema/device.ts: -------------------------------------------------------------------------------- 1 | import { Selectable } from 'kysely' 2 | import { DeviceId, SessionId } from '@atproto/oauth-provider' 3 | import { DateISO } from '../../../db' 4 | 5 | export interface Device { 6 | id: DeviceId 7 | sessionId: SessionId 8 | 9 | userAgent: string | null 10 | ipAddress: string 11 | lastSeenAt: DateISO 12 | } 13 | 14 | export type DeviceEntry = Selectable 15 | 16 | export const tableName = 'device' 17 | 18 | export type PartialDB = { [tableName]: Device } 19 | -------------------------------------------------------------------------------- /packages/bsky/src/data-plane/server/db/migrations/20230427T194702079Z-notif-record-index.ts: -------------------------------------------------------------------------------- 1 | import { Kysely } from 'kysely' 2 | 3 | export async function up(db: Kysely): Promise { 4 | // Supports record deletion 5 | await db.schema 6 | .createIndex('notification_record_idx') 7 | .on('notification') 8 | .column('recordUri') 9 | .execute() 10 | } 11 | 12 | export async function down(db: Kysely): Promise { 13 | await db.schema.dropIndex('notification_record_idx').execute() 14 | } 15 | -------------------------------------------------------------------------------- /packages/dev-env/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './bsky' 2 | export * from './bsync' 3 | export * from './network' 4 | export * from './network-no-appview' 5 | export * from './ozone' 6 | export * from './pds' 7 | export * from './plc' 8 | export * from './ozone' 9 | export * from './feed-gen' 10 | export * from './seed' 11 | export * from './moderator-client' 12 | export * from './types' 13 | export * from './util' 14 | export * from './const' 15 | 16 | import * as seedThreadV2 from './seed/thread-v2.js' 17 | export { seedThreadV2 } 18 | -------------------------------------------------------------------------------- /packages/pds/src/api/app/bsky/actor/index.ts: -------------------------------------------------------------------------------- 1 | import { AppContext } from '../../../../context' 2 | import { Server } from '../../../../lexicon' 3 | import getPreferences from './getPreferences' 4 | import getProfile from './getProfile' 5 | import getProfiles from './getProfiles' 6 | import putPreferences from './putPreferences' 7 | 8 | export default function (server: Server, ctx: AppContext) { 9 | getPreferences(server, ctx) 10 | getProfile(server, ctx) 11 | getProfiles(server, ctx) 12 | putPreferences(server, ctx) 13 | } 14 | -------------------------------------------------------------------------------- /lexicons/app/bsky/embed/defs.json: -------------------------------------------------------------------------------- 1 | { 2 | "lexicon": 1, 3 | "id": "app.bsky.embed.defs", 4 | "defs": { 5 | "aspectRatio": { 6 | "type": "object", 7 | "description": "width:height represents an aspect ratio. It may be approximate, and may not correspond to absolute dimensions in any given unit.", 8 | "required": ["width", "height"], 9 | "properties": { 10 | "width": { "type": "integer", "minimum": 1 }, 11 | "height": { "type": "integer", "minimum": 1 } 12 | } 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /packages/bsky/src/data-plane/server/db/migrations/20230807T035309811Z-feed-item-delete-invite-for-user-idx.ts: -------------------------------------------------------------------------------- 1 | import { Kysely } from 'kysely' 2 | 3 | export async function up(db: Kysely): Promise { 4 | // supports post deletion 5 | await db.schema 6 | .createIndex('feed_item_post_uri_idx') 7 | .on('feed_item') 8 | .column('postUri') 9 | .execute() 10 | } 11 | 12 | export async function down(db: Kysely): Promise { 13 | await db.schema.dropIndex('feed_item_post_uri_idx').execute() 14 | } 15 | -------------------------------------------------------------------------------- /packages/bsky/src/data-plane/server/db/tables/profile.ts: -------------------------------------------------------------------------------- 1 | export const tableName = 'profile' 2 | 3 | export interface Profile { 4 | uri: string 5 | cid: string 6 | creator: string 7 | displayName: string | null 8 | description: string | null 9 | avatarCid: string | null 10 | bannerCid: string | null 11 | joinedViaStarterPackUri: string | null 12 | pinnedPost: string | null 13 | pinnedPostCid: string | null 14 | createdAt: string 15 | indexedAt: string 16 | } 17 | export type PartialDB = { [tableName]: Profile } 18 | -------------------------------------------------------------------------------- /packages/did/jest.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('jest').Config} */ 2 | module.exports = { 3 | displayName: 'PDS', 4 | transform: { '^.+\\.(t|j)s$': '@swc/jest' }, 5 | // Jest requires all ESM dependencies to be transpiled (even if they are 6 | // dynamically import()ed). 7 | transformIgnorePatterns: [ 8 | `/node_modules/.pnpm/(?!(get-port|lande|toygrad)@)`, 9 | ], 10 | testTimeout: 60000, 11 | setupFiles: ['/../../jest.setup.ts'], 12 | moduleNameMapper: { '^(\\.\\.?\\/.+)\\.js$': ['$1.ts', '$1.js'] }, 13 | } 14 | -------------------------------------------------------------------------------- /packages/oauth/oauth-provider-frontend/src/data/usePasswordConfirmMutation.ts: -------------------------------------------------------------------------------- 1 | import { useMutation } from '@tanstack/react-query' 2 | import { ConfirmResetPasswordInput, useApi } from '#/api' 3 | 4 | export type PasswordConfirmMutationInput = ConfirmResetPasswordInput 5 | 6 | export function usePasswordConfirmMutation() { 7 | const api = useApi() 8 | 9 | return useMutation({ 10 | async mutationFn(input: ConfirmResetPasswordInput) { 11 | await api.fetch('POST', '/reset-password-confirm', input) 12 | }, 13 | }) 14 | } 15 | -------------------------------------------------------------------------------- /packages/oauth/oauth-provider-ui/src/hooks/use-escape-key.ts: -------------------------------------------------------------------------------- 1 | import { useEffect } from 'react' 2 | 3 | export function useEscapeKey(callback: () => void) { 4 | const handleKeyDown = (event: KeyboardEvent) => { 5 | if (event.key === 'Escape') { 6 | event.preventDefault() 7 | callback() 8 | } 9 | } 10 | 11 | useEffect(() => { 12 | window.addEventListener('keydown', handleKeyDown) 13 | return () => { 14 | window.removeEventListener('keydown', handleKeyDown) 15 | } 16 | }, [callback]) 17 | } 18 | -------------------------------------------------------------------------------- /packages/ozone/src/db/migrations/20240408T192432676Z-mute-reporting.ts: -------------------------------------------------------------------------------- 1 | import { Kysely } from 'kysely' 2 | 3 | export async function up(db: Kysely): Promise { 4 | await db.schema 5 | .alterTable('moderation_subject_status') 6 | .addColumn('muteReportingUntil', 'varchar') 7 | .execute() 8 | } 9 | 10 | export async function down(db: Kysely): Promise { 11 | await db.schema 12 | .alterTable('moderation_subject_status') 13 | .dropColumn('muteReportingUntil') 14 | .execute() 15 | } 16 | -------------------------------------------------------------------------------- /packages/pds/jest.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('jest').Config} */ 2 | module.exports = { 3 | displayName: 'PDS', 4 | transform: { '^.+\\.(t|j)s$': '@swc/jest' }, 5 | // Jest requires all ESM dependencies to be transpiled (even if they are 6 | // dynamically import()ed). 7 | transformIgnorePatterns: [ 8 | `/node_modules/.pnpm/(?!(get-port|lande|toygrad)@)`, 9 | ], 10 | testTimeout: 60000, 11 | setupFiles: ['/../../jest.setup.ts'], 12 | moduleNameMapper: { '^(\\.\\.?\\/.+)\\.js$': ['$1.ts', '$1.js'] }, 13 | } 14 | -------------------------------------------------------------------------------- /.changeset/README.md: -------------------------------------------------------------------------------- 1 | # Changesets 2 | 3 | Hello and welcome! This folder has been automatically generated by `@changesets/cli`, a build tool that works 4 | with multi-package repos, or single-package repos to help you version and publish your code. You can 5 | find the full documentation for it [in our repository](https://github.com/changesets/changesets) 6 | 7 | We have a quick list of common questions to get you started engaging with this project in 8 | [our documentation](https://github.com/changesets/changesets/blob/main/docs/common-questions.md) 9 | -------------------------------------------------------------------------------- /packages/bsky/src/data-plane/server/db/migrations/20230611T215300060Z-actor-state.ts: -------------------------------------------------------------------------------- 1 | import { Kysely } from 'kysely' 2 | 3 | export async function up(db: Kysely): Promise { 4 | await db.schema 5 | .createTable('actor_state') 6 | .addColumn('did', 'varchar', (col) => col.primaryKey()) 7 | .addColumn('lastSeenNotifs', 'varchar', (col) => col.notNull()) 8 | .execute() 9 | } 10 | 11 | export async function down(db: Kysely): Promise { 12 | await db.schema.dropTable('actor_state').execute() 13 | } 14 | -------------------------------------------------------------------------------- /packages/bsky/src/data-plane/server/db/migrations/20230830T205507322Z-suggested-feeds.ts: -------------------------------------------------------------------------------- 1 | import { Kysely } from 'kysely' 2 | 3 | export async function up(db: Kysely): Promise { 4 | await db.schema 5 | .createTable('suggested_feed') 6 | .addColumn('uri', 'varchar', (col) => col.primaryKey()) 7 | .addColumn('order', 'integer', (col) => col.notNull()) 8 | .execute() 9 | } 10 | 11 | export async function down(db: Kysely): Promise { 12 | await db.schema.dropTable('suggested_feed').execute() 13 | } 14 | -------------------------------------------------------------------------------- /packages/oauth/oauth-client-browser-example/src/lib/use-escape-key.ts: -------------------------------------------------------------------------------- 1 | import { useEffect } from 'react' 2 | 3 | export function useEscapeKey(callback: () => void) { 4 | const handleKeyDown = (event: KeyboardEvent) => { 5 | if (event.key === 'Escape') { 6 | event.preventDefault() 7 | callback() 8 | } 9 | } 10 | 11 | useEffect(() => { 12 | window.addEventListener('keydown', handleKeyDown) 13 | return () => { 14 | window.removeEventListener('keydown', handleKeyDown) 15 | } 16 | }, [callback]) 17 | } 18 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # buf 2 | packages/bsky/src/proto/** linguist-generated=true 3 | packages/bsync/src/proto/** linguist-generated=true 4 | 5 | # codegen 6 | packages/api/src/client/** linguist-generated=true 7 | packages/lexicon-resolver/src/client/** linguist-generated=true 8 | packages/bsky/src/lexicon/** linguist-generated=true 9 | packages/pds/src/lexicon/** linguist-generated=true 10 | packages/ozone/src/lexicon/** linguist-generated=true 11 | 12 | # i18n 13 | packages/oauth/oauth-provider-ui/src/locales/**/messages.po linguist-generated=true 14 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Dual MIT/Apache-2.0 License 2 | 3 | Copyright (c) 2022-2025 Bluesky Social PBC, and Contributors 4 | 5 | Except as otherwise noted in individual files, this software is licensed under the MIT license (), or the Apache License, Version 2.0 (). 6 | 7 | Downstream projects and end users may chose either license individually, or both together, at their discretion. The motivation for this dual-licensing is the additional software patent assurance provided by Apache 2.0. 8 | -------------------------------------------------------------------------------- /packages/bsync/src/db/schema/index.ts: -------------------------------------------------------------------------------- 1 | import { Kysely } from 'kysely' 2 | import * as muteItem from './mute_item' 3 | import * as muteOp from './mute_op' 4 | import * as notifItem from './notif_item' 5 | import * as notifOp from './notif_op' 6 | import * as op from './operation' 7 | 8 | export type DatabaseSchemaType = muteItem.PartialDB & 9 | muteOp.PartialDB & 10 | notifItem.PartialDB & 11 | notifOp.PartialDB & 12 | op.PartialDB 13 | 14 | export type DatabaseSchema = Kysely 15 | 16 | export default DatabaseSchema 17 | -------------------------------------------------------------------------------- /packages/internal/did-resolver/src/did-resolver.ts: -------------------------------------------------------------------------------- 1 | import { Did, DidDocument } from '@atproto/did' 2 | import { ResolveDidOptions } from './did-method.js' 3 | 4 | export type ResolvedDocument = 5 | D extends Did 6 | ? DidDocument 7 | : never 8 | 9 | export interface DidResolver { 10 | resolve( 11 | did: D, 12 | options?: ResolveDidOptions, 13 | ): Promise> 14 | } 15 | -------------------------------------------------------------------------------- /interop-test-files/README.md: -------------------------------------------------------------------------------- 1 | 2 | atproto Interop Test Files 3 | ========================== 4 | 5 | This directory contains reusable files for testing interoperability and specification compliance for atproto (AT Protocol). 6 | 7 | The protocol itself is documented at . If there are conflicts or ambiguity between these test files and the specs, the specs are the authority, and these test files should usually be corrected. 8 | 9 | These files are intended to be simple (JSON, text files, etc) and mostly self-documenting. 10 | -------------------------------------------------------------------------------- /lexicons/com/atproto/server/revokeAppPassword.json: -------------------------------------------------------------------------------- 1 | { 2 | "lexicon": 1, 3 | "id": "com.atproto.server.revokeAppPassword", 4 | "defs": { 5 | "main": { 6 | "type": "procedure", 7 | "description": "Revoke an App Password by name.", 8 | "input": { 9 | "encoding": "application/json", 10 | "schema": { 11 | "type": "object", 12 | "required": ["name"], 13 | "properties": { 14 | "name": { "type": "string" } 15 | } 16 | } 17 | } 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /packages/bsky/src/data-plane/server/db/migrations/20230610T203555962Z-suggested-follows.ts: -------------------------------------------------------------------------------- 1 | import { Kysely } from 'kysely' 2 | 3 | export async function up(db: Kysely): Promise { 4 | await db.schema 5 | .createTable('suggested_follow') 6 | .addColumn('did', 'varchar', (col) => col.primaryKey()) 7 | .addColumn('order', 'integer', (col) => col.notNull()) 8 | .execute() 9 | } 10 | 11 | export async function down(db: Kysely): Promise { 12 | await db.schema.dropTable('suggested_follow').execute() 13 | } 14 | --------------------------------------------------------------------------------