* adding in banners & some lex codegen improvements for server

* fix up spacing

* couple small fixes

* client codegen & remove media embed schemas

* hook up banners

* missed a couple of lexicons
This commit is contained in:
Daniel Holmgren 2022-12-12 10:18:50 -06:00 committed by GitHub
parent 91215f4f67
commit a125f4e36d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
41 changed files with 368 additions and 235 deletions

@ -30,6 +30,7 @@
"maxLength": 256
},
"avatar": { "type": "string" },
"banner": { "type": "string" },
"followersCount": {"type": "integer"},
"followsCount": {"type": "integer"},
"membersCount": {"type": "integer"},

@ -23,6 +23,13 @@
"maxWidth": 500,
"maxHeight": 500,
"maxSize": 300000
},
"banner": {
"type": "image",
"accept": ["image/png", "image/jpeg"],
"maxWidth": 1500,
"maxHeight": 500,
"maxSize": 500000
}
}
}

@ -25,6 +25,13 @@
"maxWidth": 500,
"maxHeight": 500,
"maxSize": 100000
},
"banner": {
"type": "image",
"accept": ["image/png", "image/jpeg"],
"maxWidth": 1500,
"maxHeight": 500,
"maxSize": 500000
}
}
}

@ -5,7 +5,7 @@ import {
Client as XrpcClient,
ServiceClient as XrpcServiceClient,
} from '@atproto/xrpc'
import { lexicons } from './lexicons'
import { schemas } from './lexicons'
import * as ComAtprotoAccountCreate from './types/com/atproto/account/create'
import * as ComAtprotoAccountCreateInviteCode from './types/com/atproto/account/createInviteCode'
import * as ComAtprotoAccountDelete from './types/com/atproto/account/delete'
@ -141,7 +141,7 @@ export class Client {
xrpc: XrpcClient = new XrpcClient()
constructor() {
this.xrpc.addLexicons(lexicons)
this.xrpc.addLexicons(schemas)
}
service(serviceUri: string | URL): ServiceClient {

@ -1,10 +1,10 @@
/**
* GENERATED CODE - DO NOT MODIFY
*/
import { LexiconDoc } from '@atproto/lexicon'
import { LexiconDoc, Lexicons } from '@atproto/lexicon'
export const lexicons: LexiconDoc[] = [
{
export const schemaDict = {
ComAtprotoAccountCreate: {
lexicon: 1,
id: 'com.atproto.account.create',
defs: {
@ -73,7 +73,7 @@ export const lexicons: LexiconDoc[] = [
},
},
},
{
ComAtprotoAccountCreateInviteCode: {
lexicon: 1,
id: 'com.atproto.account.createInviteCode',
defs: {
@ -107,7 +107,7 @@ export const lexicons: LexiconDoc[] = [
},
},
},
{
ComAtprotoAccountDelete: {
lexicon: 1,
id: 'com.atproto.account.delete',
defs: {
@ -117,7 +117,7 @@ export const lexicons: LexiconDoc[] = [
},
},
},
{
ComAtprotoAccountGet: {
lexicon: 1,
id: 'com.atproto.account.get',
defs: {
@ -127,7 +127,7 @@ export const lexicons: LexiconDoc[] = [
},
},
},
{
ComAtprotoAccountRequestPasswordReset: {
lexicon: 1,
id: 'com.atproto.account.requestPasswordReset',
defs: {
@ -149,7 +149,7 @@ export const lexicons: LexiconDoc[] = [
},
},
},
{
ComAtprotoAccountResetPassword: {
lexicon: 1,
id: 'com.atproto.account.resetPassword',
defs: {
@ -182,7 +182,7 @@ export const lexicons: LexiconDoc[] = [
},
},
},
{
ComAtprotoBlobUpload: {
lexicon: 1,
id: 'com.atproto.blob.upload',
defs: {
@ -213,7 +213,7 @@ export const lexicons: LexiconDoc[] = [
},
},
},
{
ComAtprotoHandleResolve: {
lexicon: 1,
id: 'com.atproto.handle.resolve',
defs: {
@ -245,7 +245,7 @@ export const lexicons: LexiconDoc[] = [
},
},
},
{
ComAtprotoRepoBatchWrite: {
lexicon: 1,
id: 'com.atproto.repo.batchWrite',
defs: {
@ -339,7 +339,7 @@ export const lexicons: LexiconDoc[] = [
},
},
},
{
ComAtprotoRepoCreateRecord: {
lexicon: 1,
id: 'com.atproto.repo.createRecord',
defs: {
@ -390,7 +390,7 @@ export const lexicons: LexiconDoc[] = [
},
},
},
{
ComAtprotoRepoDeleteRecord: {
lexicon: 1,
id: 'com.atproto.repo.deleteRecord',
defs: {
@ -421,7 +421,7 @@ export const lexicons: LexiconDoc[] = [
},
},
},
{
ComAtprotoRepoDescribe: {
lexicon: 1,
id: 'com.atproto.repo.describe',
defs: {
@ -475,7 +475,7 @@ export const lexicons: LexiconDoc[] = [
},
},
},
{
ComAtprotoRepoGetRecord: {
lexicon: 1,
id: 'com.atproto.repo.getRecord',
defs: {
@ -526,7 +526,7 @@ export const lexicons: LexiconDoc[] = [
},
},
},
{
ComAtprotoRepoListRecords: {
lexicon: 1,
id: 'com.atproto.repo.listRecords',
defs: {
@ -603,7 +603,7 @@ export const lexicons: LexiconDoc[] = [
},
},
},
{
ComAtprotoRepoPutRecord: {
lexicon: 1,
id: 'com.atproto.repo.putRecord',
defs: {
@ -658,7 +658,7 @@ export const lexicons: LexiconDoc[] = [
},
},
},
{
ComAtprotoRepoStrongRef: {
lexicon: 1,
id: 'com.atproto.repo.strongRef',
description: 'A URI with a content-hash fingerprint.',
@ -677,7 +677,7 @@ export const lexicons: LexiconDoc[] = [
},
},
},
{
ComAtprotoServerGetAccountsConfig: {
lexicon: 1,
id: 'com.atproto.server.getAccountsConfig',
defs: {
@ -721,7 +721,7 @@ export const lexicons: LexiconDoc[] = [
},
},
},
{
ComAtprotoSessionCreate: {
lexicon: 1,
id: 'com.atproto.session.create',
defs: {
@ -767,7 +767,7 @@ export const lexicons: LexiconDoc[] = [
},
},
},
{
ComAtprotoSessionDelete: {
lexicon: 1,
id: 'com.atproto.session.delete',
defs: {
@ -777,7 +777,7 @@ export const lexicons: LexiconDoc[] = [
},
},
},
{
ComAtprotoSessionGet: {
lexicon: 1,
id: 'com.atproto.session.get',
defs: {
@ -802,7 +802,7 @@ export const lexicons: LexiconDoc[] = [
},
},
},
{
ComAtprotoSessionRefresh: {
lexicon: 1,
id: 'com.atproto.session.refresh',
defs: {
@ -833,7 +833,7 @@ export const lexicons: LexiconDoc[] = [
},
},
},
{
ComAtprotoSyncGetRepo: {
lexicon: 1,
id: 'com.atproto.sync.getRepo',
defs: {
@ -860,7 +860,7 @@ export const lexicons: LexiconDoc[] = [
},
},
},
{
ComAtprotoSyncGetRoot: {
lexicon: 1,
id: 'com.atproto.sync.getRoot',
defs: {
@ -892,7 +892,7 @@ export const lexicons: LexiconDoc[] = [
},
},
},
{
ComAtprotoSyncUpdateRepo: {
lexicon: 1,
id: 'com.atproto.sync.updateRepo',
defs: {
@ -915,7 +915,7 @@ export const lexicons: LexiconDoc[] = [
},
},
},
{
AppBskyActorCreateScene: {
lexicon: 1,
id: 'app.bsky.actor.createScene',
defs: {
@ -967,7 +967,7 @@ export const lexicons: LexiconDoc[] = [
},
},
},
{
AppBskyActorGetProfile: {
lexicon: 1,
id: 'app.bsky.actor.getProfile',
defs: {
@ -1021,6 +1021,9 @@ export const lexicons: LexiconDoc[] = [
avatar: {
type: 'string',
},
banner: {
type: 'string',
},
followersCount: {
type: 'integer',
},
@ -1054,7 +1057,7 @@ export const lexicons: LexiconDoc[] = [
},
},
},
{
AppBskyActorGetSuggestions: {
lexicon: 1,
id: 'app.bsky.actor.getSuggestions',
defs: {
@ -1139,7 +1142,7 @@ export const lexicons: LexiconDoc[] = [
},
},
},
{
AppBskyActorProfile: {
lexicon: 1,
id: 'app.bsky.actor.profile',
defs: {
@ -1165,12 +1168,19 @@ export const lexicons: LexiconDoc[] = [
maxHeight: 500,
maxSize: 300000,
},
banner: {
type: 'image',
accept: ['image/png', 'image/jpeg'],
maxWidth: 1500,
maxHeight: 500,
maxSize: 500000,
},
},
},
},
},
},
{
AppBskyActorRef: {
lexicon: 1,
id: 'app.bsky.actor.ref',
description: 'A reference to an actor in the network.',
@ -1212,7 +1222,7 @@ export const lexicons: LexiconDoc[] = [
},
},
},
{
AppBskyActorSearch: {
lexicon: 1,
id: 'app.bsky.actor.search',
defs: {
@ -1288,7 +1298,7 @@ export const lexicons: LexiconDoc[] = [
},
},
},
{
AppBskyActorSearchTypeahead: {
lexicon: 1,
id: 'app.bsky.actor.searchTypeahead',
defs: {
@ -1352,7 +1362,7 @@ export const lexicons: LexiconDoc[] = [
},
},
},
{
AppBskyActorUpdateProfile: {
lexicon: 1,
id: 'app.bsky.actor.updateProfile',
defs: {
@ -1382,6 +1392,13 @@ export const lexicons: LexiconDoc[] = [
maxHeight: 500,
maxSize: 100000,
},
banner: {
type: 'image',
accept: ['image/png', 'image/jpeg'],
maxWidth: 1500,
maxHeight: 500,
maxSize: 500000,
},
},
},
},
@ -1406,7 +1423,7 @@ export const lexicons: LexiconDoc[] = [
},
},
},
{
AppBskyFeedEmbed: {
lexicon: 1,
id: 'app.bsky.feed.embed',
description:
@ -1486,7 +1503,7 @@ export const lexicons: LexiconDoc[] = [
},
},
},
{
AppBskyFeedGetAuthorFeed: {
lexicon: 1,
id: 'app.bsky.feed.getAuthorFeed',
defs: {
@ -1607,7 +1624,7 @@ export const lexicons: LexiconDoc[] = [
},
},
},
{
AppBskyFeedGetPostThread: {
lexicon: 1,
id: 'app.bsky.feed.getPostThread',
defs: {
@ -1745,7 +1762,7 @@ export const lexicons: LexiconDoc[] = [
},
},
},
{
AppBskyFeedGetRepostedBy: {
lexicon: 1,
id: 'app.bsky.feed.getRepostedBy',
defs: {
@ -1829,7 +1846,7 @@ export const lexicons: LexiconDoc[] = [
},
},
},
{
AppBskyFeedGetTimeline: {
lexicon: 1,
id: 'app.bsky.feed.getTimeline',
defs: {
@ -1949,7 +1966,7 @@ export const lexicons: LexiconDoc[] = [
},
},
},
{
AppBskyFeedGetVotes: {
lexicon: 1,
id: 'app.bsky.feed.getVotes',
defs: {
@ -2028,7 +2045,7 @@ export const lexicons: LexiconDoc[] = [
},
},
},
{
AppBskyFeedPost: {
lexicon: 1,
id: 'app.bsky.feed.post',
defs: {
@ -2108,7 +2125,7 @@ export const lexicons: LexiconDoc[] = [
},
},
},
{
AppBskyFeedRepost: {
lexicon: 1,
id: 'app.bsky.feed.repost',
defs: {
@ -2131,7 +2148,7 @@ export const lexicons: LexiconDoc[] = [
},
},
},
{
AppBskyFeedSetVote: {
lexicon: 1,
id: 'app.bsky.feed.setVote',
defs: {
@ -2172,7 +2189,7 @@ export const lexicons: LexiconDoc[] = [
},
},
},
{
AppBskyFeedTrend: {
lexicon: 1,
id: 'app.bsky.feed.trend',
defs: {
@ -2195,7 +2212,7 @@ export const lexicons: LexiconDoc[] = [
},
},
},
{
AppBskyFeedVote: {
lexicon: 1,
id: 'app.bsky.feed.vote',
defs: {
@ -2222,7 +2239,7 @@ export const lexicons: LexiconDoc[] = [
},
},
},
{
AppBskyGraphAssertCreator: {
lexicon: 1,
id: 'app.bsky.graph.assertCreator',
defs: {
@ -2233,7 +2250,7 @@ export const lexicons: LexiconDoc[] = [
},
},
},
{
AppBskyGraphAssertMember: {
lexicon: 1,
id: 'app.bsky.graph.assertMember',
defs: {
@ -2244,7 +2261,7 @@ export const lexicons: LexiconDoc[] = [
},
},
},
{
AppBskyGraphAssertion: {
lexicon: 1,
id: 'app.bsky.graph.assertion',
defs: {
@ -2270,7 +2287,7 @@ export const lexicons: LexiconDoc[] = [
},
},
},
{
AppBskyGraphConfirmation: {
lexicon: 1,
id: 'app.bsky.graph.confirmation',
defs: {
@ -2297,7 +2314,7 @@ export const lexicons: LexiconDoc[] = [
},
},
},
{
AppBskyGraphFollow: {
lexicon: 1,
id: 'app.bsky.graph.follow',
defs: {
@ -2321,7 +2338,7 @@ export const lexicons: LexiconDoc[] = [
},
},
},
{
AppBskyGraphGetAssertions: {
lexicon: 1,
id: 'app.bsky.graph.getAssertions',
defs: {
@ -2435,7 +2452,7 @@ export const lexicons: LexiconDoc[] = [
},
},
},
{
AppBskyGraphGetFollowers: {
lexicon: 1,
id: 'app.bsky.graph.getFollowers',
defs: {
@ -2515,7 +2532,7 @@ export const lexicons: LexiconDoc[] = [
},
},
},
{
AppBskyGraphGetFollows: {
lexicon: 1,
id: 'app.bsky.graph.getFollows',
defs: {
@ -2592,7 +2609,7 @@ export const lexicons: LexiconDoc[] = [
},
},
},
{
AppBskyGraphGetMembers: {
lexicon: 1,
id: 'app.bsky.graph.getMembers',
defs: {
@ -2669,7 +2686,7 @@ export const lexicons: LexiconDoc[] = [
},
},
},
{
AppBskyGraphGetMemberships: {
lexicon: 1,
id: 'app.bsky.graph.getMemberships',
defs: {
@ -2746,7 +2763,7 @@ export const lexicons: LexiconDoc[] = [
},
},
},
{
AppBskyNotificationGetCount: {
lexicon: 1,
id: 'app.bsky.notification.getCount',
defs: {
@ -2767,7 +2784,7 @@ export const lexicons: LexiconDoc[] = [
},
},
},
{
AppBskyNotificationList: {
lexicon: 1,
id: 'app.bsky.notification.list',
defs: {
@ -2859,7 +2876,7 @@ export const lexicons: LexiconDoc[] = [
},
},
},
{
AppBskyNotificationUpdateSeen: {
lexicon: 1,
id: 'app.bsky.notification.updateSeen',
defs: {
@ -2881,7 +2898,7 @@ export const lexicons: LexiconDoc[] = [
},
},
},
{
AppBskySystemActorScene: {
lexicon: 1,
id: 'app.bsky.system.actorScene',
defs: {
@ -2892,7 +2909,7 @@ export const lexicons: LexiconDoc[] = [
},
},
},
{
AppBskySystemActorUser: {
lexicon: 1,
id: 'app.bsky.system.actorUser',
defs: {
@ -2903,7 +2920,7 @@ export const lexicons: LexiconDoc[] = [
},
},
},
{
AppBskySystemDeclRef: {
lexicon: 1,
id: 'app.bsky.system.declRef',
defs: {
@ -2926,7 +2943,7 @@ export const lexicons: LexiconDoc[] = [
},
},
},
{
AppBskySystemDeclaration: {
lexicon: 1,
id: 'app.bsky.system.declaration',
defs: {
@ -2951,7 +2968,9 @@ export const lexicons: LexiconDoc[] = [
},
},
},
]
}
export const schemas: LexiconDoc[] = Object.values(schemaDict) as LexiconDoc[]
export const lexicons: Lexicons = new Lexicons(schemas)
export const ids = {
ComAtprotoAccountCreate: 'com.atproto.account.create',
ComAtprotoAccountCreateInviteCode: 'com.atproto.account.createInviteCode',

@ -18,6 +18,7 @@ export interface OutputSchema {
displayName?: string
description?: string
avatar?: string
banner?: string
followersCount: number
followsCount: number
membersCount: number

@ -5,5 +5,6 @@ export interface Record {
displayName: string
description?: string
avatar?: { cid: string; mimeType: string; [k: string]: unknown }
banner?: { cid: string; mimeType: string; [k: string]: unknown }
[k: string]: unknown
}

@ -10,6 +10,7 @@ export interface InputSchema {
displayName?: string
description?: string
avatar?: { cid: string; mimeType: string; [k: string]: unknown }
banner?: { cid: string; mimeType: string; [k: string]: unknown }
[k: string]: unknown
}

@ -74,10 +74,10 @@ const indexTs = (
{ name: 'Client', alias: 'XrpcClient' },
{ name: 'ServiceClient', alias: 'XrpcServiceClient' },
])
//= import {lexicons} from './lexicons'
//= import {schemas} from './lexicons'
file
.addImportDeclaration({ moduleSpecifier: './lexicons' })
.addNamedImports([{ name: 'lexicons' }])
.addNamedImports([{ name: 'schemas' }])
// generate type imports and re-exports
for (const lexicon of lexiconDocs) {
@ -126,9 +126,9 @@ const indexTs = (
initializer: 'new XrpcClient()',
})
//= constructor () {
//= this.xrpc.addLexicons(lexicons)
//= this.xrpc.addLexicons(schemas)
//= }
clientCls.addConstructor().setBodyText(`this.xrpc.addLexicons(lexicons)`)
clientCls.addConstructor().setBodyText(`this.xrpc.addLexicons(schemas)`)
//= service(serviceUri: string | URL): ServiceClient {
//= return new ServiceClient(this, this.xrpc.service(serviceUri))
//= }

@ -25,17 +25,52 @@ export const lexiconsTs = (project, lexicons: LexiconDoc[]) =>
.addImportDeclaration({
moduleSpecifier: '@atproto/lexicon',
})
.addNamedImports([{ name: 'LexiconDoc' }])
.addNamedImports([{ name: 'LexiconDoc' }, { name: 'Lexicons' }])
//= export const lexicons: LexiconDoc[] = [...]
//= export const schemaDict: Record<string, LexiconDoc> = {...}
file.addVariableStatement({
isExported: true,
declarationKind: VariableDeclarationKind.Const,
declarations: [
{
name: 'schemaDict',
initializer: JSON.stringify(
lexicons.reduce(
(acc, cur) => ({
...acc,
[nsidToEnum(cur.id)]: cur,
}),
{},
),
null,
2,
),
},
],
})
//= export const schemas: LexiconDoc[] = Object.values(schemaDict) as LexiconDoc[]
file.addVariableStatement({
isExported: true,
declarationKind: VariableDeclarationKind.Const,
declarations: [
{
name: 'schemas',
type: 'LexiconDoc[]',
initializer: 'Object.values(schemaDict) as LexiconDoc[]',
},
],
})
//= export const lexicons: Lexicons = new Lexicons(schemas)
file.addVariableStatement({
isExported: true,
declarationKind: VariableDeclarationKind.Const,
declarations: [
{
name: 'lexicons',
type: 'LexiconDoc[]',
initializer: JSON.stringify(lexicons, null, 2),
type: 'Lexicons',
initializer: 'new Lexicons(schemas)',
},
],
})

@ -76,13 +76,13 @@ const indexTs = (
xrpcImport.addNamedImport({
name: 'AuthVerifier',
})
//= import {lexicons} from './lexicons'
//= import {schemas} from './lexicons'
file
.addImportDeclaration({
moduleSpecifier: './lexicons',
})
.addNamedImport({
name: 'lexicons',
name: 'schemas',
})
// generate type imports
@ -159,7 +159,7 @@ const indexTs = (
}
//= constructor (options?: XrpcOptions) {
//= this.xrpc = createXrpcServer(lexicons, options)
//= this.xrpc = createXrpcServer(schemas, options)
//= {namespace declarations}
//= }
serverCls
@ -170,7 +170,7 @@ const indexTs = (
})
.setBodyText(
[
'this.xrpc = createXrpcServer(lexicons, options)',
'this.xrpc = createXrpcServer(schemas, options)',
...nsidTree.map(
(ns) => `this.${ns.propName} = new ${ns.className}(this)`,
),

@ -4,7 +4,7 @@ import { PlcClient } from '@atproto/plc'
import * as crypto from '@atproto/crypto'
import * as handleLib from '@atproto/handle'
import * as locals from '../../../../locals'
import * as lexicons from '../../../../lexicon/lexicons'
import * as lex from '../../../../lexicon/lexicons'
import { TID } from '@atproto/common'
import { UserAlreadyExistsError } from '../../../../db'
import * as repo from '../../../../repo'
@ -74,7 +74,7 @@ export default function (server: Server) {
// Now that we have a real did, we create the declaration & replace the tempDid
// and setup the repo root. This _should_ succeed under typical conditions.
const declaration = {
$type: lexicons.ids.AppBskySystemDeclaration,
$type: lex.ids.AppBskySystemDeclaration,
actorType: APP_BSKY_SYSTEM.ActorScene,
}
await dbTxn.finalizeDid(handle, did, tempDid, declaration)
@ -100,13 +100,13 @@ export default function (server: Server) {
const sceneWrites = await repo.prepareCreates(did, [
{
action: 'create',
collection: lexicons.ids.AppBskySystemDeclaration,
collection: lex.ids.AppBskySystemDeclaration,
rkey: 'self',
value: declaration,
},
{
action: 'create',
collection: lexicons.ids.AppBskyGraphAssertion,
collection: lex.ids.AppBskyGraphAssertion,
rkey: TID.nextStr(),
value: {
assertion: APP_BSKY_GRAPH.AssertCreator,
@ -119,7 +119,7 @@ export default function (server: Server) {
},
{
action: 'create',
collection: lexicons.ids.AppBskyGraphAssertion,
collection: lex.ids.AppBskyGraphAssertion,
rkey: TID.nextStr(),
value: {
assertion: APP_BSKY_GRAPH.AssertMember,
@ -136,7 +136,7 @@ export default function (server: Server) {
const userWrites = await repo.prepareCreates(requester, [
{
action: 'create',
collection: lexicons.ids.AppBskyGraphConfirmation,
collection: lex.ids.AppBskyGraphConfirmation,
rkey: TID.nextStr(),
value: {
originator: {
@ -152,7 +152,7 @@ export default function (server: Server) {
},
{
action: 'create',
collection: lexicons.ids.AppBskyGraphConfirmation,
collection: lex.ids.AppBskyGraphConfirmation,
rkey: TID.nextStr(),
value: {
originator: {

@ -31,6 +31,7 @@ export default function (server: Server) {
'profile.displayName as displayName',
'profile.description as description',
'profile.avatarCid as avatarCid',
'profile.bannerCid as bannerCid',
db.db
.selectFrom('follow')
.whereRef('creator', '=', ref('did_handle.did'))
@ -78,6 +79,10 @@ export default function (server: Server) {
? imgUriBuilder.getCommonSignedUri('avatar', queryRes.avatarCid)
: undefined
const banner = queryRes.bannerCid
? imgUriBuilder.getCommonSignedUri('banner', queryRes.bannerCid)
: undefined
return {
encoding: 'application/json',
body: {
@ -88,6 +93,7 @@ export default function (server: Server) {
displayName: queryRes.displayName || undefined,
description: queryRes.description || undefined,
avatar: avatar,
banner: banner,
followsCount: queryRes.followsCount,
followersCount: queryRes.followersCount,
membersCount: queryRes.membersCount,

@ -46,6 +46,7 @@ export default function (server: Server) {
displayName: input.body.displayName || current.displayName,
description: input.body.description || current.description,
avatar: input.body.avatar || current.avatar,
banner: input.body.banner || current.banner,
}
} else {
updated = {
@ -53,6 +54,7 @@ export default function (server: Server) {
displayName: input.body.displayName,
description: input.body.description,
avatar: input.body.avatar,
banner: input.body.banner,
}
}
updated = common.noUndefinedVals(updated)
@ -97,6 +99,7 @@ export default function (server: Server) {
displayName: updated.displayName,
description: updated.description,
avatarCid: updated.avatar?.cid,
bannerCid: updated.banner?.cid,
indexedAt: now,
})
.where('uri', '=', uri.toString())

@ -7,7 +7,7 @@ import * as locals from '../../../locals'
import { countAll } from '../../../db/util'
import { UserAlreadyExistsError } from '../../../db'
import { grantRefreshToken } from './util/auth'
import * as lexicons from '../../../lexicon/lexicons'
import * as lex from '../../../lexicon/lexicons'
import * as repo from '../../../repo'
import { cidForData } from '@atproto/common'
@ -130,7 +130,7 @@ export default function (server: Server) {
// Now that we have a real did, we create the declaration & replace the tempDid
// and setup the repo root. This _should_ succeed under typical conditions.
const declaration = {
$type: lexicons.ids.AppBskySystemDeclaration,
$type: lex.ids.AppBskySystemDeclaration,
actorType: APP_BSKY_SYSTEM.ActorUser,
}
await dbTxn.finalizeDid(handle, did, tempDid, declaration)
@ -147,7 +147,7 @@ export default function (server: Server) {
const write = await repo.prepareCreate(did, {
action: 'create',
collection: lexicons.ids.AppBskySystemDeclaration,
collection: lex.ids.AppBskySystemDeclaration,
rkey: 'self',
value: declaration,
})

@ -5,7 +5,7 @@ import { AtUri } from '@atproto/uri'
import * as didResolver from '@atproto/did-resolver'
import { DeleteOp, RecordCreateOp } from '@atproto/repo'
import * as locals from '../../../locals'
import * as dbSchemas from '../../../db/schemas'
import { lexicons } from '../../../lexicon/lexicons'
import { TID } from '@atproto/common'
import * as repo from '../../../repo'
import ServerAuth from '../../../auth'
@ -182,7 +182,7 @@ export default function (server: Server) {
// determine key type. if undefined, repo assigns a TID
const keyType = (
dbSchemas.records.getDefOrThrow(collection, ['record']) as LexRecord
lexicons.getDefOrThrow(collection, ['record']) as LexRecord
).key
let rkey: string
if (keyType && keyType.startsWith('literal')) {

@ -0,0 +1,12 @@
import { Kysely } from 'kysely'
export async function up(db: Kysely<unknown>): Promise<void> {
await db.schema
.alterTable('profile')
.addColumn('bannerCid', 'varchar')
.execute()
}
export async function down(db: Kysely<unknown>): Promise<void> {
await db.schema.alterTable('profile').dropColumn('bannerCid').execute()
}

@ -5,3 +5,4 @@
export * as _20221021T162202001Z from './20221021T162202001Z-init'
export * as _20221116T234458063Z from './20221116T234458063Z-duplicate-records'
export * as _20221202T212459280Z from './20221202T212459280Z-blobs'
export * as _20221209T210026294Z from './20221209T210026294Z-banners'

@ -4,10 +4,10 @@ import { Kysely } from 'kysely'
import { CID } from 'multiformats/cid'
import { DatabaseSchema } from './database-schema'
import { Message } from './message-queue/messages'
import * as schemas from './schemas'
import { lexicons } from '../lexicon/lexicons'
type RecordProcessorParams<T, S> = {
schemaId: string
lexId: string
insertFn: (
db: Kysely<DatabaseSchema>,
uri: AtUri,
@ -31,7 +31,7 @@ export class RecordProcessor<T, S> {
private db: Kysely<DatabaseSchema>,
private params: RecordProcessorParams<T, S>,
) {
this.collection = this.params.schemaId
this.collection = this.params.lexId
}
matchesSchema(obj: unknown): obj is T {
@ -44,7 +44,7 @@ export class RecordProcessor<T, S> {
}
assertValidRecord(obj: unknown): void {
schemas.records.assertValidRecord(this.params.schemaId, obj)
lexicons.assertValidRecord(this.params.lexId, obj)
}
async insertRecord(
@ -54,7 +54,7 @@ export class RecordProcessor<T, S> {
timestamp?: string,
): Promise<Message[]> {
if (!this.matchesSchema(obj)) {
throw new Error(`Record does not match schema: ${this.params.schemaId}`)
throw new Error(`Record does not match schema: ${this.params.lexId}`)
}
const inserted = await this.params.insertFn(
this.db,

@ -3,13 +3,13 @@ import { AtUri } from '@atproto/uri'
import { CID } from 'multiformats/cid'
import * as Assertion from '../../lexicon/types/app/bsky/graph/assertion'
import { Assertion as IndexedAssertion } from '../tables/assertion'
import * as schemas from '../schemas'
import * as lex from '../../lexicon/lexicons'
import * as messages from '../message-queue/messages'
import { Message } from '../message-queue/messages'
import DatabaseSchema from '../database-schema'
import RecordProcessor from '../record-processor'
const schemaId = schemas.ids.AppBskyGraphAssertion
const lexId = lex.ids.AppBskyGraphAssertion
const insertFn = async (
db: Kysely<DatabaseSchema>,
@ -98,7 +98,7 @@ export type PluginType = RecordProcessor<Assertion.Record, IndexedAssertion>
export const makePlugin = (db: Kysely<DatabaseSchema>): PluginType => {
return new RecordProcessor(db, {
schemaId,
lexId,
insertFn,
findDuplicate,
deleteFn,

@ -3,14 +3,14 @@ import { AtUri } from '@atproto/uri'
import { CID } from 'multiformats/cid'
import * as Confirmation from '../../lexicon/types/app/bsky/graph/confirmation'
import { Assertion as IndexedAssertion } from '../tables/assertion'
import * as schemas from '../schemas'
import * as lex from '../../lexicon/lexicons'
import * as messages from '../message-queue/messages'
import { Message } from '../message-queue/messages'
import { APP_BSKY_GRAPH } from '../../lexicon'
import DatabaseSchema from '../database-schema'
import RecordProcessor from '../record-processor'
const schemaId = schemas.ids.AppBskyGraphConfirmation
const lexId = lex.ids.AppBskyGraphConfirmation
const insertFn = async (
db: Kysely<DatabaseSchema>,
@ -89,7 +89,7 @@ export type PluginType = RecordProcessor<Confirmation.Record, IndexedAssertion>
export const makePlugin = (db: Kysely<DatabaseSchema>): PluginType => {
return new RecordProcessor(db, {
schemaId,
lexId,
insertFn,
findDuplicate,
deleteFn,

@ -2,13 +2,13 @@ import { Kysely } from 'kysely'
import { AtUri } from '@atproto/uri'
import { CID } from 'multiformats/cid'
import * as Declaration from '../../lexicon/types/app/bsky/system/declaration'
import * as schemas from '../schemas'
import * as lex from '../../lexicon/lexicons'
import { DidHandle } from '../tables/did-handle'
import { Message } from '../message-queue/messages'
import RecordProcessor from '../record-processor'
import DatabaseSchema from '../database-schema'
const schemaId = schemas.ids.AppBskySystemDeclaration
const lexId = lex.ids.AppBskySystemDeclaration
const insertFn = async (
db: Kysely<DatabaseSchema>,
@ -47,7 +47,7 @@ export type PluginType = RecordProcessor<Declaration.Record, DidHandle>
export const makePlugin = (db: Kysely<DatabaseSchema>): PluginType => {
return new RecordProcessor(db, {
schemaId,
lexId,
insertFn,
findDuplicate,
deleteFn,

@ -3,13 +3,13 @@ import { AtUri } from '@atproto/uri'
import { CID } from 'multiformats/cid'
import * as Follow from '../../lexicon/types/app/bsky/graph/follow'
import { Follow as IndexedFollow } from '../tables/follow'
import * as schemas from '../schemas'
import * as lex from '../../lexicon/lexicons'
import * as messages from '../message-queue/messages'
import { Message } from '../message-queue/messages'
import DatabaseSchema from '../database-schema'
import RecordProcessor from '../record-processor'
const schemaId = schemas.ids.AppBskyGraphFollow
const lexId = lex.ids.AppBskyGraphFollow
const insertFn = async (
db: Kysely<DatabaseSchema>,
@ -85,7 +85,7 @@ export type PluginType = RecordProcessor<Follow.Record, IndexedFollow>
export const makePlugin = (db: Kysely<DatabaseSchema>): PluginType => {
return new RecordProcessor(db, {
schemaId,
lexId,
insertFn,
findDuplicate,
deleteFn,

@ -3,7 +3,7 @@ import { AtUri } from '@atproto/uri'
import { CID } from 'multiformats/cid'
import * as Post from '../../lexicon/types/app/bsky/feed/post'
import * as PostTables from '../tables/post'
import * as schemas from '../schemas'
import * as lex from '../../lexicon/lexicons'
import * as messages from '../message-queue/messages'
import { Message } from '../message-queue/messages'
import DatabaseSchema from '../database-schema'
@ -14,7 +14,7 @@ type IndexedPost = {
entities: PostTables.PostEntity[]
}
const schemaId = schemas.ids.AppBskyFeedPost
const lexId = lex.ids.AppBskyFeedPost
const insertFn = async (
db: Kysely<DatabaseSchema>,
@ -129,7 +129,7 @@ export type PluginType = RecordProcessor<Post.Record, IndexedPost>
export const makePlugin = (db: Kysely<DatabaseSchema>): PluginType => {
return new RecordProcessor(db, {
schemaId,
lexId,
insertFn,
findDuplicate,
deleteFn,

@ -3,12 +3,12 @@ import { AtUri } from '@atproto/uri'
import { CID } from 'multiformats/cid'
import * as Profile from '../../lexicon/types/app/bsky/actor/profile'
import { Profile as IndexedProfile } from '../tables/profile'
import * as schemas from '../schemas'
import * as lex from '../../lexicon/lexicons'
import { Message } from '../message-queue/messages'
import DatabaseSchema from '../database-schema'
import RecordProcessor from '../record-processor'
const schemaId = schemas.ids.AppBskyActorProfile
const lexId = lex.ids.AppBskyActorProfile
const insertFn = async (
db: Kysely<DatabaseSchema>,
@ -26,6 +26,7 @@ const insertFn = async (
displayName: obj.displayName,
description: obj.description,
avatarCid: obj.avatar?.cid,
bannerCid: obj.banner?.cid,
indexedAt: new Date().toISOString(),
})
.onConflict((oc) => oc.doNothing())
@ -62,7 +63,7 @@ export type PluginType = RecordProcessor<Profile.Record, IndexedProfile>
export const makePlugin = (db: Kysely<DatabaseSchema>): PluginType => {
return new RecordProcessor(db, {
schemaId,
lexId,
insertFn,
findDuplicate,
deleteFn,

@ -2,14 +2,14 @@ import { Kysely } from 'kysely'
import { AtUri } from '@atproto/uri'
import * as Repost from '../../lexicon/types/app/bsky/feed/repost'
import { Repost as IndexedRepost } from '../tables/repost'
import * as schemas from '../schemas'
import * as lex from '../../lexicon/lexicons'
import { CID } from 'multiformats/cid'
import * as messages from '../message-queue/messages'
import { Message } from '../message-queue/messages'
import { DatabaseSchema } from '../database-schema'
import RecordProcessor from '../record-processor'
const schemaId = schemas.ids.AppBskyFeedRepost
const lexId = lex.ids.AppBskyFeedRepost
const insertFn = async (
db: Kysely<DatabaseSchema>,
@ -86,7 +86,7 @@ export type PluginType = RecordProcessor<Repost.Record, IndexedRepost>
export const makePlugin = (db: Kysely<DatabaseSchema>): PluginType => {
return new RecordProcessor(db, {
schemaId,
lexId,
insertFn,
findDuplicate,
deleteFn,

@ -2,14 +2,14 @@ import { Kysely } from 'kysely'
import { AtUri } from '@atproto/uri'
import * as Trend from '../../lexicon/types/app/bsky/feed/trend'
import { Trend as IndexedTrend } from '../tables/trend'
import * as schemas from '../schemas'
import * as lex from '../../lexicon/lexicons'
import { CID } from 'multiformats/cid'
import * as messages from '../message-queue/messages'
import { Message } from '../message-queue/messages'
import DatabaseSchema from '../database-schema'
import RecordProcessor from '../record-processor'
const schemaId = schemas.ids.AppBskyFeedTrend
const lexId = lex.ids.AppBskyFeedTrend
const insertFn = async (
db: Kysely<DatabaseSchema>,
@ -86,7 +86,7 @@ export type PluginType = RecordProcessor<Trend.Record, IndexedTrend>
export const makePlugin = (db: Kysely<DatabaseSchema>): PluginType => {
return new RecordProcessor(db, {
schemaId,
lexId,
insertFn,
findDuplicate,
deleteFn,

@ -3,13 +3,13 @@ import { AtUri } from '@atproto/uri'
import { CID } from 'multiformats/cid'
import * as Vote from '../../lexicon/types/app/bsky/feed/vote'
import { Vote as IndexedVote } from '../tables/vote'
import * as schemas from '../schemas'
import * as lex from '../../lexicon/lexicons'
import * as messages from '../message-queue/messages'
import { Message } from '../message-queue/messages'
import { DatabaseSchema } from '../database-schema'
import RecordProcessor from '../record-processor'
const schemaId = schemas.ids.AppBskyFeedVote
const lexId = lex.ids.AppBskyFeedVote
const insertFn = async (
db: Kysely<DatabaseSchema>,
@ -107,7 +107,7 @@ export type PluginType = RecordProcessor<Vote.Record, IndexedVote>
export const makePlugin = (db: Kysely<DatabaseSchema>): PluginType => {
return new RecordProcessor(db, {
schemaId,
lexId,
insertFn,
findDuplicate,
deleteFn,

@ -1,6 +0,0 @@
import { Lexicons } from '@atproto/lexicon'
import { lexicons } from '../lexicon/lexicons'
export const records = new Lexicons(lexicons)
export { ids } from '../lexicon/lexicons'

@ -7,6 +7,7 @@ export interface Profile {
displayName: string
description: string | null
avatarCid: string | null
bannerCid: string | null
indexedAt: string
}
export type PartialDB = { [tableName]: Profile }

@ -3,7 +3,7 @@ import * as uint8arrays from 'uint8arrays'
import { CID } from 'multiformats/cid'
import { Options } from './util'
type CommonSignedUris = 'avatar'
type CommonSignedUris = 'avatar' | 'banner'
export class ImageUriBuilder {
public endpoint: string
@ -50,6 +50,15 @@ export class ImageUriBuilder {
width: 250,
min: true,
})
} else if (id === 'banner') {
return this.getSignedUri({
cid: typeof cid === 'string' ? CID.parse(cid) : cid,
format: 'jpeg',
fit: 'cover',
height: 750,
width: 250,
min: true,
})
}
return undefined
}

@ -7,7 +7,7 @@ import {
Options as XrpcOptions,
AuthVerifier,
} from '@atproto/xrpc-server'
import { lexicons } from './lexicons'
import { schemas } from './lexicons'
import * as ComAtprotoAccountCreate from './types/com/atproto/account/create'
import * as ComAtprotoAccountCreateInviteCode from './types/com/atproto/account/createInviteCode'
import * as ComAtprotoAccountDelete from './types/com/atproto/account/delete'
@ -71,7 +71,7 @@ export class Server {
app: AppNS
constructor(options?: XrpcOptions) {
this.xrpc = createXrpcServer(lexicons, options)
this.xrpc = createXrpcServer(schemas, options)
this.com = new ComNS(this)
this.app = new AppNS(this)
}

@ -1,10 +1,10 @@
/**
* GENERATED CODE - DO NOT MODIFY
*/
import { LexiconDoc } from '@atproto/lexicon'
import { LexiconDoc, Lexicons } from '@atproto/lexicon'
export const lexicons: LexiconDoc[] = [
{
export const schemaDict = {
ComAtprotoAccountCreate: {
lexicon: 1,
id: 'com.atproto.account.create',
defs: {
@ -73,7 +73,7 @@ export const lexicons: LexiconDoc[] = [
},
},
},
{
ComAtprotoAccountCreateInviteCode: {
lexicon: 1,
id: 'com.atproto.account.createInviteCode',
defs: {
@ -107,7 +107,7 @@ export const lexicons: LexiconDoc[] = [
},
},
},
{
ComAtprotoAccountDelete: {
lexicon: 1,
id: 'com.atproto.account.delete',
defs: {
@ -117,7 +117,7 @@ export const lexicons: LexiconDoc[] = [
},
},
},
{
ComAtprotoAccountGet: {
lexicon: 1,
id: 'com.atproto.account.get',
defs: {
@ -127,7 +127,7 @@ export const lexicons: LexiconDoc[] = [
},
},
},
{
ComAtprotoAccountRequestPasswordReset: {
lexicon: 1,
id: 'com.atproto.account.requestPasswordReset',
defs: {
@ -149,7 +149,7 @@ export const lexicons: LexiconDoc[] = [
},
},
},
{
ComAtprotoAccountResetPassword: {
lexicon: 1,
id: 'com.atproto.account.resetPassword',
defs: {
@ -182,7 +182,7 @@ export const lexicons: LexiconDoc[] = [
},
},
},
{
ComAtprotoBlobUpload: {
lexicon: 1,
id: 'com.atproto.blob.upload',
defs: {
@ -213,7 +213,7 @@ export const lexicons: LexiconDoc[] = [
},
},
},
{
ComAtprotoHandleResolve: {
lexicon: 1,
id: 'com.atproto.handle.resolve',
defs: {
@ -245,7 +245,7 @@ export const lexicons: LexiconDoc[] = [
},
},
},
{
ComAtprotoRepoBatchWrite: {
lexicon: 1,
id: 'com.atproto.repo.batchWrite',
defs: {
@ -339,7 +339,7 @@ export const lexicons: LexiconDoc[] = [
},
},
},
{
ComAtprotoRepoCreateRecord: {
lexicon: 1,
id: 'com.atproto.repo.createRecord',
defs: {
@ -390,7 +390,7 @@ export const lexicons: LexiconDoc[] = [
},
},
},
{
ComAtprotoRepoDeleteRecord: {
lexicon: 1,
id: 'com.atproto.repo.deleteRecord',
defs: {
@ -421,7 +421,7 @@ export const lexicons: LexiconDoc[] = [
},
},
},
{
ComAtprotoRepoDescribe: {
lexicon: 1,
id: 'com.atproto.repo.describe',
defs: {
@ -475,7 +475,7 @@ export const lexicons: LexiconDoc[] = [
},
},
},
{
ComAtprotoRepoGetRecord: {
lexicon: 1,
id: 'com.atproto.repo.getRecord',
defs: {
@ -526,7 +526,7 @@ export const lexicons: LexiconDoc[] = [
},
},
},
{
ComAtprotoRepoListRecords: {
lexicon: 1,
id: 'com.atproto.repo.listRecords',
defs: {
@ -603,7 +603,7 @@ export const lexicons: LexiconDoc[] = [
},
},
},
{
ComAtprotoRepoPutRecord: {
lexicon: 1,
id: 'com.atproto.repo.putRecord',
defs: {
@ -658,7 +658,7 @@ export const lexicons: LexiconDoc[] = [
},
},
},
{
ComAtprotoRepoStrongRef: {
lexicon: 1,
id: 'com.atproto.repo.strongRef',
description: 'A URI with a content-hash fingerprint.',
@ -677,7 +677,7 @@ export const lexicons: LexiconDoc[] = [
},
},
},
{
ComAtprotoServerGetAccountsConfig: {
lexicon: 1,
id: 'com.atproto.server.getAccountsConfig',
defs: {
@ -721,7 +721,7 @@ export const lexicons: LexiconDoc[] = [
},
},
},
{
ComAtprotoSessionCreate: {
lexicon: 1,
id: 'com.atproto.session.create',
defs: {
@ -767,7 +767,7 @@ export const lexicons: LexiconDoc[] = [
},
},
},
{
ComAtprotoSessionDelete: {
lexicon: 1,
id: 'com.atproto.session.delete',
defs: {
@ -777,7 +777,7 @@ export const lexicons: LexiconDoc[] = [
},
},
},
{
ComAtprotoSessionGet: {
lexicon: 1,
id: 'com.atproto.session.get',
defs: {
@ -802,7 +802,7 @@ export const lexicons: LexiconDoc[] = [
},
},
},
{
ComAtprotoSessionRefresh: {
lexicon: 1,
id: 'com.atproto.session.refresh',
defs: {
@ -833,7 +833,7 @@ export const lexicons: LexiconDoc[] = [
},
},
},
{
ComAtprotoSyncGetRepo: {
lexicon: 1,
id: 'com.atproto.sync.getRepo',
defs: {
@ -860,7 +860,7 @@ export const lexicons: LexiconDoc[] = [
},
},
},
{
ComAtprotoSyncGetRoot: {
lexicon: 1,
id: 'com.atproto.sync.getRoot',
defs: {
@ -892,7 +892,7 @@ export const lexicons: LexiconDoc[] = [
},
},
},
{
ComAtprotoSyncUpdateRepo: {
lexicon: 1,
id: 'com.atproto.sync.updateRepo',
defs: {
@ -915,7 +915,7 @@ export const lexicons: LexiconDoc[] = [
},
},
},
{
AppBskyActorCreateScene: {
lexicon: 1,
id: 'app.bsky.actor.createScene',
defs: {
@ -967,7 +967,7 @@ export const lexicons: LexiconDoc[] = [
},
},
},
{
AppBskyActorGetProfile: {
lexicon: 1,
id: 'app.bsky.actor.getProfile',
defs: {
@ -1021,6 +1021,9 @@ export const lexicons: LexiconDoc[] = [
avatar: {
type: 'string',
},
banner: {
type: 'string',
},
followersCount: {
type: 'integer',
},
@ -1054,7 +1057,7 @@ export const lexicons: LexiconDoc[] = [
},
},
},
{
AppBskyActorGetSuggestions: {
lexicon: 1,
id: 'app.bsky.actor.getSuggestions',
defs: {
@ -1139,7 +1142,7 @@ export const lexicons: LexiconDoc[] = [
},
},
},
{
AppBskyActorProfile: {
lexicon: 1,
id: 'app.bsky.actor.profile',
defs: {
@ -1165,12 +1168,19 @@ export const lexicons: LexiconDoc[] = [
maxHeight: 500,
maxSize: 300000,
},
banner: {
type: 'image',
accept: ['image/png', 'image/jpeg'],
maxWidth: 1500,
maxHeight: 500,
maxSize: 500000,
},
},
},
},
},
},
{
AppBskyActorRef: {
lexicon: 1,
id: 'app.bsky.actor.ref',
description: 'A reference to an actor in the network.',
@ -1212,7 +1222,7 @@ export const lexicons: LexiconDoc[] = [
},
},
},
{
AppBskyActorSearch: {
lexicon: 1,
id: 'app.bsky.actor.search',
defs: {
@ -1288,7 +1298,7 @@ export const lexicons: LexiconDoc[] = [
},
},
},
{
AppBskyActorSearchTypeahead: {
lexicon: 1,
id: 'app.bsky.actor.searchTypeahead',
defs: {
@ -1352,7 +1362,7 @@ export const lexicons: LexiconDoc[] = [
},
},
},
{
AppBskyActorUpdateProfile: {
lexicon: 1,
id: 'app.bsky.actor.updateProfile',
defs: {
@ -1382,6 +1392,13 @@ export const lexicons: LexiconDoc[] = [
maxHeight: 500,
maxSize: 100000,
},
banner: {
type: 'image',
accept: ['image/png', 'image/jpeg'],
maxWidth: 1500,
maxHeight: 500,
maxSize: 500000,
},
},
},
},
@ -1406,7 +1423,7 @@ export const lexicons: LexiconDoc[] = [
},
},
},
{
AppBskyFeedEmbed: {
lexicon: 1,
id: 'app.bsky.feed.embed',
description:
@ -1486,7 +1503,7 @@ export const lexicons: LexiconDoc[] = [
},
},
},
{
AppBskyFeedGetAuthorFeed: {
lexicon: 1,
id: 'app.bsky.feed.getAuthorFeed',
defs: {
@ -1607,7 +1624,7 @@ export const lexicons: LexiconDoc[] = [
},
},
},
{
AppBskyFeedGetPostThread: {
lexicon: 1,
id: 'app.bsky.feed.getPostThread',
defs: {
@ -1745,7 +1762,7 @@ export const lexicons: LexiconDoc[] = [
},
},
},
{
AppBskyFeedGetRepostedBy: {
lexicon: 1,
id: 'app.bsky.feed.getRepostedBy',
defs: {
@ -1829,7 +1846,7 @@ export const lexicons: LexiconDoc[] = [
},
},
},
{
AppBskyFeedGetTimeline: {
lexicon: 1,
id: 'app.bsky.feed.getTimeline',
defs: {
@ -1949,7 +1966,7 @@ export const lexicons: LexiconDoc[] = [
},
},
},
{
AppBskyFeedGetVotes: {
lexicon: 1,
id: 'app.bsky.feed.getVotes',
defs: {
@ -2028,7 +2045,7 @@ export const lexicons: LexiconDoc[] = [
},
},
},
{
AppBskyFeedPost: {
lexicon: 1,
id: 'app.bsky.feed.post',
defs: {
@ -2108,7 +2125,7 @@ export const lexicons: LexiconDoc[] = [
},
},
},
{
AppBskyFeedRepost: {
lexicon: 1,
id: 'app.bsky.feed.repost',
defs: {
@ -2131,7 +2148,7 @@ export const lexicons: LexiconDoc[] = [
},
},
},
{
AppBskyFeedSetVote: {
lexicon: 1,
id: 'app.bsky.feed.setVote',
defs: {
@ -2172,7 +2189,7 @@ export const lexicons: LexiconDoc[] = [
},
},
},
{
AppBskyFeedTrend: {
lexicon: 1,
id: 'app.bsky.feed.trend',
defs: {
@ -2195,7 +2212,7 @@ export const lexicons: LexiconDoc[] = [
},
},
},
{
AppBskyFeedVote: {
lexicon: 1,
id: 'app.bsky.feed.vote',
defs: {
@ -2222,7 +2239,7 @@ export const lexicons: LexiconDoc[] = [
},
},
},
{
AppBskyGraphAssertCreator: {
lexicon: 1,
id: 'app.bsky.graph.assertCreator',
defs: {
@ -2233,7 +2250,7 @@ export const lexicons: LexiconDoc[] = [
},
},
},
{
AppBskyGraphAssertMember: {
lexicon: 1,
id: 'app.bsky.graph.assertMember',
defs: {
@ -2244,7 +2261,7 @@ export const lexicons: LexiconDoc[] = [
},
},
},
{
AppBskyGraphAssertion: {
lexicon: 1,
id: 'app.bsky.graph.assertion',
defs: {
@ -2270,7 +2287,7 @@ export const lexicons: LexiconDoc[] = [
},
},
},
{
AppBskyGraphConfirmation: {
lexicon: 1,
id: 'app.bsky.graph.confirmation',
defs: {
@ -2297,7 +2314,7 @@ export const lexicons: LexiconDoc[] = [
},
},
},
{
AppBskyGraphFollow: {
lexicon: 1,
id: 'app.bsky.graph.follow',
defs: {
@ -2321,7 +2338,7 @@ export const lexicons: LexiconDoc[] = [
},
},
},
{
AppBskyGraphGetAssertions: {
lexicon: 1,
id: 'app.bsky.graph.getAssertions',
defs: {
@ -2435,7 +2452,7 @@ export const lexicons: LexiconDoc[] = [
},
},
},
{
AppBskyGraphGetFollowers: {
lexicon: 1,
id: 'app.bsky.graph.getFollowers',
defs: {
@ -2515,7 +2532,7 @@ export const lexicons: LexiconDoc[] = [
},
},
},
{
AppBskyGraphGetFollows: {
lexicon: 1,
id: 'app.bsky.graph.getFollows',
defs: {
@ -2592,7 +2609,7 @@ export const lexicons: LexiconDoc[] = [
},
},
},
{
AppBskyGraphGetMembers: {
lexicon: 1,
id: 'app.bsky.graph.getMembers',
defs: {
@ -2669,7 +2686,7 @@ export const lexicons: LexiconDoc[] = [
},
},
},
{
AppBskyGraphGetMemberships: {
lexicon: 1,
id: 'app.bsky.graph.getMemberships',
defs: {
@ -2746,7 +2763,7 @@ export const lexicons: LexiconDoc[] = [
},
},
},
{
AppBskyNotificationGetCount: {
lexicon: 1,
id: 'app.bsky.notification.getCount',
defs: {
@ -2767,7 +2784,7 @@ export const lexicons: LexiconDoc[] = [
},
},
},
{
AppBskyNotificationList: {
lexicon: 1,
id: 'app.bsky.notification.list',
defs: {
@ -2859,7 +2876,7 @@ export const lexicons: LexiconDoc[] = [
},
},
},
{
AppBskyNotificationUpdateSeen: {
lexicon: 1,
id: 'app.bsky.notification.updateSeen',
defs: {
@ -2881,7 +2898,7 @@ export const lexicons: LexiconDoc[] = [
},
},
},
{
AppBskySystemActorScene: {
lexicon: 1,
id: 'app.bsky.system.actorScene',
defs: {
@ -2892,7 +2909,7 @@ export const lexicons: LexiconDoc[] = [
},
},
},
{
AppBskySystemActorUser: {
lexicon: 1,
id: 'app.bsky.system.actorUser',
defs: {
@ -2903,7 +2920,7 @@ export const lexicons: LexiconDoc[] = [
},
},
},
{
AppBskySystemDeclRef: {
lexicon: 1,
id: 'app.bsky.system.declRef',
defs: {
@ -2926,7 +2943,7 @@ export const lexicons: LexiconDoc[] = [
},
},
},
{
AppBskySystemDeclaration: {
lexicon: 1,
id: 'app.bsky.system.declaration',
defs: {
@ -2951,7 +2968,9 @@ export const lexicons: LexiconDoc[] = [
},
},
},
]
}
export const schemas: LexiconDoc[] = Object.values(schemaDict) as LexiconDoc[]
export const lexicons: Lexicons = new Lexicons(schemas)
export const ids = {
ComAtprotoAccountCreate: 'com.atproto.account.create',
ComAtprotoAccountCreateInviteCode: 'com.atproto.account.createInviteCode',

@ -19,6 +19,7 @@ export interface OutputSchema {
displayName?: string
description?: string
avatar?: string
banner?: string
followersCount: number
followsCount: number
membersCount: number

@ -5,5 +5,6 @@ export interface Record {
displayName: string
description?: string
avatar?: { cid: string; mimeType: string; [k: string]: unknown }
banner?: { cid: string; mimeType: string; [k: string]: unknown }
[k: string]: unknown
}

@ -11,6 +11,7 @@ export interface InputSchema {
displayName?: string
description?: string
avatar?: { cid: string; mimeType: string; [k: string]: unknown }
banner?: { cid: string; mimeType: string; [k: string]: unknown }
[k: string]: unknown
}

@ -13,30 +13,33 @@ import {
PreparedDelete,
PreparedWrites,
BlobRef,
ImageConstraint,
} from './types'
import { ids as lexIds } from '../lexicon/lexicons'
import * as lex from '../lexicon/lexicons'
// @TODO do this dynamically off of schemas
export const blobsForWrite = (
write: RecordCreateOp | RecordUpdateOp,
): BlobRef[] => {
if (write.collection === lexIds.AppBskyActorProfile) {
if (write.collection === lex.ids.AppBskyActorProfile) {
const doc = lex.schemaDict.AppBskyActorProfile
const refs: BlobRef[] = []
if (write.value.avatar) {
return [
{
cid: CID.parse(write.value.avatar.cid),
mimeType: write.value.avatar.mimeType,
constraints: {
type: 'image',
accept: ['image/png', 'image/jpeg'],
maxWidth: 500,
maxHeight: 500,
maxSize: 300000,
},
},
]
refs.push({
cid: CID.parse(write.value.avatar.cid),
mimeType: write.value.avatar.mimeType,
constraints: doc.defs.main.record.properties.avatar as ImageConstraint,
})
}
if (write.value.banner) {
refs.push({
cid: CID.parse(write.value.banner.cid),
mimeType: write.value.banner.mimeType,
constraints: doc.defs.main.record.properties.banner as ImageConstraint,
})
}
return refs
}
return []
}

@ -1,7 +1,7 @@
import { AtUri } from '@atproto/uri'
import { CloseFn, runTestServer } from './_util'
import { Database } from '../src'
import * as schemas from '../src/db/schemas'
import * as lex from '../src/lexicon/lexicons'
import { cidForData, TID, valueToIpldBytes } from '@atproto/common'
import { CID } from 'multiformats/cid'
import { APP_BSKY_GRAPH } from '../src/lexicon'
@ -50,9 +50,9 @@ describe('duplicate record', () => {
}
it('dedupes reposts', async () => {
const subject = AtUri.make(did, schemas.ids.AppBskyFeedPost, TID.nextStr())
const subject = AtUri.make(did, lex.ids.AppBskyFeedPost, TID.nextStr())
const subjectCid = await putBlock(db, { test: 'blah' })
const coll = schemas.ids.AppBskyFeedRepost
const coll = lex.ids.AppBskyFeedRepost
const uris: AtUri[] = []
await db.transaction(async (tx) => {
for (let i = 0; i < 5; i++) {
@ -90,9 +90,9 @@ describe('duplicate record', () => {
})
it('dedupes trends', async () => {
const subject = AtUri.make(did, schemas.ids.AppBskyFeedPost, TID.nextStr())
const subject = AtUri.make(did, lex.ids.AppBskyFeedPost, TID.nextStr())
const subjectCid = await putBlock(db, { test: 'blah' })
const coll = schemas.ids.AppBskyFeedTrend
const coll = lex.ids.AppBskyFeedTrend
const uris: AtUri[] = []
await db.transaction(async (tx) => {
for (let i = 0; i < 5; i++) {
@ -130,9 +130,9 @@ describe('duplicate record', () => {
})
it('dedupes votes', async () => {
const subject = AtUri.make(did, schemas.ids.AppBskyFeedPost, TID.nextStr())
const subject = AtUri.make(did, lex.ids.AppBskyFeedPost, TID.nextStr())
const subjectCid = await putBlock(db, { test: 'blah' })
const coll = schemas.ids.AppBskyFeedVote
const coll = lex.ids.AppBskyFeedVote
const uris: AtUri[] = []
await db.transaction(async (tx) => {
for (let i = 0; i < 5; i++) {
@ -180,7 +180,7 @@ describe('duplicate record', () => {
it('dedupes follows', async () => {
const subjectCid = await putBlock(db, { test: 'blah' })
const coll = schemas.ids.AppBskyGraphFollow
const coll = lex.ids.AppBskyGraphFollow
const uris: AtUri[] = []
await db.transaction(async (tx) => {
for (let i = 0; i < 5; i++) {
@ -223,7 +223,7 @@ describe('duplicate record', () => {
const assertCids: CID[] = []
// make assertions
await db.transaction(async (tx) => {
const coll = schemas.ids.AppBskyGraphAssertion
const coll = lex.ids.AppBskyGraphAssertion
for (let i = 0; i < 5; i++) {
const assertion = {
$type: coll,
@ -245,7 +245,7 @@ describe('duplicate record', () => {
const confirmCids: CID[] = []
// make confirms on first assert
await db.transaction(async (tx) => {
const coll = schemas.ids.AppBskyGraphConfirmation
const coll = lex.ids.AppBskyGraphConfirmation
for (let i = 0; i < 5; i++) {
const follow = {
$type: coll,

@ -1,7 +1,7 @@
import { AtUri } from '@atproto/uri'
import { Database } from '../../src'
import { cidForData, TID } from '@atproto/common'
import * as schemas from '../../src/db/schemas'
import * as lex from '../../src/lexicon/lexicons'
import { APP_BSKY_GRAPH } from '../../src/lexicon'
describe('duplicate record', () => {
@ -37,15 +37,11 @@ describe('duplicate record', () => {
}
it('has duplicate records', async () => {
const subjectUri = AtUri.make(
did,
schemas.ids.AppBskyFeedPost,
TID.nextStr(),
)
const subjectUri = AtUri.make(did, lex.ids.AppBskyFeedPost, TID.nextStr())
const subjectCid = await cidForData({ test: 'blah' })
const subjectDid = 'did:example:bob'
const repost = {
$type: schemas.ids.AppBskyFeedRepost,
$type: lex.ids.AppBskyFeedRepost,
subject: {
uri: subjectUri.toString(),
cid: subjectCid.toString(),
@ -54,7 +50,7 @@ describe('duplicate record', () => {
}
await indexRecord(repost, 5)
const trend = {
$type: schemas.ids.AppBskyFeedTrend,
$type: lex.ids.AppBskyFeedTrend,
subject: {
uri: subjectUri.toString(),
cid: subjectCid.toString(),
@ -63,7 +59,7 @@ describe('duplicate record', () => {
}
await indexRecord(trend, 5)
const vote = {
$type: schemas.ids.AppBskyFeedVote,
$type: lex.ids.AppBskyFeedVote,
direction: 'up',
subject: {
uri: subjectUri.toString(),
@ -73,7 +69,7 @@ describe('duplicate record', () => {
}
await indexRecord(vote, 5)
const follow = {
$type: schemas.ids.AppBskyGraphFollow,
$type: lex.ids.AppBskyGraphFollow,
subject: {
did: subjectDid,
declarationCid: subjectCid.toString(),
@ -82,7 +78,7 @@ describe('duplicate record', () => {
}
await indexRecord(follow, 5)
const assertMember = {
$type: schemas.ids.AppBskyGraphAssertion,
$type: lex.ids.AppBskyGraphAssertion,
assertion: APP_BSKY_GRAPH.AssertMember,
subject: {
did: subjectDid,
@ -92,7 +88,7 @@ describe('duplicate record', () => {
}
await indexRecord(assertMember, 5)
const assertCreator = {
$type: schemas.ids.AppBskyGraphAssertion,
$type: lex.ids.AppBskyGraphAssertion,
assertion: APP_BSKY_GRAPH.AssertCreator,
subject: {
did: subjectDid,

@ -99,9 +99,10 @@ Object {
}
`;
exports[`pds profile views handles avatars 1`] = `
exports[`pds profile views handles avatars & banners 1`] = `
Object {
"avatar": "https://pds.public.url/image/w4t9ji0l53vlWd7Res2ZSFAL6QS2iaI9RGCt6Gs5reE/rs:fill:250:250:1:0/plain/bafkreiaivizp4xldojmmpuzmiu75cmea7nq56dnntnuhzhsjcb63aou5ei@jpeg",
"banner": "https://pds.public.url/image/pBWJTJbdqH1-25XObfwYex9kW_s4ltYGVG4Qjg2TdMc/rs:fill:250:750:1:0/plain/bafkreigy5p3xxceipk2o6nqtnugpft26ol6yleqhboqziino7axvdngtci@jpeg",
"creator": "user(0)",
"declaration": Object {
"actorType": "app.bsky.system.actorUser",

@ -99,15 +99,27 @@ describe('pds profile views', () => {
expect(forSnapshot(aliceForAlice.data)).toMatchSnapshot()
})
it('handles avatars', async () => {
const img = await fs.readFile('tests/image/fixtures/key-portrait-small.jpg')
const res = await client.com.atproto.blob.upload(img, {
it('handles avatars & banners', async () => {
const avatarImg = await fs.readFile(
'tests/image/fixtures/key-portrait-small.jpg',
)
const bannerImg = await fs.readFile(
'tests/image/fixtures/key-landscape-small.jpg',
)
const avatarRes = await client.com.atproto.blob.upload(avatarImg, {
headers: sc.getHeaders(alice),
encoding: 'image/jpeg',
} as any)
const bannerRes = await client.com.atproto.blob.upload(bannerImg, {
headers: sc.getHeaders(alice),
encoding: 'image/jpeg',
} as any)
await client.app.bsky.actor.updateProfile(
{ avatar: { cid: res.data.cid, mimeType: 'image/jpeg' } },
{
avatar: { cid: avatarRes.data.cid, mimeType: 'image/jpeg' },
banner: { cid: bannerRes.data.cid, mimeType: 'image/jpeg' },
},
{ headers: sc.getHeaders(alice), encoding: 'application/json' },
)