✨ Ozone sets (#2636)
* ✨ Initial implementation of sets api on ozone * ✨ Introduce sortDirection to querySets * 🧹 Cleanup and refactor * ✨ Align setView for response * ♻️ Rename and add specific error * 🐛 Cleanup unnecessary check that is covered by lexicon * ✨ Rename remove to delete and add set suffix * ✨ Use id and createdAt for values pagination * ✨ Add index on createdAt for query perf and other cleanups * 🐛 Set createdAt when inserting values * 📝 Add changeset * ✨ Add index on setId and createdAt
This commit is contained in:
parent
3e1ae8d1d5
commit
22d039a229
.changeset
lexicons/tools/ozone/set
packages
api/src/client
ozone
pds/src/lexicon
6
.changeset/modern-snails-flash.md
Normal file
6
.changeset/modern-snails-flash.md
Normal file
@ -0,0 +1,6 @@
|
||||
---
|
||||
"@atproto/ozone": patch
|
||||
"@atproto/api": patch
|
||||
---
|
||||
|
||||
Sets api to manage lists of strings on ozone, mostly aimed for automod configuration
|
32
lexicons/tools/ozone/set/addValues.json
Normal file
32
lexicons/tools/ozone/set/addValues.json
Normal file
@ -0,0 +1,32 @@
|
||||
{
|
||||
"lexicon": 1,
|
||||
"id": "tools.ozone.set.addValues",
|
||||
"defs": {
|
||||
"main": {
|
||||
"type": "procedure",
|
||||
"description": "Add values to a specific set. Attempting to add values to a set that does not exist will result in an error.",
|
||||
"input": {
|
||||
"encoding": "application/json",
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"required": ["name", "values"],
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string",
|
||||
"description": "Name of the set to add values to"
|
||||
},
|
||||
"values": {
|
||||
"type": "array",
|
||||
"minLength": 1,
|
||||
"maxLength": 1000,
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"description": "Array of string values to add to the set"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
49
lexicons/tools/ozone/set/defs.json
Normal file
49
lexicons/tools/ozone/set/defs.json
Normal file
@ -0,0 +1,49 @@
|
||||
{
|
||||
"lexicon": 1,
|
||||
"id": "tools.ozone.set.defs",
|
||||
"defs": {
|
||||
"set": {
|
||||
"type": "object",
|
||||
"required": ["name"],
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string",
|
||||
"minLength": 3,
|
||||
"maxLength": 128
|
||||
},
|
||||
"description": {
|
||||
"type": "string",
|
||||
"maxGraphemes": 1024,
|
||||
"maxLength": 10240
|
||||
}
|
||||
}
|
||||
},
|
||||
"setView": {
|
||||
"type": "object",
|
||||
"required": ["name", "setSize", "createdAt", "updatedAt"],
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string",
|
||||
"minLength": 3,
|
||||
"maxLength": 128
|
||||
},
|
||||
"description": {
|
||||
"type": "string",
|
||||
"maxGraphemes": 1024,
|
||||
"maxLength": 10240
|
||||
},
|
||||
"setSize": {
|
||||
"type": "integer"
|
||||
},
|
||||
"createdAt": {
|
||||
"type": "string",
|
||||
"format": "datetime"
|
||||
},
|
||||
"updatedAt": {
|
||||
"type": "string",
|
||||
"format": "datetime"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
36
lexicons/tools/ozone/set/deleteSet.json
Normal file
36
lexicons/tools/ozone/set/deleteSet.json
Normal file
@ -0,0 +1,36 @@
|
||||
{
|
||||
"lexicon": 1,
|
||||
"id": "tools.ozone.set.deleteSet",
|
||||
"defs": {
|
||||
"main": {
|
||||
"type": "procedure",
|
||||
"description": "Delete an entire set. Attempting to delete a set that does not exist will result in an error.",
|
||||
"input": {
|
||||
"encoding": "application/json",
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"required": ["name"],
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string",
|
||||
"description": "Name of the set to delete"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"output": {
|
||||
"encoding": "application/json",
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {}
|
||||
}
|
||||
},
|
||||
"errors": [
|
||||
{
|
||||
"name": "SetNotFound",
|
||||
"description": "set with the given name does not exist"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
37
lexicons/tools/ozone/set/deleteValues.json
Normal file
37
lexicons/tools/ozone/set/deleteValues.json
Normal file
@ -0,0 +1,37 @@
|
||||
{
|
||||
"lexicon": 1,
|
||||
"id": "tools.ozone.set.deleteValues",
|
||||
"defs": {
|
||||
"main": {
|
||||
"type": "procedure",
|
||||
"description": "Delete values from a specific set. Attempting to delete values that are not in the set will not result in an error",
|
||||
"input": {
|
||||
"encoding": "application/json",
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"required": ["name", "values"],
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string",
|
||||
"description": "Name of the set to delete values from"
|
||||
},
|
||||
"values": {
|
||||
"type": "array",
|
||||
"minLength": 1,
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"description": "Array of string values to delete from the set"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"errors": [
|
||||
{
|
||||
"name": "SetNotFound",
|
||||
"description": "set with the given name does not exist"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
56
lexicons/tools/ozone/set/getValues.json
Normal file
56
lexicons/tools/ozone/set/getValues.json
Normal file
@ -0,0 +1,56 @@
|
||||
{
|
||||
"lexicon": 1,
|
||||
"id": "tools.ozone.set.getValues",
|
||||
"defs": {
|
||||
"main": {
|
||||
"type": "query",
|
||||
"description": "Get a specific set and its values",
|
||||
"parameters": {
|
||||
"type": "params",
|
||||
"required": ["name"],
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"limit": {
|
||||
"type": "integer",
|
||||
"minimum": 1,
|
||||
"maximum": 1000,
|
||||
"default": 100
|
||||
},
|
||||
"cursor": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"output": {
|
||||
"encoding": "application/json",
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"required": ["set", "values"],
|
||||
"properties": {
|
||||
"set": {
|
||||
"type": "ref",
|
||||
"ref": "tools.ozone.set.defs#setView"
|
||||
},
|
||||
"values": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"cursor": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"errors": [
|
||||
{
|
||||
"name": "SetNotFound",
|
||||
"description": "set with the given name does not exist"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
57
lexicons/tools/ozone/set/querySets.json
Normal file
57
lexicons/tools/ozone/set/querySets.json
Normal file
@ -0,0 +1,57 @@
|
||||
{
|
||||
"lexicon": 1,
|
||||
"id": "tools.ozone.set.querySets",
|
||||
"defs": {
|
||||
"main": {
|
||||
"type": "query",
|
||||
"description": "Query available sets",
|
||||
"parameters": {
|
||||
"type": "params",
|
||||
"properties": {
|
||||
"limit": {
|
||||
"type": "integer",
|
||||
"minimum": 1,
|
||||
"maximum": 100,
|
||||
"default": 50
|
||||
},
|
||||
"cursor": {
|
||||
"type": "string"
|
||||
},
|
||||
"namePrefix": {
|
||||
"type": "string"
|
||||
},
|
||||
"sortBy": {
|
||||
"type": "string",
|
||||
"enum": ["name", "createdAt", "updatedAt"],
|
||||
"default": "name"
|
||||
},
|
||||
"sortDirection": {
|
||||
"type": "string",
|
||||
"default": "asc",
|
||||
"enum": ["asc", "desc"],
|
||||
"description": "Defaults to ascending order of name field."
|
||||
}
|
||||
}
|
||||
},
|
||||
"output": {
|
||||
"encoding": "application/json",
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"required": ["sets"],
|
||||
"properties": {
|
||||
"sets": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "ref",
|
||||
"ref": "tools.ozone.set.defs#setView"
|
||||
}
|
||||
},
|
||||
"cursor": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
24
lexicons/tools/ozone/set/upsertSet.json
Normal file
24
lexicons/tools/ozone/set/upsertSet.json
Normal file
@ -0,0 +1,24 @@
|
||||
{
|
||||
"lexicon": 1,
|
||||
"id": "tools.ozone.set.upsertSet",
|
||||
"defs": {
|
||||
"main": {
|
||||
"type": "procedure",
|
||||
"description": "Create or update set metadata",
|
||||
"input": {
|
||||
"encoding": "application/json",
|
||||
"schema": {
|
||||
"type": "ref",
|
||||
"ref": "tools.ozone.set.defs#set"
|
||||
}
|
||||
},
|
||||
"output": {
|
||||
"encoding": "application/json",
|
||||
"schema": {
|
||||
"type": "ref",
|
||||
"ref": "tools.ozone.set.defs#setView"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -206,6 +206,13 @@ import * as ToolsOzoneModerationQueryEvents from './types/tools/ozone/moderation
|
||||
import * as ToolsOzoneModerationQueryStatuses from './types/tools/ozone/moderation/queryStatuses'
|
||||
import * as ToolsOzoneModerationSearchRepos from './types/tools/ozone/moderation/searchRepos'
|
||||
import * as ToolsOzoneServerGetConfig from './types/tools/ozone/server/getConfig'
|
||||
import * as ToolsOzoneSetAddValues from './types/tools/ozone/set/addValues'
|
||||
import * as ToolsOzoneSetDefs from './types/tools/ozone/set/defs'
|
||||
import * as ToolsOzoneSetDeleteSet from './types/tools/ozone/set/deleteSet'
|
||||
import * as ToolsOzoneSetDeleteValues from './types/tools/ozone/set/deleteValues'
|
||||
import * as ToolsOzoneSetGetValues from './types/tools/ozone/set/getValues'
|
||||
import * as ToolsOzoneSetQuerySets from './types/tools/ozone/set/querySets'
|
||||
import * as ToolsOzoneSetUpsertSet from './types/tools/ozone/set/upsertSet'
|
||||
import * as ToolsOzoneSignatureDefs from './types/tools/ozone/signature/defs'
|
||||
import * as ToolsOzoneSignatureFindCorrelation from './types/tools/ozone/signature/findCorrelation'
|
||||
import * as ToolsOzoneSignatureFindRelatedAccounts from './types/tools/ozone/signature/findRelatedAccounts'
|
||||
@ -418,6 +425,13 @@ export * as ToolsOzoneModerationQueryEvents from './types/tools/ozone/moderation
|
||||
export * as ToolsOzoneModerationQueryStatuses from './types/tools/ozone/moderation/queryStatuses'
|
||||
export * as ToolsOzoneModerationSearchRepos from './types/tools/ozone/moderation/searchRepos'
|
||||
export * as ToolsOzoneServerGetConfig from './types/tools/ozone/server/getConfig'
|
||||
export * as ToolsOzoneSetAddValues from './types/tools/ozone/set/addValues'
|
||||
export * as ToolsOzoneSetDefs from './types/tools/ozone/set/defs'
|
||||
export * as ToolsOzoneSetDeleteSet from './types/tools/ozone/set/deleteSet'
|
||||
export * as ToolsOzoneSetDeleteValues from './types/tools/ozone/set/deleteValues'
|
||||
export * as ToolsOzoneSetGetValues from './types/tools/ozone/set/getValues'
|
||||
export * as ToolsOzoneSetQuerySets from './types/tools/ozone/set/querySets'
|
||||
export * as ToolsOzoneSetUpsertSet from './types/tools/ozone/set/upsertSet'
|
||||
export * as ToolsOzoneSignatureDefs from './types/tools/ozone/signature/defs'
|
||||
export * as ToolsOzoneSignatureFindCorrelation from './types/tools/ozone/signature/findCorrelation'
|
||||
export * as ToolsOzoneSignatureFindRelatedAccounts from './types/tools/ozone/signature/findRelatedAccounts'
|
||||
@ -3404,6 +3418,7 @@ export class ToolsOzoneNS {
|
||||
communication: ToolsOzoneCommunicationNS
|
||||
moderation: ToolsOzoneModerationNS
|
||||
server: ToolsOzoneServerNS
|
||||
set: ToolsOzoneSetNS
|
||||
signature: ToolsOzoneSignatureNS
|
||||
team: ToolsOzoneTeamNS
|
||||
|
||||
@ -3412,6 +3427,7 @@ export class ToolsOzoneNS {
|
||||
this.communication = new ToolsOzoneCommunicationNS(client)
|
||||
this.moderation = new ToolsOzoneModerationNS(client)
|
||||
this.server = new ToolsOzoneServerNS(client)
|
||||
this.set = new ToolsOzoneSetNS(client)
|
||||
this.signature = new ToolsOzoneSignatureNS(client)
|
||||
this.team = new ToolsOzoneTeamNS(client)
|
||||
}
|
||||
@ -3604,6 +3620,73 @@ export class ToolsOzoneServerNS {
|
||||
}
|
||||
}
|
||||
|
||||
export class ToolsOzoneSetNS {
|
||||
_client: XrpcClient
|
||||
|
||||
constructor(client: XrpcClient) {
|
||||
this._client = client
|
||||
}
|
||||
|
||||
addValues(
|
||||
data?: ToolsOzoneSetAddValues.InputSchema,
|
||||
opts?: ToolsOzoneSetAddValues.CallOptions,
|
||||
): Promise<ToolsOzoneSetAddValues.Response> {
|
||||
return this._client.call('tools.ozone.set.addValues', opts?.qp, data, opts)
|
||||
}
|
||||
|
||||
deleteSet(
|
||||
data?: ToolsOzoneSetDeleteSet.InputSchema,
|
||||
opts?: ToolsOzoneSetDeleteSet.CallOptions,
|
||||
): Promise<ToolsOzoneSetDeleteSet.Response> {
|
||||
return this._client
|
||||
.call('tools.ozone.set.deleteSet', opts?.qp, data, opts)
|
||||
.catch((e) => {
|
||||
throw ToolsOzoneSetDeleteSet.toKnownErr(e)
|
||||
})
|
||||
}
|
||||
|
||||
deleteValues(
|
||||
data?: ToolsOzoneSetDeleteValues.InputSchema,
|
||||
opts?: ToolsOzoneSetDeleteValues.CallOptions,
|
||||
): Promise<ToolsOzoneSetDeleteValues.Response> {
|
||||
return this._client
|
||||
.call('tools.ozone.set.deleteValues', opts?.qp, data, opts)
|
||||
.catch((e) => {
|
||||
throw ToolsOzoneSetDeleteValues.toKnownErr(e)
|
||||
})
|
||||
}
|
||||
|
||||
getValues(
|
||||
params?: ToolsOzoneSetGetValues.QueryParams,
|
||||
opts?: ToolsOzoneSetGetValues.CallOptions,
|
||||
): Promise<ToolsOzoneSetGetValues.Response> {
|
||||
return this._client
|
||||
.call('tools.ozone.set.getValues', params, undefined, opts)
|
||||
.catch((e) => {
|
||||
throw ToolsOzoneSetGetValues.toKnownErr(e)
|
||||
})
|
||||
}
|
||||
|
||||
querySets(
|
||||
params?: ToolsOzoneSetQuerySets.QueryParams,
|
||||
opts?: ToolsOzoneSetQuerySets.CallOptions,
|
||||
): Promise<ToolsOzoneSetQuerySets.Response> {
|
||||
return this._client.call(
|
||||
'tools.ozone.set.querySets',
|
||||
params,
|
||||
undefined,
|
||||
opts,
|
||||
)
|
||||
}
|
||||
|
||||
upsertSet(
|
||||
data?: ToolsOzoneSetUpsertSet.InputSchema,
|
||||
opts?: ToolsOzoneSetUpsertSet.CallOptions,
|
||||
): Promise<ToolsOzoneSetUpsertSet.Response> {
|
||||
return this._client.call('tools.ozone.set.upsertSet', opts?.qp, data, opts)
|
||||
}
|
||||
}
|
||||
|
||||
export class ToolsOzoneSignatureNS {
|
||||
_client: XrpcClient
|
||||
|
||||
|
@ -12139,6 +12139,300 @@ export const schemaDict = {
|
||||
},
|
||||
},
|
||||
},
|
||||
ToolsOzoneSetAddValues: {
|
||||
lexicon: 1,
|
||||
id: 'tools.ozone.set.addValues',
|
||||
defs: {
|
||||
main: {
|
||||
type: 'procedure',
|
||||
description:
|
||||
'Add values to a specific set. Attempting to add values to a set that does not exist will result in an error.',
|
||||
input: {
|
||||
encoding: 'application/json',
|
||||
schema: {
|
||||
type: 'object',
|
||||
required: ['name', 'values'],
|
||||
properties: {
|
||||
name: {
|
||||
type: 'string',
|
||||
description: 'Name of the set to add values to',
|
||||
},
|
||||
values: {
|
||||
type: 'array',
|
||||
minLength: 1,
|
||||
maxLength: 1000,
|
||||
items: {
|
||||
type: 'string',
|
||||
},
|
||||
description: 'Array of string values to add to the set',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
ToolsOzoneSetDefs: {
|
||||
lexicon: 1,
|
||||
id: 'tools.ozone.set.defs',
|
||||
defs: {
|
||||
set: {
|
||||
type: 'object',
|
||||
required: ['name'],
|
||||
properties: {
|
||||
name: {
|
||||
type: 'string',
|
||||
minLength: 3,
|
||||
maxLength: 128,
|
||||
},
|
||||
description: {
|
||||
type: 'string',
|
||||
maxGraphemes: 1024,
|
||||
maxLength: 10240,
|
||||
},
|
||||
},
|
||||
},
|
||||
setView: {
|
||||
type: 'object',
|
||||
required: ['name', 'setSize', 'createdAt', 'updatedAt'],
|
||||
properties: {
|
||||
name: {
|
||||
type: 'string',
|
||||
minLength: 3,
|
||||
maxLength: 128,
|
||||
},
|
||||
description: {
|
||||
type: 'string',
|
||||
maxGraphemes: 1024,
|
||||
maxLength: 10240,
|
||||
},
|
||||
setSize: {
|
||||
type: 'integer',
|
||||
},
|
||||
createdAt: {
|
||||
type: 'string',
|
||||
format: 'datetime',
|
||||
},
|
||||
updatedAt: {
|
||||
type: 'string',
|
||||
format: 'datetime',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
ToolsOzoneSetDeleteSet: {
|
||||
lexicon: 1,
|
||||
id: 'tools.ozone.set.deleteSet',
|
||||
defs: {
|
||||
main: {
|
||||
type: 'procedure',
|
||||
description:
|
||||
'Delete an entire set. Attempting to delete a set that does not exist will result in an error.',
|
||||
input: {
|
||||
encoding: 'application/json',
|
||||
schema: {
|
||||
type: 'object',
|
||||
required: ['name'],
|
||||
properties: {
|
||||
name: {
|
||||
type: 'string',
|
||||
description: 'Name of the set to delete',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
output: {
|
||||
encoding: 'application/json',
|
||||
schema: {
|
||||
type: 'object',
|
||||
properties: {},
|
||||
},
|
||||
},
|
||||
errors: [
|
||||
{
|
||||
name: 'SetNotFound',
|
||||
description: 'set with the given name does not exist',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
ToolsOzoneSetDeleteValues: {
|
||||
lexicon: 1,
|
||||
id: 'tools.ozone.set.deleteValues',
|
||||
defs: {
|
||||
main: {
|
||||
type: 'procedure',
|
||||
description:
|
||||
'Delete values from a specific set. Attempting to delete values that are not in the set will not result in an error',
|
||||
input: {
|
||||
encoding: 'application/json',
|
||||
schema: {
|
||||
type: 'object',
|
||||
required: ['name', 'values'],
|
||||
properties: {
|
||||
name: {
|
||||
type: 'string',
|
||||
description: 'Name of the set to delete values from',
|
||||
},
|
||||
values: {
|
||||
type: 'array',
|
||||
minLength: 1,
|
||||
items: {
|
||||
type: 'string',
|
||||
},
|
||||
description: 'Array of string values to delete from the set',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
errors: [
|
||||
{
|
||||
name: 'SetNotFound',
|
||||
description: 'set with the given name does not exist',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
ToolsOzoneSetGetValues: {
|
||||
lexicon: 1,
|
||||
id: 'tools.ozone.set.getValues',
|
||||
defs: {
|
||||
main: {
|
||||
type: 'query',
|
||||
description: 'Get a specific set and its values',
|
||||
parameters: {
|
||||
type: 'params',
|
||||
required: ['name'],
|
||||
properties: {
|
||||
name: {
|
||||
type: 'string',
|
||||
},
|
||||
limit: {
|
||||
type: 'integer',
|
||||
minimum: 1,
|
||||
maximum: 1000,
|
||||
default: 100,
|
||||
},
|
||||
cursor: {
|
||||
type: 'string',
|
||||
},
|
||||
},
|
||||
},
|
||||
output: {
|
||||
encoding: 'application/json',
|
||||
schema: {
|
||||
type: 'object',
|
||||
required: ['set', 'values'],
|
||||
properties: {
|
||||
set: {
|
||||
type: 'ref',
|
||||
ref: 'lex:tools.ozone.set.defs#setView',
|
||||
},
|
||||
values: {
|
||||
type: 'array',
|
||||
items: {
|
||||
type: 'string',
|
||||
},
|
||||
},
|
||||
cursor: {
|
||||
type: 'string',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
errors: [
|
||||
{
|
||||
name: 'SetNotFound',
|
||||
description: 'set with the given name does not exist',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
ToolsOzoneSetQuerySets: {
|
||||
lexicon: 1,
|
||||
id: 'tools.ozone.set.querySets',
|
||||
defs: {
|
||||
main: {
|
||||
type: 'query',
|
||||
description: 'Query available sets',
|
||||
parameters: {
|
||||
type: 'params',
|
||||
properties: {
|
||||
limit: {
|
||||
type: 'integer',
|
||||
minimum: 1,
|
||||
maximum: 100,
|
||||
default: 50,
|
||||
},
|
||||
cursor: {
|
||||
type: 'string',
|
||||
},
|
||||
namePrefix: {
|
||||
type: 'string',
|
||||
},
|
||||
sortBy: {
|
||||
type: 'string',
|
||||
enum: ['name', 'createdAt', 'updatedAt'],
|
||||
default: 'name',
|
||||
},
|
||||
sortDirection: {
|
||||
type: 'string',
|
||||
default: 'asc',
|
||||
enum: ['asc', 'desc'],
|
||||
description: 'Defaults to ascending order of name field.',
|
||||
},
|
||||
},
|
||||
},
|
||||
output: {
|
||||
encoding: 'application/json',
|
||||
schema: {
|
||||
type: 'object',
|
||||
required: ['sets'],
|
||||
properties: {
|
||||
sets: {
|
||||
type: 'array',
|
||||
items: {
|
||||
type: 'ref',
|
||||
ref: 'lex:tools.ozone.set.defs#setView',
|
||||
},
|
||||
},
|
||||
cursor: {
|
||||
type: 'string',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
ToolsOzoneSetUpsertSet: {
|
||||
lexicon: 1,
|
||||
id: 'tools.ozone.set.upsertSet',
|
||||
defs: {
|
||||
main: {
|
||||
type: 'procedure',
|
||||
description: 'Create or update set metadata',
|
||||
input: {
|
||||
encoding: 'application/json',
|
||||
schema: {
|
||||
type: 'ref',
|
||||
ref: 'lex:tools.ozone.set.defs#set',
|
||||
},
|
||||
},
|
||||
output: {
|
||||
encoding: 'application/json',
|
||||
schema: {
|
||||
type: 'ref',
|
||||
ref: 'lex:tools.ozone.set.defs#setView',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
ToolsOzoneSignatureDefs: {
|
||||
lexicon: 1,
|
||||
id: 'tools.ozone.signature.defs',
|
||||
@ -12764,6 +13058,13 @@ export const ids = {
|
||||
ToolsOzoneModerationQueryStatuses: 'tools.ozone.moderation.queryStatuses',
|
||||
ToolsOzoneModerationSearchRepos: 'tools.ozone.moderation.searchRepos',
|
||||
ToolsOzoneServerGetConfig: 'tools.ozone.server.getConfig',
|
||||
ToolsOzoneSetAddValues: 'tools.ozone.set.addValues',
|
||||
ToolsOzoneSetDefs: 'tools.ozone.set.defs',
|
||||
ToolsOzoneSetDeleteSet: 'tools.ozone.set.deleteSet',
|
||||
ToolsOzoneSetDeleteValues: 'tools.ozone.set.deleteValues',
|
||||
ToolsOzoneSetGetValues: 'tools.ozone.set.getValues',
|
||||
ToolsOzoneSetQuerySets: 'tools.ozone.set.querySets',
|
||||
ToolsOzoneSetUpsertSet: 'tools.ozone.set.upsertSet',
|
||||
ToolsOzoneSignatureDefs: 'tools.ozone.signature.defs',
|
||||
ToolsOzoneSignatureFindCorrelation: 'tools.ozone.signature.findCorrelation',
|
||||
ToolsOzoneSignatureFindRelatedAccounts:
|
||||
|
34
packages/api/src/client/types/tools/ozone/set/addValues.ts
Normal file
34
packages/api/src/client/types/tools/ozone/set/addValues.ts
Normal file
@ -0,0 +1,34 @@
|
||||
/**
|
||||
* GENERATED CODE - DO NOT MODIFY
|
||||
*/
|
||||
import { HeadersMap, XRPCError } from '@atproto/xrpc'
|
||||
import { ValidationResult, BlobRef } from '@atproto/lexicon'
|
||||
import { isObj, hasProp } from '../../../../util'
|
||||
import { lexicons } from '../../../../lexicons'
|
||||
import { CID } from 'multiformats/cid'
|
||||
|
||||
export interface QueryParams {}
|
||||
|
||||
export interface InputSchema {
|
||||
/** Name of the set to add values to */
|
||||
name: string
|
||||
/** Array of string values to add to the set */
|
||||
values: string[]
|
||||
[k: string]: unknown
|
||||
}
|
||||
|
||||
export interface CallOptions {
|
||||
signal?: AbortSignal
|
||||
headers?: HeadersMap
|
||||
qp?: QueryParams
|
||||
encoding?: 'application/json'
|
||||
}
|
||||
|
||||
export interface Response {
|
||||
success: boolean
|
||||
headers: HeadersMap
|
||||
}
|
||||
|
||||
export function toKnownErr(e: any) {
|
||||
return e
|
||||
}
|
44
packages/api/src/client/types/tools/ozone/set/defs.ts
Normal file
44
packages/api/src/client/types/tools/ozone/set/defs.ts
Normal file
@ -0,0 +1,44 @@
|
||||
/**
|
||||
* GENERATED CODE - DO NOT MODIFY
|
||||
*/
|
||||
import { ValidationResult, BlobRef } from '@atproto/lexicon'
|
||||
import { isObj, hasProp } from '../../../../util'
|
||||
import { lexicons } from '../../../../lexicons'
|
||||
import { CID } from 'multiformats/cid'
|
||||
|
||||
export interface Set {
|
||||
name: string
|
||||
description?: string
|
||||
[k: string]: unknown
|
||||
}
|
||||
|
||||
export function isSet(v: unknown): v is Set {
|
||||
return (
|
||||
isObj(v) && hasProp(v, '$type') && v.$type === 'tools.ozone.set.defs#set'
|
||||
)
|
||||
}
|
||||
|
||||
export function validateSet(v: unknown): ValidationResult {
|
||||
return lexicons.validate('tools.ozone.set.defs#set', v)
|
||||
}
|
||||
|
||||
export interface SetView {
|
||||
name: string
|
||||
description?: string
|
||||
setSize: number
|
||||
createdAt: string
|
||||
updatedAt: string
|
||||
[k: string]: unknown
|
||||
}
|
||||
|
||||
export function isSetView(v: unknown): v is SetView {
|
||||
return (
|
||||
isObj(v) &&
|
||||
hasProp(v, '$type') &&
|
||||
v.$type === 'tools.ozone.set.defs#setView'
|
||||
)
|
||||
}
|
||||
|
||||
export function validateSetView(v: unknown): ValidationResult {
|
||||
return lexicons.validate('tools.ozone.set.defs#setView', v)
|
||||
}
|
47
packages/api/src/client/types/tools/ozone/set/deleteSet.ts
Normal file
47
packages/api/src/client/types/tools/ozone/set/deleteSet.ts
Normal file
@ -0,0 +1,47 @@
|
||||
/**
|
||||
* GENERATED CODE - DO NOT MODIFY
|
||||
*/
|
||||
import { HeadersMap, XRPCError } from '@atproto/xrpc'
|
||||
import { ValidationResult, BlobRef } from '@atproto/lexicon'
|
||||
import { isObj, hasProp } from '../../../../util'
|
||||
import { lexicons } from '../../../../lexicons'
|
||||
import { CID } from 'multiformats/cid'
|
||||
|
||||
export interface QueryParams {}
|
||||
|
||||
export interface InputSchema {
|
||||
/** Name of the set to delete */
|
||||
name: string
|
||||
[k: string]: unknown
|
||||
}
|
||||
|
||||
export interface OutputSchema {
|
||||
[k: string]: unknown
|
||||
}
|
||||
|
||||
export interface CallOptions {
|
||||
signal?: AbortSignal
|
||||
headers?: HeadersMap
|
||||
qp?: QueryParams
|
||||
encoding?: 'application/json'
|
||||
}
|
||||
|
||||
export interface Response {
|
||||
success: boolean
|
||||
headers: HeadersMap
|
||||
data: OutputSchema
|
||||
}
|
||||
|
||||
export class SetNotFoundError extends XRPCError {
|
||||
constructor(src: XRPCError) {
|
||||
super(src.status, src.error, src.message, src.headers, { cause: src })
|
||||
}
|
||||
}
|
||||
|
||||
export function toKnownErr(e: any) {
|
||||
if (e instanceof XRPCError) {
|
||||
if (e.error === 'SetNotFound') return new SetNotFoundError(e)
|
||||
}
|
||||
|
||||
return e
|
||||
}
|
@ -0,0 +1,44 @@
|
||||
/**
|
||||
* GENERATED CODE - DO NOT MODIFY
|
||||
*/
|
||||
import { HeadersMap, XRPCError } from '@atproto/xrpc'
|
||||
import { ValidationResult, BlobRef } from '@atproto/lexicon'
|
||||
import { isObj, hasProp } from '../../../../util'
|
||||
import { lexicons } from '../../../../lexicons'
|
||||
import { CID } from 'multiformats/cid'
|
||||
|
||||
export interface QueryParams {}
|
||||
|
||||
export interface InputSchema {
|
||||
/** Name of the set to delete values from */
|
||||
name: string
|
||||
/** Array of string values to delete from the set */
|
||||
values: string[]
|
||||
[k: string]: unknown
|
||||
}
|
||||
|
||||
export interface CallOptions {
|
||||
signal?: AbortSignal
|
||||
headers?: HeadersMap
|
||||
qp?: QueryParams
|
||||
encoding?: 'application/json'
|
||||
}
|
||||
|
||||
export interface Response {
|
||||
success: boolean
|
||||
headers: HeadersMap
|
||||
}
|
||||
|
||||
export class SetNotFoundError extends XRPCError {
|
||||
constructor(src: XRPCError) {
|
||||
super(src.status, src.error, src.message, src.headers, { cause: src })
|
||||
}
|
||||
}
|
||||
|
||||
export function toKnownErr(e: any) {
|
||||
if (e instanceof XRPCError) {
|
||||
if (e.error === 'SetNotFound') return new SetNotFoundError(e)
|
||||
}
|
||||
|
||||
return e
|
||||
}
|
49
packages/api/src/client/types/tools/ozone/set/getValues.ts
Normal file
49
packages/api/src/client/types/tools/ozone/set/getValues.ts
Normal file
@ -0,0 +1,49 @@
|
||||
/**
|
||||
* GENERATED CODE - DO NOT MODIFY
|
||||
*/
|
||||
import { HeadersMap, XRPCError } from '@atproto/xrpc'
|
||||
import { ValidationResult, BlobRef } from '@atproto/lexicon'
|
||||
import { isObj, hasProp } from '../../../../util'
|
||||
import { lexicons } from '../../../../lexicons'
|
||||
import { CID } from 'multiformats/cid'
|
||||
import * as ToolsOzoneSetDefs from './defs'
|
||||
|
||||
export interface QueryParams {
|
||||
name: string
|
||||
limit?: number
|
||||
cursor?: string
|
||||
}
|
||||
|
||||
export type InputSchema = undefined
|
||||
|
||||
export interface OutputSchema {
|
||||
set: ToolsOzoneSetDefs.SetView
|
||||
values: string[]
|
||||
cursor?: string
|
||||
[k: string]: unknown
|
||||
}
|
||||
|
||||
export interface CallOptions {
|
||||
signal?: AbortSignal
|
||||
headers?: HeadersMap
|
||||
}
|
||||
|
||||
export interface Response {
|
||||
success: boolean
|
||||
headers: HeadersMap
|
||||
data: OutputSchema
|
||||
}
|
||||
|
||||
export class SetNotFoundError extends XRPCError {
|
||||
constructor(src: XRPCError) {
|
||||
super(src.status, src.error, src.message, src.headers, { cause: src })
|
||||
}
|
||||
}
|
||||
|
||||
export function toKnownErr(e: any) {
|
||||
if (e instanceof XRPCError) {
|
||||
if (e.error === 'SetNotFound') return new SetNotFoundError(e)
|
||||
}
|
||||
|
||||
return e
|
||||
}
|
41
packages/api/src/client/types/tools/ozone/set/querySets.ts
Normal file
41
packages/api/src/client/types/tools/ozone/set/querySets.ts
Normal file
@ -0,0 +1,41 @@
|
||||
/**
|
||||
* GENERATED CODE - DO NOT MODIFY
|
||||
*/
|
||||
import { HeadersMap, XRPCError } from '@atproto/xrpc'
|
||||
import { ValidationResult, BlobRef } from '@atproto/lexicon'
|
||||
import { isObj, hasProp } from '../../../../util'
|
||||
import { lexicons } from '../../../../lexicons'
|
||||
import { CID } from 'multiformats/cid'
|
||||
import * as ToolsOzoneSetDefs from './defs'
|
||||
|
||||
export interface QueryParams {
|
||||
limit?: number
|
||||
cursor?: string
|
||||
namePrefix?: string
|
||||
sortBy?: 'name' | 'createdAt' | 'updatedAt'
|
||||
/** Defaults to ascending order of name field. */
|
||||
sortDirection?: 'asc' | 'desc'
|
||||
}
|
||||
|
||||
export type InputSchema = undefined
|
||||
|
||||
export interface OutputSchema {
|
||||
sets: ToolsOzoneSetDefs.SetView[]
|
||||
cursor?: string
|
||||
[k: string]: unknown
|
||||
}
|
||||
|
||||
export interface CallOptions {
|
||||
signal?: AbortSignal
|
||||
headers?: HeadersMap
|
||||
}
|
||||
|
||||
export interface Response {
|
||||
success: boolean
|
||||
headers: HeadersMap
|
||||
data: OutputSchema
|
||||
}
|
||||
|
||||
export function toKnownErr(e: any) {
|
||||
return e
|
||||
}
|
31
packages/api/src/client/types/tools/ozone/set/upsertSet.ts
Normal file
31
packages/api/src/client/types/tools/ozone/set/upsertSet.ts
Normal file
@ -0,0 +1,31 @@
|
||||
/**
|
||||
* GENERATED CODE - DO NOT MODIFY
|
||||
*/
|
||||
import { HeadersMap, XRPCError } from '@atproto/xrpc'
|
||||
import { ValidationResult, BlobRef } from '@atproto/lexicon'
|
||||
import { isObj, hasProp } from '../../../../util'
|
||||
import { lexicons } from '../../../../lexicons'
|
||||
import { CID } from 'multiformats/cid'
|
||||
import * as ToolsOzoneSetDefs from './defs'
|
||||
|
||||
export interface QueryParams {}
|
||||
|
||||
export type InputSchema = ToolsOzoneSetDefs.Set
|
||||
export type OutputSchema = ToolsOzoneSetDefs.SetView
|
||||
|
||||
export interface CallOptions {
|
||||
signal?: AbortSignal
|
||||
headers?: HeadersMap
|
||||
qp?: QueryParams
|
||||
encoding?: 'application/json'
|
||||
}
|
||||
|
||||
export interface Response {
|
||||
success: boolean
|
||||
headers: HeadersMap
|
||||
data: OutputSchema
|
||||
}
|
||||
|
||||
export function toKnownErr(e: any) {
|
||||
return e
|
||||
}
|
@ -23,6 +23,12 @@ import listMembers from './team/listMembers'
|
||||
import getConfig from './server/getConfig'
|
||||
import chat from './chat'
|
||||
import proxied from './proxied'
|
||||
import setAddValues from './set/addValues'
|
||||
import setGetValues from './set/getValues'
|
||||
import querySets from './set/querySets'
|
||||
import upsertSet from './set/upsertSet'
|
||||
import setDeleteValues from './set/deleteValues'
|
||||
import deleteSet from './set/deleteSet'
|
||||
import getRepos from './moderation/getRepos'
|
||||
|
||||
export * as health from './health'
|
||||
@ -54,5 +60,11 @@ export default function (server: Server, ctx: AppContext) {
|
||||
chat(server, ctx)
|
||||
proxied(server, ctx)
|
||||
getConfig(server, ctx)
|
||||
setAddValues(server, ctx)
|
||||
setGetValues(server, ctx)
|
||||
querySets(server, ctx)
|
||||
upsertSet(server, ctx)
|
||||
setDeleteValues(server, ctx)
|
||||
deleteSet(server, ctx)
|
||||
return server
|
||||
}
|
||||
|
28
packages/ozone/src/api/set/addValues.ts
Normal file
28
packages/ozone/src/api/set/addValues.ts
Normal file
@ -0,0 +1,28 @@
|
||||
import { AuthRequiredError, InvalidRequestError } from '@atproto/xrpc-server'
|
||||
import { Server } from '../../lexicon'
|
||||
import AppContext from '../../context'
|
||||
|
||||
export default function (server: Server, ctx: AppContext) {
|
||||
server.tools.ozone.set.addValues({
|
||||
auth: ctx.authVerifier.modOrAdminToken,
|
||||
handler: async ({ input, auth }) => {
|
||||
const access = auth.credentials
|
||||
const db = ctx.db
|
||||
const { name, values } = input.body
|
||||
|
||||
if (!access.isModerator) {
|
||||
throw new AuthRequiredError(
|
||||
'Must be a moderator to add values to a set',
|
||||
)
|
||||
}
|
||||
|
||||
const setService = ctx.setService(db)
|
||||
const set = await setService.getByName(name)
|
||||
if (!set) {
|
||||
throw new InvalidRequestError(`Set with name "${name}" does not exist`)
|
||||
}
|
||||
|
||||
await setService.addValues(set.id, values)
|
||||
},
|
||||
})
|
||||
}
|
34
packages/ozone/src/api/set/deleteSet.ts
Normal file
34
packages/ozone/src/api/set/deleteSet.ts
Normal file
@ -0,0 +1,34 @@
|
||||
import { AuthRequiredError, InvalidRequestError } from '@atproto/xrpc-server'
|
||||
import { Server } from '../../lexicon'
|
||||
import AppContext from '../../context'
|
||||
|
||||
export default function (server: Server, ctx: AppContext) {
|
||||
server.tools.ozone.set.deleteSet({
|
||||
auth: ctx.authVerifier.modOrAdminToken,
|
||||
handler: async ({ input, auth }) => {
|
||||
const access = auth.credentials
|
||||
const db = ctx.db
|
||||
const { name } = input.body
|
||||
|
||||
if (!access.isModerator) {
|
||||
throw new AuthRequiredError('Must be a moderator to delete a set')
|
||||
}
|
||||
|
||||
const setService = ctx.setService(db)
|
||||
const set = await setService.getByName(name)
|
||||
if (!set) {
|
||||
throw new InvalidRequestError(
|
||||
`Set with name "${name}" does not exist`,
|
||||
'SetNotFound',
|
||||
)
|
||||
}
|
||||
|
||||
await setService.removeSet(set.id)
|
||||
|
||||
return {
|
||||
encoding: 'application/json',
|
||||
body: {},
|
||||
}
|
||||
},
|
||||
})
|
||||
}
|
31
packages/ozone/src/api/set/deleteValues.ts
Normal file
31
packages/ozone/src/api/set/deleteValues.ts
Normal file
@ -0,0 +1,31 @@
|
||||
import { AuthRequiredError, InvalidRequestError } from '@atproto/xrpc-server'
|
||||
import { Server } from '../../lexicon'
|
||||
import AppContext from '../../context'
|
||||
|
||||
export default function (server: Server, ctx: AppContext) {
|
||||
server.tools.ozone.set.deleteValues({
|
||||
auth: ctx.authVerifier.modOrAdminToken,
|
||||
handler: async ({ input, auth }) => {
|
||||
const access = auth.credentials
|
||||
const db = ctx.db
|
||||
const { name, values } = input.body
|
||||
|
||||
if (!access.isModerator) {
|
||||
throw new AuthRequiredError(
|
||||
'Must be a moderator to remove values from a set',
|
||||
)
|
||||
}
|
||||
|
||||
const setService = ctx.setService(db)
|
||||
const set = await setService.getByName(name)
|
||||
if (!set) {
|
||||
throw new InvalidRequestError(
|
||||
`Set with name "${name}" does not exist`,
|
||||
'SetNotFound',
|
||||
)
|
||||
}
|
||||
|
||||
await setService.removeValues(set.id, values)
|
||||
},
|
||||
})
|
||||
}
|
42
packages/ozone/src/api/set/getValues.ts
Normal file
42
packages/ozone/src/api/set/getValues.ts
Normal file
@ -0,0 +1,42 @@
|
||||
import { AuthRequiredError, InvalidRequestError } from '@atproto/xrpc-server'
|
||||
import { Server } from '../../lexicon'
|
||||
import AppContext from '../../context'
|
||||
|
||||
export default function (server: Server, ctx: AppContext) {
|
||||
server.tools.ozone.set.getValues({
|
||||
auth: ctx.authVerifier.modOrAdminToken,
|
||||
handler: async ({ params, auth }) => {
|
||||
const access = auth.credentials
|
||||
const db = ctx.db
|
||||
const { name, limit, cursor } = params
|
||||
|
||||
if (!access.isModerator) {
|
||||
throw new AuthRequiredError('Must be a moderator to get set details')
|
||||
}
|
||||
|
||||
const setService = ctx.setService(db)
|
||||
|
||||
const result = await setService.getSetWithValues({
|
||||
name,
|
||||
limit,
|
||||
cursor,
|
||||
})
|
||||
|
||||
if (!result) {
|
||||
throw new InvalidRequestError(
|
||||
`Set with name "${name}" not found`,
|
||||
'SetNotFound',
|
||||
)
|
||||
}
|
||||
|
||||
return {
|
||||
encoding: 'application/json',
|
||||
body: {
|
||||
set: setService.view(result.set),
|
||||
values: result.values,
|
||||
cursor: result.cursor,
|
||||
},
|
||||
}
|
||||
},
|
||||
})
|
||||
}
|
36
packages/ozone/src/api/set/querySets.ts
Normal file
36
packages/ozone/src/api/set/querySets.ts
Normal file
@ -0,0 +1,36 @@
|
||||
import { AuthRequiredError } from '@atproto/xrpc-server'
|
||||
import { Server } from '../../lexicon'
|
||||
import AppContext from '../../context'
|
||||
|
||||
export default function (server: Server, ctx: AppContext) {
|
||||
server.tools.ozone.set.querySets({
|
||||
auth: ctx.authVerifier.modOrAdminToken,
|
||||
handler: async ({ params, auth }) => {
|
||||
const access = auth.credentials
|
||||
const db = ctx.db
|
||||
const { limit, cursor, namePrefix, sortBy, sortDirection } = params
|
||||
|
||||
if (!access.isModerator) {
|
||||
throw new AuthRequiredError('Must be a moderator to query sets')
|
||||
}
|
||||
|
||||
const setService = ctx.setService(db)
|
||||
|
||||
const queryResult = await setService.query({
|
||||
limit,
|
||||
cursor,
|
||||
namePrefix,
|
||||
sortBy,
|
||||
sortDirection,
|
||||
})
|
||||
|
||||
return {
|
||||
encoding: 'application/json',
|
||||
body: {
|
||||
sets: queryResult.sets.map((set) => setService.view(set)),
|
||||
cursor: queryResult.cursor,
|
||||
},
|
||||
}
|
||||
},
|
||||
})
|
||||
}
|
38
packages/ozone/src/api/set/upsertSet.ts
Normal file
38
packages/ozone/src/api/set/upsertSet.ts
Normal file
@ -0,0 +1,38 @@
|
||||
import { AuthRequiredError, InvalidRequestError } from '@atproto/xrpc-server'
|
||||
import { Server } from '../../lexicon'
|
||||
import AppContext from '../../context'
|
||||
|
||||
export default function (server: Server, ctx: AppContext) {
|
||||
server.tools.ozone.set.upsertSet({
|
||||
auth: ctx.authVerifier.modOrAdminToken,
|
||||
handler: async ({ input, auth }) => {
|
||||
const access = auth.credentials
|
||||
const db = ctx.db
|
||||
const { name, description } = input.body
|
||||
|
||||
if (!access.isModerator) {
|
||||
throw new AuthRequiredError(
|
||||
'Must be a moderator to create or update a set',
|
||||
)
|
||||
}
|
||||
|
||||
const setService = ctx.setService(db)
|
||||
|
||||
await setService.upsert({
|
||||
name,
|
||||
description: description ?? null,
|
||||
})
|
||||
const setWithSize = await setService.getByNameWithSize(name)
|
||||
|
||||
// Unlikely to happen since we just upserted the set
|
||||
if (!setWithSize) {
|
||||
throw new InvalidRequestError(`Set not found`)
|
||||
}
|
||||
|
||||
return {
|
||||
encoding: 'application/json',
|
||||
body: setService.view(setWithSize),
|
||||
}
|
||||
},
|
||||
})
|
||||
}
|
@ -26,12 +26,14 @@ import {
|
||||
ParsedLabelers,
|
||||
parseLabelerHeader,
|
||||
} from './util'
|
||||
import { SetService, SetServiceCreator } from './set/service'
|
||||
|
||||
export type AppContextOptions = {
|
||||
db: Database
|
||||
cfg: OzoneConfig
|
||||
modService: ModerationServiceCreator
|
||||
communicationTemplateService: CommunicationTemplateServiceCreator
|
||||
setService: SetServiceCreator
|
||||
teamService: TeamServiceCreator
|
||||
appviewAgent: AtpAgent
|
||||
pdsAgent: AtpAgent | undefined
|
||||
@ -117,6 +119,7 @@ export class AppContext {
|
||||
|
||||
const communicationTemplateService = CommunicationTemplateService.creator()
|
||||
const teamService = TeamService.creator()
|
||||
const setService = SetService.creator()
|
||||
|
||||
const sequencer = new Sequencer(modService(db))
|
||||
|
||||
@ -133,6 +136,7 @@ export class AppContext {
|
||||
modService,
|
||||
communicationTemplateService,
|
||||
teamService,
|
||||
setService,
|
||||
appviewAgent,
|
||||
pdsAgent,
|
||||
chatAgent,
|
||||
@ -182,6 +186,10 @@ export class AppContext {
|
||||
return this.opts.teamService
|
||||
}
|
||||
|
||||
get setService(): SetServiceCreator {
|
||||
return this.opts.setService
|
||||
}
|
||||
|
||||
get appviewAgent(): AtpAgent {
|
||||
return this.opts.appviewAgent
|
||||
}
|
||||
|
53
packages/ozone/src/db/migrations/20241008T205730722Z-sets.ts
Normal file
53
packages/ozone/src/db/migrations/20241008T205730722Z-sets.ts
Normal file
@ -0,0 +1,53 @@
|
||||
import { Kysely, sql } from 'kysely'
|
||||
|
||||
export async function up(db: Kysely<unknown>): Promise<void> {
|
||||
// Create the sets table
|
||||
await db.schema
|
||||
.createTable('set_detail')
|
||||
.addColumn('id', 'serial', (col) => col.primaryKey())
|
||||
.addColumn('name', 'varchar', (col) => col.notNull().unique())
|
||||
.addColumn('description', 'varchar')
|
||||
.addColumn('createdAt', 'timestamptz', (col) =>
|
||||
col.defaultTo(sql`now()`).notNull(),
|
||||
)
|
||||
.addColumn('updatedAt', 'timestamptz', (col) =>
|
||||
col.defaultTo(sql`now()`).notNull(),
|
||||
)
|
||||
.execute()
|
||||
|
||||
// Create the set values table
|
||||
await db.schema
|
||||
.createTable('set_value')
|
||||
.addColumn('id', 'bigserial', (col) => col.primaryKey())
|
||||
.addColumn('setId', 'integer', (col) =>
|
||||
col.notNull().references('set_detail.id'),
|
||||
)
|
||||
.addColumn('value', 'varchar', (col) => col.notNull())
|
||||
.addColumn('createdAt', 'timestamptz', (col) =>
|
||||
col.defaultTo(sql`now()`).notNull(),
|
||||
)
|
||||
.execute()
|
||||
|
||||
// Add indexes for better performance
|
||||
await db.schema
|
||||
.createIndex('set_detail_name_idx')
|
||||
.on('set_detail')
|
||||
.column('name')
|
||||
.execute()
|
||||
|
||||
// Create a unique constraint on setId and value
|
||||
await db.schema
|
||||
.alterTable('set_value')
|
||||
.addUniqueConstraint('set_value_setid_value_unique', ['setId', 'value'])
|
||||
.execute()
|
||||
await db.schema
|
||||
.createIndex('set_value_setid_created_at_idx')
|
||||
.on('set_value')
|
||||
.columns(['setId', 'createdAt'])
|
||||
.execute()
|
||||
}
|
||||
|
||||
export async function down(db: Kysely<unknown>): Promise<void> {
|
||||
await db.schema.dropTable('set_value').execute()
|
||||
await db.schema.dropTable('set_detail').execute()
|
||||
}
|
@ -14,3 +14,4 @@ export * as _20240814T003647759Z from './20240814T003647759Z-event-created-at-in
|
||||
export * as _20240903T205730722Z from './20240903T205730722Z-add-template-lang'
|
||||
export * as _20240904T205730722Z from './20240904T205730722Z-add-subject-did-index'
|
||||
export * as _20241001T205730722Z from './20241001T205730722Z-subject-status-review-state-index'
|
||||
export * as _20241008T205730722Z from './20241008T205730722Z-sets'
|
||||
|
@ -146,7 +146,7 @@ export class StatusKeyset extends GenericKeyset<StatusKeysetParam, Cursor> {
|
||||
|
||||
type TimeIdKeysetParam = {
|
||||
id: number
|
||||
createdAt: string
|
||||
createdAt: string | Date
|
||||
}
|
||||
type TimeIdResult = TimeIdKeysetParam
|
||||
|
||||
|
@ -7,6 +7,7 @@ import * as blobPushEvent from './blob_push_event'
|
||||
import * as label from './label'
|
||||
import * as signingKey from './signing_key'
|
||||
import * as communicationTemplate from './communication_template'
|
||||
import * as set from './ozone_set'
|
||||
import * as member from './member'
|
||||
|
||||
export type DatabaseSchemaType = modEvent.PartialDB &
|
||||
@ -17,6 +18,7 @@ export type DatabaseSchemaType = modEvent.PartialDB &
|
||||
recordPushEvent.PartialDB &
|
||||
blobPushEvent.PartialDB &
|
||||
communicationTemplate.PartialDB &
|
||||
set.PartialDB &
|
||||
member.PartialDB
|
||||
|
||||
export type DatabaseSchema = Kysely<DatabaseSchemaType>
|
||||
|
24
packages/ozone/src/db/schema/ozone_set.ts
Normal file
24
packages/ozone/src/db/schema/ozone_set.ts
Normal file
@ -0,0 +1,24 @@
|
||||
import { Generated, GeneratedAlways } from 'kysely'
|
||||
|
||||
export const ozoneSetTableName = 'set_detail'
|
||||
export const ozoneSetValueTableName = 'set_value'
|
||||
|
||||
export interface SetDetail {
|
||||
id: GeneratedAlways<number>
|
||||
name: string
|
||||
description: string | null
|
||||
createdAt: Generated<Date>
|
||||
updatedAt: Generated<Date>
|
||||
}
|
||||
|
||||
export interface SetValue {
|
||||
id: GeneratedAlways<number>
|
||||
setId: number
|
||||
value: string
|
||||
createdAt: Generated<Date>
|
||||
}
|
||||
|
||||
export type PartialDB = {
|
||||
[ozoneSetTableName]: SetDetail
|
||||
[ozoneSetValueTableName]: SetValue
|
||||
}
|
@ -173,6 +173,12 @@ import * as ToolsOzoneModerationQueryEvents from './types/tools/ozone/moderation
|
||||
import * as ToolsOzoneModerationQueryStatuses from './types/tools/ozone/moderation/queryStatuses'
|
||||
import * as ToolsOzoneModerationSearchRepos from './types/tools/ozone/moderation/searchRepos'
|
||||
import * as ToolsOzoneServerGetConfig from './types/tools/ozone/server/getConfig'
|
||||
import * as ToolsOzoneSetAddValues from './types/tools/ozone/set/addValues'
|
||||
import * as ToolsOzoneSetDeleteSet from './types/tools/ozone/set/deleteSet'
|
||||
import * as ToolsOzoneSetDeleteValues from './types/tools/ozone/set/deleteValues'
|
||||
import * as ToolsOzoneSetGetValues from './types/tools/ozone/set/getValues'
|
||||
import * as ToolsOzoneSetQuerySets from './types/tools/ozone/set/querySets'
|
||||
import * as ToolsOzoneSetUpsertSet from './types/tools/ozone/set/upsertSet'
|
||||
import * as ToolsOzoneSignatureFindCorrelation from './types/tools/ozone/signature/findCorrelation'
|
||||
import * as ToolsOzoneSignatureFindRelatedAccounts from './types/tools/ozone/signature/findRelatedAccounts'
|
||||
import * as ToolsOzoneSignatureSearchAccounts from './types/tools/ozone/signature/searchAccounts'
|
||||
@ -2164,6 +2170,7 @@ export class ToolsOzoneNS {
|
||||
communication: ToolsOzoneCommunicationNS
|
||||
moderation: ToolsOzoneModerationNS
|
||||
server: ToolsOzoneServerNS
|
||||
set: ToolsOzoneSetNS
|
||||
signature: ToolsOzoneSignatureNS
|
||||
team: ToolsOzoneTeamNS
|
||||
|
||||
@ -2172,6 +2179,7 @@ export class ToolsOzoneNS {
|
||||
this.communication = new ToolsOzoneCommunicationNS(server)
|
||||
this.moderation = new ToolsOzoneModerationNS(server)
|
||||
this.server = new ToolsOzoneServerNS(server)
|
||||
this.set = new ToolsOzoneSetNS(server)
|
||||
this.signature = new ToolsOzoneSignatureNS(server)
|
||||
this.team = new ToolsOzoneTeamNS(server)
|
||||
}
|
||||
@ -2355,6 +2363,80 @@ export class ToolsOzoneServerNS {
|
||||
}
|
||||
}
|
||||
|
||||
export class ToolsOzoneSetNS {
|
||||
_server: Server
|
||||
|
||||
constructor(server: Server) {
|
||||
this._server = server
|
||||
}
|
||||
|
||||
addValues<AV extends AuthVerifier>(
|
||||
cfg: ConfigOf<
|
||||
AV,
|
||||
ToolsOzoneSetAddValues.Handler<ExtractAuth<AV>>,
|
||||
ToolsOzoneSetAddValues.HandlerReqCtx<ExtractAuth<AV>>
|
||||
>,
|
||||
) {
|
||||
const nsid = 'tools.ozone.set.addValues' // @ts-ignore
|
||||
return this._server.xrpc.method(nsid, cfg)
|
||||
}
|
||||
|
||||
deleteSet<AV extends AuthVerifier>(
|
||||
cfg: ConfigOf<
|
||||
AV,
|
||||
ToolsOzoneSetDeleteSet.Handler<ExtractAuth<AV>>,
|
||||
ToolsOzoneSetDeleteSet.HandlerReqCtx<ExtractAuth<AV>>
|
||||
>,
|
||||
) {
|
||||
const nsid = 'tools.ozone.set.deleteSet' // @ts-ignore
|
||||
return this._server.xrpc.method(nsid, cfg)
|
||||
}
|
||||
|
||||
deleteValues<AV extends AuthVerifier>(
|
||||
cfg: ConfigOf<
|
||||
AV,
|
||||
ToolsOzoneSetDeleteValues.Handler<ExtractAuth<AV>>,
|
||||
ToolsOzoneSetDeleteValues.HandlerReqCtx<ExtractAuth<AV>>
|
||||
>,
|
||||
) {
|
||||
const nsid = 'tools.ozone.set.deleteValues' // @ts-ignore
|
||||
return this._server.xrpc.method(nsid, cfg)
|
||||
}
|
||||
|
||||
getValues<AV extends AuthVerifier>(
|
||||
cfg: ConfigOf<
|
||||
AV,
|
||||
ToolsOzoneSetGetValues.Handler<ExtractAuth<AV>>,
|
||||
ToolsOzoneSetGetValues.HandlerReqCtx<ExtractAuth<AV>>
|
||||
>,
|
||||
) {
|
||||
const nsid = 'tools.ozone.set.getValues' // @ts-ignore
|
||||
return this._server.xrpc.method(nsid, cfg)
|
||||
}
|
||||
|
||||
querySets<AV extends AuthVerifier>(
|
||||
cfg: ConfigOf<
|
||||
AV,
|
||||
ToolsOzoneSetQuerySets.Handler<ExtractAuth<AV>>,
|
||||
ToolsOzoneSetQuerySets.HandlerReqCtx<ExtractAuth<AV>>
|
||||
>,
|
||||
) {
|
||||
const nsid = 'tools.ozone.set.querySets' // @ts-ignore
|
||||
return this._server.xrpc.method(nsid, cfg)
|
||||
}
|
||||
|
||||
upsertSet<AV extends AuthVerifier>(
|
||||
cfg: ConfigOf<
|
||||
AV,
|
||||
ToolsOzoneSetUpsertSet.Handler<ExtractAuth<AV>>,
|
||||
ToolsOzoneSetUpsertSet.HandlerReqCtx<ExtractAuth<AV>>
|
||||
>,
|
||||
) {
|
||||
const nsid = 'tools.ozone.set.upsertSet' // @ts-ignore
|
||||
return this._server.xrpc.method(nsid, cfg)
|
||||
}
|
||||
}
|
||||
|
||||
export class ToolsOzoneSignatureNS {
|
||||
_server: Server
|
||||
|
||||
|
@ -12139,6 +12139,300 @@ export const schemaDict = {
|
||||
},
|
||||
},
|
||||
},
|
||||
ToolsOzoneSetAddValues: {
|
||||
lexicon: 1,
|
||||
id: 'tools.ozone.set.addValues',
|
||||
defs: {
|
||||
main: {
|
||||
type: 'procedure',
|
||||
description:
|
||||
'Add values to a specific set. Attempting to add values to a set that does not exist will result in an error.',
|
||||
input: {
|
||||
encoding: 'application/json',
|
||||
schema: {
|
||||
type: 'object',
|
||||
required: ['name', 'values'],
|
||||
properties: {
|
||||
name: {
|
||||
type: 'string',
|
||||
description: 'Name of the set to add values to',
|
||||
},
|
||||
values: {
|
||||
type: 'array',
|
||||
minLength: 1,
|
||||
maxLength: 1000,
|
||||
items: {
|
||||
type: 'string',
|
||||
},
|
||||
description: 'Array of string values to add to the set',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
ToolsOzoneSetDefs: {
|
||||
lexicon: 1,
|
||||
id: 'tools.ozone.set.defs',
|
||||
defs: {
|
||||
set: {
|
||||
type: 'object',
|
||||
required: ['name'],
|
||||
properties: {
|
||||
name: {
|
||||
type: 'string',
|
||||
minLength: 3,
|
||||
maxLength: 128,
|
||||
},
|
||||
description: {
|
||||
type: 'string',
|
||||
maxGraphemes: 1024,
|
||||
maxLength: 10240,
|
||||
},
|
||||
},
|
||||
},
|
||||
setView: {
|
||||
type: 'object',
|
||||
required: ['name', 'setSize', 'createdAt', 'updatedAt'],
|
||||
properties: {
|
||||
name: {
|
||||
type: 'string',
|
||||
minLength: 3,
|
||||
maxLength: 128,
|
||||
},
|
||||
description: {
|
||||
type: 'string',
|
||||
maxGraphemes: 1024,
|
||||
maxLength: 10240,
|
||||
},
|
||||
setSize: {
|
||||
type: 'integer',
|
||||
},
|
||||
createdAt: {
|
||||
type: 'string',
|
||||
format: 'datetime',
|
||||
},
|
||||
updatedAt: {
|
||||
type: 'string',
|
||||
format: 'datetime',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
ToolsOzoneSetDeleteSet: {
|
||||
lexicon: 1,
|
||||
id: 'tools.ozone.set.deleteSet',
|
||||
defs: {
|
||||
main: {
|
||||
type: 'procedure',
|
||||
description:
|
||||
'Delete an entire set. Attempting to delete a set that does not exist will result in an error.',
|
||||
input: {
|
||||
encoding: 'application/json',
|
||||
schema: {
|
||||
type: 'object',
|
||||
required: ['name'],
|
||||
properties: {
|
||||
name: {
|
||||
type: 'string',
|
||||
description: 'Name of the set to delete',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
output: {
|
||||
encoding: 'application/json',
|
||||
schema: {
|
||||
type: 'object',
|
||||
properties: {},
|
||||
},
|
||||
},
|
||||
errors: [
|
||||
{
|
||||
name: 'SetNotFound',
|
||||
description: 'set with the given name does not exist',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
ToolsOzoneSetDeleteValues: {
|
||||
lexicon: 1,
|
||||
id: 'tools.ozone.set.deleteValues',
|
||||
defs: {
|
||||
main: {
|
||||
type: 'procedure',
|
||||
description:
|
||||
'Delete values from a specific set. Attempting to delete values that are not in the set will not result in an error',
|
||||
input: {
|
||||
encoding: 'application/json',
|
||||
schema: {
|
||||
type: 'object',
|
||||
required: ['name', 'values'],
|
||||
properties: {
|
||||
name: {
|
||||
type: 'string',
|
||||
description: 'Name of the set to delete values from',
|
||||
},
|
||||
values: {
|
||||
type: 'array',
|
||||
minLength: 1,
|
||||
items: {
|
||||
type: 'string',
|
||||
},
|
||||
description: 'Array of string values to delete from the set',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
errors: [
|
||||
{
|
||||
name: 'SetNotFound',
|
||||
description: 'set with the given name does not exist',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
ToolsOzoneSetGetValues: {
|
||||
lexicon: 1,
|
||||
id: 'tools.ozone.set.getValues',
|
||||
defs: {
|
||||
main: {
|
||||
type: 'query',
|
||||
description: 'Get a specific set and its values',
|
||||
parameters: {
|
||||
type: 'params',
|
||||
required: ['name'],
|
||||
properties: {
|
||||
name: {
|
||||
type: 'string',
|
||||
},
|
||||
limit: {
|
||||
type: 'integer',
|
||||
minimum: 1,
|
||||
maximum: 1000,
|
||||
default: 100,
|
||||
},
|
||||
cursor: {
|
||||
type: 'string',
|
||||
},
|
||||
},
|
||||
},
|
||||
output: {
|
||||
encoding: 'application/json',
|
||||
schema: {
|
||||
type: 'object',
|
||||
required: ['set', 'values'],
|
||||
properties: {
|
||||
set: {
|
||||
type: 'ref',
|
||||
ref: 'lex:tools.ozone.set.defs#setView',
|
||||
},
|
||||
values: {
|
||||
type: 'array',
|
||||
items: {
|
||||
type: 'string',
|
||||
},
|
||||
},
|
||||
cursor: {
|
||||
type: 'string',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
errors: [
|
||||
{
|
||||
name: 'SetNotFound',
|
||||
description: 'set with the given name does not exist',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
ToolsOzoneSetQuerySets: {
|
||||
lexicon: 1,
|
||||
id: 'tools.ozone.set.querySets',
|
||||
defs: {
|
||||
main: {
|
||||
type: 'query',
|
||||
description: 'Query available sets',
|
||||
parameters: {
|
||||
type: 'params',
|
||||
properties: {
|
||||
limit: {
|
||||
type: 'integer',
|
||||
minimum: 1,
|
||||
maximum: 100,
|
||||
default: 50,
|
||||
},
|
||||
cursor: {
|
||||
type: 'string',
|
||||
},
|
||||
namePrefix: {
|
||||
type: 'string',
|
||||
},
|
||||
sortBy: {
|
||||
type: 'string',
|
||||
enum: ['name', 'createdAt', 'updatedAt'],
|
||||
default: 'name',
|
||||
},
|
||||
sortDirection: {
|
||||
type: 'string',
|
||||
default: 'asc',
|
||||
enum: ['asc', 'desc'],
|
||||
description: 'Defaults to ascending order of name field.',
|
||||
},
|
||||
},
|
||||
},
|
||||
output: {
|
||||
encoding: 'application/json',
|
||||
schema: {
|
||||
type: 'object',
|
||||
required: ['sets'],
|
||||
properties: {
|
||||
sets: {
|
||||
type: 'array',
|
||||
items: {
|
||||
type: 'ref',
|
||||
ref: 'lex:tools.ozone.set.defs#setView',
|
||||
},
|
||||
},
|
||||
cursor: {
|
||||
type: 'string',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
ToolsOzoneSetUpsertSet: {
|
||||
lexicon: 1,
|
||||
id: 'tools.ozone.set.upsertSet',
|
||||
defs: {
|
||||
main: {
|
||||
type: 'procedure',
|
||||
description: 'Create or update set metadata',
|
||||
input: {
|
||||
encoding: 'application/json',
|
||||
schema: {
|
||||
type: 'ref',
|
||||
ref: 'lex:tools.ozone.set.defs#set',
|
||||
},
|
||||
},
|
||||
output: {
|
||||
encoding: 'application/json',
|
||||
schema: {
|
||||
type: 'ref',
|
||||
ref: 'lex:tools.ozone.set.defs#setView',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
ToolsOzoneSignatureDefs: {
|
||||
lexicon: 1,
|
||||
id: 'tools.ozone.signature.defs',
|
||||
@ -12764,6 +13058,13 @@ export const ids = {
|
||||
ToolsOzoneModerationQueryStatuses: 'tools.ozone.moderation.queryStatuses',
|
||||
ToolsOzoneModerationSearchRepos: 'tools.ozone.moderation.searchRepos',
|
||||
ToolsOzoneServerGetConfig: 'tools.ozone.server.getConfig',
|
||||
ToolsOzoneSetAddValues: 'tools.ozone.set.addValues',
|
||||
ToolsOzoneSetDefs: 'tools.ozone.set.defs',
|
||||
ToolsOzoneSetDeleteSet: 'tools.ozone.set.deleteSet',
|
||||
ToolsOzoneSetDeleteValues: 'tools.ozone.set.deleteValues',
|
||||
ToolsOzoneSetGetValues: 'tools.ozone.set.getValues',
|
||||
ToolsOzoneSetQuerySets: 'tools.ozone.set.querySets',
|
||||
ToolsOzoneSetUpsertSet: 'tools.ozone.set.upsertSet',
|
||||
ToolsOzoneSignatureDefs: 'tools.ozone.signature.defs',
|
||||
ToolsOzoneSignatureFindCorrelation: 'tools.ozone.signature.findCorrelation',
|
||||
ToolsOzoneSignatureFindRelatedAccounts:
|
||||
|
@ -0,0 +1,41 @@
|
||||
/**
|
||||
* GENERATED CODE - DO NOT MODIFY
|
||||
*/
|
||||
import express from 'express'
|
||||
import { ValidationResult, BlobRef } from '@atproto/lexicon'
|
||||
import { lexicons } from '../../../../lexicons'
|
||||
import { isObj, hasProp } from '../../../../util'
|
||||
import { CID } from 'multiformats/cid'
|
||||
import { HandlerAuth, HandlerPipeThrough } from '@atproto/xrpc-server'
|
||||
|
||||
export interface QueryParams {}
|
||||
|
||||
export interface InputSchema {
|
||||
/** Name of the set to add values to */
|
||||
name: string
|
||||
/** Array of string values to add to the set */
|
||||
values: string[]
|
||||
[k: string]: unknown
|
||||
}
|
||||
|
||||
export interface HandlerInput {
|
||||
encoding: 'application/json'
|
||||
body: InputSchema
|
||||
}
|
||||
|
||||
export interface HandlerError {
|
||||
status: number
|
||||
message?: string
|
||||
}
|
||||
|
||||
export type HandlerOutput = HandlerError | void
|
||||
export type HandlerReqCtx<HA extends HandlerAuth = never> = {
|
||||
auth: HA
|
||||
params: QueryParams
|
||||
input: HandlerInput
|
||||
req: express.Request
|
||||
res: express.Response
|
||||
}
|
||||
export type Handler<HA extends HandlerAuth = never> = (
|
||||
ctx: HandlerReqCtx<HA>,
|
||||
) => Promise<HandlerOutput> | HandlerOutput
|
44
packages/ozone/src/lexicon/types/tools/ozone/set/defs.ts
Normal file
44
packages/ozone/src/lexicon/types/tools/ozone/set/defs.ts
Normal file
@ -0,0 +1,44 @@
|
||||
/**
|
||||
* GENERATED CODE - DO NOT MODIFY
|
||||
*/
|
||||
import { ValidationResult, BlobRef } from '@atproto/lexicon'
|
||||
import { lexicons } from '../../../../lexicons'
|
||||
import { isObj, hasProp } from '../../../../util'
|
||||
import { CID } from 'multiformats/cid'
|
||||
|
||||
export interface Set {
|
||||
name: string
|
||||
description?: string
|
||||
[k: string]: unknown
|
||||
}
|
||||
|
||||
export function isSet(v: unknown): v is Set {
|
||||
return (
|
||||
isObj(v) && hasProp(v, '$type') && v.$type === 'tools.ozone.set.defs#set'
|
||||
)
|
||||
}
|
||||
|
||||
export function validateSet(v: unknown): ValidationResult {
|
||||
return lexicons.validate('tools.ozone.set.defs#set', v)
|
||||
}
|
||||
|
||||
export interface SetView {
|
||||
name: string
|
||||
description?: string
|
||||
setSize: number
|
||||
createdAt: string
|
||||
updatedAt: string
|
||||
[k: string]: unknown
|
||||
}
|
||||
|
||||
export function isSetView(v: unknown): v is SetView {
|
||||
return (
|
||||
isObj(v) &&
|
||||
hasProp(v, '$type') &&
|
||||
v.$type === 'tools.ozone.set.defs#setView'
|
||||
)
|
||||
}
|
||||
|
||||
export function validateSetView(v: unknown): ValidationResult {
|
||||
return lexicons.validate('tools.ozone.set.defs#setView', v)
|
||||
}
|
@ -0,0 +1,50 @@
|
||||
/**
|
||||
* GENERATED CODE - DO NOT MODIFY
|
||||
*/
|
||||
import express from 'express'
|
||||
import { ValidationResult, BlobRef } from '@atproto/lexicon'
|
||||
import { lexicons } from '../../../../lexicons'
|
||||
import { isObj, hasProp } from '../../../../util'
|
||||
import { CID } from 'multiformats/cid'
|
||||
import { HandlerAuth, HandlerPipeThrough } from '@atproto/xrpc-server'
|
||||
|
||||
export interface QueryParams {}
|
||||
|
||||
export interface InputSchema {
|
||||
/** Name of the set to delete */
|
||||
name: string
|
||||
[k: string]: unknown
|
||||
}
|
||||
|
||||
export interface OutputSchema {
|
||||
[k: string]: unknown
|
||||
}
|
||||
|
||||
export interface HandlerInput {
|
||||
encoding: 'application/json'
|
||||
body: InputSchema
|
||||
}
|
||||
|
||||
export interface HandlerSuccess {
|
||||
encoding: 'application/json'
|
||||
body: OutputSchema
|
||||
headers?: { [key: string]: string }
|
||||
}
|
||||
|
||||
export interface HandlerError {
|
||||
status: number
|
||||
message?: string
|
||||
error?: 'SetNotFound'
|
||||
}
|
||||
|
||||
export type HandlerOutput = HandlerError | HandlerSuccess | HandlerPipeThrough
|
||||
export type HandlerReqCtx<HA extends HandlerAuth = never> = {
|
||||
auth: HA
|
||||
params: QueryParams
|
||||
input: HandlerInput
|
||||
req: express.Request
|
||||
res: express.Response
|
||||
}
|
||||
export type Handler<HA extends HandlerAuth = never> = (
|
||||
ctx: HandlerReqCtx<HA>,
|
||||
) => Promise<HandlerOutput> | HandlerOutput
|
@ -0,0 +1,42 @@
|
||||
/**
|
||||
* GENERATED CODE - DO NOT MODIFY
|
||||
*/
|
||||
import express from 'express'
|
||||
import { ValidationResult, BlobRef } from '@atproto/lexicon'
|
||||
import { lexicons } from '../../../../lexicons'
|
||||
import { isObj, hasProp } from '../../../../util'
|
||||
import { CID } from 'multiformats/cid'
|
||||
import { HandlerAuth, HandlerPipeThrough } from '@atproto/xrpc-server'
|
||||
|
||||
export interface QueryParams {}
|
||||
|
||||
export interface InputSchema {
|
||||
/** Name of the set to delete values from */
|
||||
name: string
|
||||
/** Array of string values to delete from the set */
|
||||
values: string[]
|
||||
[k: string]: unknown
|
||||
}
|
||||
|
||||
export interface HandlerInput {
|
||||
encoding: 'application/json'
|
||||
body: InputSchema
|
||||
}
|
||||
|
||||
export interface HandlerError {
|
||||
status: number
|
||||
message?: string
|
||||
error?: 'SetNotFound'
|
||||
}
|
||||
|
||||
export type HandlerOutput = HandlerError | void
|
||||
export type HandlerReqCtx<HA extends HandlerAuth = never> = {
|
||||
auth: HA
|
||||
params: QueryParams
|
||||
input: HandlerInput
|
||||
req: express.Request
|
||||
res: express.Response
|
||||
}
|
||||
export type Handler<HA extends HandlerAuth = never> = (
|
||||
ctx: HandlerReqCtx<HA>,
|
||||
) => Promise<HandlerOutput> | HandlerOutput
|
@ -0,0 +1,51 @@
|
||||
/**
|
||||
* GENERATED CODE - DO NOT MODIFY
|
||||
*/
|
||||
import express from 'express'
|
||||
import { ValidationResult, BlobRef } from '@atproto/lexicon'
|
||||
import { lexicons } from '../../../../lexicons'
|
||||
import { isObj, hasProp } from '../../../../util'
|
||||
import { CID } from 'multiformats/cid'
|
||||
import { HandlerAuth, HandlerPipeThrough } from '@atproto/xrpc-server'
|
||||
import * as ToolsOzoneSetDefs from './defs'
|
||||
|
||||
export interface QueryParams {
|
||||
name: string
|
||||
limit: number
|
||||
cursor?: string
|
||||
}
|
||||
|
||||
export type InputSchema = undefined
|
||||
|
||||
export interface OutputSchema {
|
||||
set: ToolsOzoneSetDefs.SetView
|
||||
values: string[]
|
||||
cursor?: string
|
||||
[k: string]: unknown
|
||||
}
|
||||
|
||||
export type HandlerInput = undefined
|
||||
|
||||
export interface HandlerSuccess {
|
||||
encoding: 'application/json'
|
||||
body: OutputSchema
|
||||
headers?: { [key: string]: string }
|
||||
}
|
||||
|
||||
export interface HandlerError {
|
||||
status: number
|
||||
message?: string
|
||||
error?: 'SetNotFound'
|
||||
}
|
||||
|
||||
export type HandlerOutput = HandlerError | HandlerSuccess | HandlerPipeThrough
|
||||
export type HandlerReqCtx<HA extends HandlerAuth = never> = {
|
||||
auth: HA
|
||||
params: QueryParams
|
||||
input: HandlerInput
|
||||
req: express.Request
|
||||
res: express.Response
|
||||
}
|
||||
export type Handler<HA extends HandlerAuth = never> = (
|
||||
ctx: HandlerReqCtx<HA>,
|
||||
) => Promise<HandlerOutput> | HandlerOutput
|
@ -0,0 +1,52 @@
|
||||
/**
|
||||
* GENERATED CODE - DO NOT MODIFY
|
||||
*/
|
||||
import express from 'express'
|
||||
import { ValidationResult, BlobRef } from '@atproto/lexicon'
|
||||
import { lexicons } from '../../../../lexicons'
|
||||
import { isObj, hasProp } from '../../../../util'
|
||||
import { CID } from 'multiformats/cid'
|
||||
import { HandlerAuth, HandlerPipeThrough } from '@atproto/xrpc-server'
|
||||
import * as ToolsOzoneSetDefs from './defs'
|
||||
|
||||
export interface QueryParams {
|
||||
limit: number
|
||||
cursor?: string
|
||||
namePrefix?: string
|
||||
sortBy: 'name' | 'createdAt' | 'updatedAt'
|
||||
/** Defaults to ascending order of name field. */
|
||||
sortDirection: 'asc' | 'desc'
|
||||
}
|
||||
|
||||
export type InputSchema = undefined
|
||||
|
||||
export interface OutputSchema {
|
||||
sets: ToolsOzoneSetDefs.SetView[]
|
||||
cursor?: string
|
||||
[k: string]: unknown
|
||||
}
|
||||
|
||||
export type HandlerInput = undefined
|
||||
|
||||
export interface HandlerSuccess {
|
||||
encoding: 'application/json'
|
||||
body: OutputSchema
|
||||
headers?: { [key: string]: string }
|
||||
}
|
||||
|
||||
export interface HandlerError {
|
||||
status: number
|
||||
message?: string
|
||||
}
|
||||
|
||||
export type HandlerOutput = HandlerError | HandlerSuccess | HandlerPipeThrough
|
||||
export type HandlerReqCtx<HA extends HandlerAuth = never> = {
|
||||
auth: HA
|
||||
params: QueryParams
|
||||
input: HandlerInput
|
||||
req: express.Request
|
||||
res: express.Response
|
||||
}
|
||||
export type Handler<HA extends HandlerAuth = never> = (
|
||||
ctx: HandlerReqCtx<HA>,
|
||||
) => Promise<HandlerOutput> | HandlerOutput
|
@ -0,0 +1,43 @@
|
||||
/**
|
||||
* GENERATED CODE - DO NOT MODIFY
|
||||
*/
|
||||
import express from 'express'
|
||||
import { ValidationResult, BlobRef } from '@atproto/lexicon'
|
||||
import { lexicons } from '../../../../lexicons'
|
||||
import { isObj, hasProp } from '../../../../util'
|
||||
import { CID } from 'multiformats/cid'
|
||||
import { HandlerAuth, HandlerPipeThrough } from '@atproto/xrpc-server'
|
||||
import * as ToolsOzoneSetDefs from './defs'
|
||||
|
||||
export interface QueryParams {}
|
||||
|
||||
export type InputSchema = ToolsOzoneSetDefs.Set
|
||||
export type OutputSchema = ToolsOzoneSetDefs.SetView
|
||||
|
||||
export interface HandlerInput {
|
||||
encoding: 'application/json'
|
||||
body: InputSchema
|
||||
}
|
||||
|
||||
export interface HandlerSuccess {
|
||||
encoding: 'application/json'
|
||||
body: OutputSchema
|
||||
headers?: { [key: string]: string }
|
||||
}
|
||||
|
||||
export interface HandlerError {
|
||||
status: number
|
||||
message?: string
|
||||
}
|
||||
|
||||
export type HandlerOutput = HandlerError | HandlerSuccess | HandlerPipeThrough
|
||||
export type HandlerReqCtx<HA extends HandlerAuth = never> = {
|
||||
auth: HA
|
||||
params: QueryParams
|
||||
input: HandlerInput
|
||||
req: express.Request
|
||||
res: express.Response
|
||||
}
|
||||
export type Handler<HA extends HandlerAuth = never> = (
|
||||
ctx: HandlerReqCtx<HA>,
|
||||
) => Promise<HandlerOutput> | HandlerOutput
|
227
packages/ozone/src/set/service.ts
Normal file
227
packages/ozone/src/set/service.ts
Normal file
@ -0,0 +1,227 @@
|
||||
import Database from '../db'
|
||||
import { Selectable } from 'kysely'
|
||||
import { SetDetail } from '../db/schema/ozone_set'
|
||||
import { SetView } from '../lexicon/types/tools/ozone/set/defs'
|
||||
import { paginate, TimeIdKeyset } from '../db/pagination'
|
||||
|
||||
export type SetServiceCreator = (db: Database) => SetService
|
||||
|
||||
export class SetService {
|
||||
constructor(public db: Database) {}
|
||||
|
||||
static creator() {
|
||||
return (db: Database) => new SetService(db)
|
||||
}
|
||||
|
||||
buildQueryForSetWithSize() {
|
||||
return this.db.db.selectFrom('set_detail as s').select([
|
||||
's.id',
|
||||
's.name',
|
||||
's.description',
|
||||
's.createdAt',
|
||||
's.updatedAt',
|
||||
(eb) =>
|
||||
eb
|
||||
.selectFrom('set_value')
|
||||
.select((e) => e.fn.count<number>('setId').as('count'))
|
||||
.whereRef('setId', '=', 's.id')
|
||||
.as('setSize'),
|
||||
])
|
||||
}
|
||||
|
||||
async query({
|
||||
limit,
|
||||
cursor,
|
||||
namePrefix,
|
||||
sortBy,
|
||||
sortDirection,
|
||||
}: {
|
||||
limit: number
|
||||
cursor?: string
|
||||
namePrefix?: string
|
||||
sortBy: 'name' | 'createdAt' | 'updatedAt'
|
||||
sortDirection: 'asc' | 'desc'
|
||||
}): Promise<{
|
||||
sets: Selectable<SetDetail & { setSize: number }>[]
|
||||
cursor?: string
|
||||
}> {
|
||||
let qb = this.buildQueryForSetWithSize().limit(limit)
|
||||
|
||||
if (namePrefix) {
|
||||
qb = qb.where('s.name', 'like', `${namePrefix}%`)
|
||||
}
|
||||
|
||||
if (cursor) {
|
||||
if (sortBy === 'name') {
|
||||
qb = qb.where('s.name', sortDirection === 'asc' ? '>' : '<', cursor)
|
||||
} else {
|
||||
qb = qb.where(
|
||||
`s.${sortBy}`,
|
||||
sortDirection === 'asc' ? '>' : '<',
|
||||
new Date(cursor),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
qb = qb.orderBy(`s.${sortBy}`, sortDirection)
|
||||
|
||||
const sets = await qb.execute()
|
||||
const lastItem = sets.at(-1)
|
||||
|
||||
return {
|
||||
sets,
|
||||
cursor: lastItem
|
||||
? sortBy === 'name'
|
||||
? lastItem?.name
|
||||
: lastItem?.[sortBy].toISOString()
|
||||
: undefined,
|
||||
}
|
||||
}
|
||||
|
||||
async getByName(name: string): Promise<Selectable<SetDetail> | undefined> {
|
||||
const query = this.db.db
|
||||
.selectFrom('set_detail')
|
||||
.selectAll()
|
||||
.where('name', '=', name)
|
||||
|
||||
return await query.executeTakeFirst()
|
||||
}
|
||||
|
||||
async getByNameWithSize(
|
||||
name: string,
|
||||
): Promise<Selectable<SetDetail & { setSize: number }> | undefined> {
|
||||
return await this.buildQueryForSetWithSize()
|
||||
.where('s.name', '=', name)
|
||||
.executeTakeFirst()
|
||||
}
|
||||
|
||||
async getSetWithValues({
|
||||
name,
|
||||
limit,
|
||||
cursor,
|
||||
}: {
|
||||
name: string
|
||||
limit: number
|
||||
cursor?: string
|
||||
}): Promise<
|
||||
| {
|
||||
set: Selectable<SetDetail & { setSize: number }>
|
||||
values: string[]
|
||||
cursor?: string
|
||||
}
|
||||
| undefined
|
||||
> {
|
||||
const set = await this.getByNameWithSize(name)
|
||||
if (!set) return undefined
|
||||
|
||||
const { ref } = this.db.db.dynamic
|
||||
const qb = this.db.db
|
||||
.selectFrom('set_value')
|
||||
.selectAll()
|
||||
.where('setId', '=', set.id)
|
||||
|
||||
const keyset = new TimeIdKeyset(ref(`createdAt`), ref('id'))
|
||||
const paginatedBuilder = paginate(qb, {
|
||||
limit,
|
||||
cursor,
|
||||
keyset,
|
||||
direction: 'asc',
|
||||
})
|
||||
|
||||
const result = await paginatedBuilder.execute()
|
||||
|
||||
return {
|
||||
set,
|
||||
values: result.map((v) => v.value),
|
||||
cursor: keyset.packFromResult(result),
|
||||
}
|
||||
}
|
||||
async upsert({
|
||||
name,
|
||||
description,
|
||||
}: Pick<SetDetail, 'name' | 'description'>): Promise<void> {
|
||||
await this.db.db
|
||||
.insertInto('set_detail')
|
||||
.values({
|
||||
name,
|
||||
description,
|
||||
updatedAt: new Date(),
|
||||
})
|
||||
.onConflict((oc) => {
|
||||
// if description is provided as a string, even an empty one, update it
|
||||
// otherwise, just update the updatedAt timestamp
|
||||
return oc.column('name').doUpdateSet(
|
||||
typeof description === 'string'
|
||||
? {
|
||||
description,
|
||||
updatedAt: new Date(),
|
||||
}
|
||||
: { updatedAt: new Date() },
|
||||
)
|
||||
})
|
||||
.execute()
|
||||
}
|
||||
|
||||
async addValues(setId: number, values: string[]): Promise<void> {
|
||||
await this.db.transaction(async (txn) => {
|
||||
const now = new Date()
|
||||
const query = txn.db
|
||||
.insertInto('set_value')
|
||||
.values(
|
||||
values.map((value) => ({
|
||||
setId,
|
||||
value,
|
||||
createdAt: now,
|
||||
})),
|
||||
)
|
||||
.onConflict((oc) => oc.columns(['setId', 'value']).doNothing())
|
||||
|
||||
await query.execute()
|
||||
|
||||
// Update the set's updatedAt timestamp
|
||||
await txn.db
|
||||
.updateTable('set_detail')
|
||||
.set({ updatedAt: now })
|
||||
.where('id', '=', setId)
|
||||
.execute()
|
||||
})
|
||||
}
|
||||
|
||||
async removeValues(setId: number, values: string[]): Promise<void> {
|
||||
if (values.length < 1) {
|
||||
return
|
||||
}
|
||||
await this.db.transaction(async (txn) => {
|
||||
const query = txn.db
|
||||
.deleteFrom('set_value')
|
||||
.where('setId', '=', setId)
|
||||
.where('value', 'in', values)
|
||||
|
||||
await query.execute()
|
||||
|
||||
// Update the set's updatedAt timestamp
|
||||
await txn.db
|
||||
.updateTable('set_detail')
|
||||
.set({ updatedAt: new Date() })
|
||||
.where('id', '=', setId)
|
||||
.execute()
|
||||
})
|
||||
}
|
||||
|
||||
async removeSet(setId: number): Promise<void> {
|
||||
await this.db.transaction(async (txn) => {
|
||||
await txn.db.deleteFrom('set_value').where('setId', '=', setId).execute()
|
||||
await txn.db.deleteFrom('set_detail').where('id', '=', setId).execute()
|
||||
})
|
||||
}
|
||||
|
||||
view(set: Selectable<SetDetail> & { setSize: number }): SetView {
|
||||
return {
|
||||
name: set.name,
|
||||
description: set.description || undefined,
|
||||
setSize: set.setSize,
|
||||
createdAt: set.createdAt.toISOString(),
|
||||
updatedAt: set.updatedAt.toISOString(),
|
||||
}
|
||||
}
|
||||
}
|
46
packages/ozone/tests/__snapshots__/sets.test.ts.snap
Normal file
46
packages/ozone/tests/__snapshots__/sets.test.ts.snap
Normal file
@ -0,0 +1,46 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`ozone-sets querySets returns all sets when no parameters are provided 1`] = `
|
||||
Array [
|
||||
Object {
|
||||
"createdAt": "1970-01-01T00:00:00.000Z",
|
||||
"description": "Another test set",
|
||||
"name": "another-set",
|
||||
"setSize": 0,
|
||||
"updatedAt": "1970-01-01T00:00:00.000Z",
|
||||
},
|
||||
Object {
|
||||
"createdAt": "1970-01-01T00:00:00.000Z",
|
||||
"description": "Test set 1",
|
||||
"name": "test-set-1",
|
||||
"setSize": 0,
|
||||
"updatedAt": "1970-01-01T00:00:00.000Z",
|
||||
},
|
||||
Object {
|
||||
"createdAt": "1970-01-01T00:00:00.000Z",
|
||||
"name": "test-set-2",
|
||||
"setSize": 0,
|
||||
"updatedAt": "1970-01-01T00:00:00.000Z",
|
||||
},
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`ozone-sets upsertSet creates a new set 1`] = `
|
||||
Object {
|
||||
"createdAt": "1970-01-01T00:00:00.000Z",
|
||||
"description": "A new test set",
|
||||
"name": "new-test-set",
|
||||
"setSize": 0,
|
||||
"updatedAt": "1970-01-01T00:00:00.000Z",
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`ozone-sets upsertSet updates an existing set 1`] = `
|
||||
Object {
|
||||
"createdAt": "1970-01-01T00:00:00.000Z",
|
||||
"description": "Updated description",
|
||||
"name": "new-test-set",
|
||||
"setSize": 0,
|
||||
"updatedAt": "1970-01-01T00:00:00.000Z",
|
||||
}
|
||||
`;
|
246
packages/ozone/tests/sets.test.ts
Normal file
246
packages/ozone/tests/sets.test.ts
Normal file
@ -0,0 +1,246 @@
|
||||
import { TestNetwork, SeedClient, basicSeed } from '@atproto/dev-env'
|
||||
import AtpAgent, {
|
||||
ToolsOzoneSetDefs,
|
||||
ToolsOzoneSetQuerySets,
|
||||
} from '@atproto/api'
|
||||
import { forSnapshot } from './_util'
|
||||
import { ids } from '../src/lexicon/lexicons'
|
||||
|
||||
describe('ozone-sets', () => {
|
||||
let network: TestNetwork
|
||||
let agent: AtpAgent
|
||||
let sc: SeedClient
|
||||
|
||||
const sampleSet1 = {
|
||||
name: 'test-set-1',
|
||||
description: 'Test set 1',
|
||||
}
|
||||
|
||||
const sampleSet2 = {
|
||||
name: 'test-set-2',
|
||||
}
|
||||
|
||||
const sampleSet3 = {
|
||||
name: 'another-set',
|
||||
description: 'Another test set',
|
||||
}
|
||||
|
||||
const upsertSet = async (set: ToolsOzoneSetDefs.Set) => {
|
||||
const { data } = await agent.tools.ozone.set.upsertSet(set, {
|
||||
encoding: 'application/json',
|
||||
headers: await network.ozone.modHeaders(
|
||||
ids.ToolsOzoneSetUpsertSet,
|
||||
'admin',
|
||||
),
|
||||
})
|
||||
|
||||
return data
|
||||
}
|
||||
|
||||
const removeSet = async (name: string) => {
|
||||
await agent.tools.ozone.set.deleteSet(
|
||||
{ name },
|
||||
{
|
||||
encoding: 'application/json',
|
||||
headers: await network.ozone.modHeaders(
|
||||
ids.ToolsOzoneSetDeleteSet,
|
||||
'admin',
|
||||
),
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
const addValues = async (name: string, values: string[]) => {
|
||||
await agent.tools.ozone.set.addValues(
|
||||
{ name, values },
|
||||
{
|
||||
encoding: 'application/json',
|
||||
headers: await network.ozone.modHeaders(
|
||||
ids.ToolsOzoneSetAddValues,
|
||||
'admin',
|
||||
),
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
const getValues = async (name: string, limit?: number, cursor?: string) => {
|
||||
const { data } = await agent.tools.ozone.set.getValues(
|
||||
{ name, limit, cursor },
|
||||
{
|
||||
headers: await network.ozone.modHeaders(
|
||||
ids.ToolsOzoneSetGetValues,
|
||||
'moderator',
|
||||
),
|
||||
},
|
||||
)
|
||||
return data
|
||||
}
|
||||
|
||||
const querySets = async (params: ToolsOzoneSetQuerySets.QueryParams) => {
|
||||
const { data } = await agent.tools.ozone.set.querySets(params, {
|
||||
headers: await network.ozone.modHeaders(
|
||||
ids.ToolsOzoneSetQuerySets,
|
||||
'moderator',
|
||||
),
|
||||
})
|
||||
return data
|
||||
}
|
||||
|
||||
beforeAll(async () => {
|
||||
network = await TestNetwork.create({
|
||||
dbPostgresSchema: 'ozone_sets',
|
||||
})
|
||||
agent = network.ozone.getClient()
|
||||
sc = network.getSeedClient()
|
||||
await basicSeed(sc)
|
||||
await network.processAll()
|
||||
})
|
||||
|
||||
afterAll(async () => {
|
||||
await network.close()
|
||||
})
|
||||
|
||||
describe('querySets', () => {
|
||||
beforeAll(async () => {
|
||||
await Promise.all([
|
||||
upsertSet(sampleSet1),
|
||||
upsertSet(sampleSet2),
|
||||
upsertSet(sampleSet3),
|
||||
])
|
||||
})
|
||||
afterAll(async () => {
|
||||
await Promise.all([
|
||||
removeSet(sampleSet1.name),
|
||||
removeSet(sampleSet2.name),
|
||||
removeSet(sampleSet3.name),
|
||||
])
|
||||
})
|
||||
it('returns all sets when no parameters are provided', async () => {
|
||||
const result = await querySets({})
|
||||
expect(result.sets.length).toBe(3)
|
||||
expect(forSnapshot(result.sets)).toMatchSnapshot()
|
||||
})
|
||||
|
||||
it('limits the number of returned sets', async () => {
|
||||
const result = await querySets({ limit: 2 })
|
||||
expect(result.sets.length).toBe(2)
|
||||
expect(result.cursor).toBeDefined()
|
||||
})
|
||||
|
||||
it('returns sets after the cursor', async () => {
|
||||
const firstPage = await querySets({ limit: 2 })
|
||||
const secondPage = await querySets({ cursor: firstPage.cursor })
|
||||
expect(secondPage.sets.length).toBe(1)
|
||||
expect(secondPage.sets[0].name).toBe('test-set-2')
|
||||
})
|
||||
|
||||
it('filters sets by name prefix', async () => {
|
||||
const result = await querySets({ namePrefix: 'test-' })
|
||||
expect(result.sets.length).toBe(2)
|
||||
expect(result.sets.map((s) => s.name)).toEqual([
|
||||
'test-set-1',
|
||||
'test-set-2',
|
||||
])
|
||||
})
|
||||
|
||||
it('sorts sets by given column and direction', async () => {
|
||||
const sortedByName = await querySets({ sortBy: 'name' })
|
||||
expect(sortedByName.sets.map((s) => s.name)).toEqual([
|
||||
'another-set',
|
||||
'test-set-1',
|
||||
'test-set-2',
|
||||
])
|
||||
const reverseSortedByName = await querySets({
|
||||
sortBy: 'name',
|
||||
sortDirection: 'desc',
|
||||
})
|
||||
expect(reverseSortedByName.sets.map((s) => s.name)).toEqual([
|
||||
'test-set-2',
|
||||
'test-set-1',
|
||||
'another-set',
|
||||
])
|
||||
})
|
||||
})
|
||||
|
||||
describe('upsertSet', () => {
|
||||
afterAll(async () => {
|
||||
await removeSet('new-test-set')
|
||||
})
|
||||
it('creates a new set', async () => {
|
||||
const result = await upsertSet({
|
||||
name: 'new-test-set',
|
||||
description: 'A new test set',
|
||||
})
|
||||
expect(forSnapshot(result)).toMatchSnapshot()
|
||||
})
|
||||
|
||||
it('updates an existing set', async () => {
|
||||
const result = await upsertSet({
|
||||
name: 'new-test-set',
|
||||
description: 'Updated description',
|
||||
})
|
||||
expect(forSnapshot(result)).toMatchSnapshot()
|
||||
})
|
||||
|
||||
it('allows setting empty description', async () => {
|
||||
const result = await upsertSet({
|
||||
name: 'new-test-set',
|
||||
description: '',
|
||||
})
|
||||
expect(result.description).toBeUndefined()
|
||||
})
|
||||
})
|
||||
|
||||
describe('addValues', () => {
|
||||
beforeAll(async () => {
|
||||
await upsertSet(sampleSet1)
|
||||
await upsertSet(sampleSet2)
|
||||
})
|
||||
afterAll(async () => {
|
||||
await removeSet(sampleSet1.name)
|
||||
await removeSet(sampleSet2.name)
|
||||
})
|
||||
it('adds new values to an existing set', async () => {
|
||||
const newValues = ['value1', 'value2', 'value3']
|
||||
await addValues(sampleSet1.name, newValues)
|
||||
|
||||
const result = await getValues(sampleSet1.name)
|
||||
expect(result.values).toEqual(expect.arrayContaining(newValues))
|
||||
})
|
||||
|
||||
it('does not duplicate existing values', async () => {
|
||||
const initialValues = ['initial1', 'initial2']
|
||||
await addValues(sampleSet2.name, initialValues)
|
||||
|
||||
const newValues = ['initial2', 'new1', 'new2']
|
||||
await addValues(sampleSet2.name, newValues)
|
||||
|
||||
const result = await getValues(sampleSet2.name)
|
||||
expect(result.values).toEqual(
|
||||
expect.arrayContaining([...initialValues, 'new1', 'new2']),
|
||||
)
|
||||
expect(result.values.filter((v) => v === 'initial2').length).toBe(1)
|
||||
})
|
||||
})
|
||||
|
||||
describe('getValues', () => {
|
||||
beforeAll(async () => {
|
||||
await upsertSet(sampleSet1)
|
||||
})
|
||||
afterAll(async () => {
|
||||
await removeSet(sampleSet1.name)
|
||||
})
|
||||
it('paginates values from a set', async () => {
|
||||
const allValues = Array.from({ length: 9 }, (_, i) => `value${i}`)
|
||||
await addValues(sampleSet1.name, allValues)
|
||||
|
||||
const firstPage = await getValues(sampleSet1.name, 3)
|
||||
const secondPage = await getValues(sampleSet1.name, 3, firstPage.cursor)
|
||||
const lastPage = await getValues(sampleSet1.name, 3, secondPage.cursor)
|
||||
|
||||
expect(firstPage.values).toEqual(allValues.slice(0, 3))
|
||||
expect(secondPage.values).toEqual(allValues.slice(3, 6))
|
||||
expect(lastPage.values).toEqual(allValues.slice(6, 9))
|
||||
})
|
||||
})
|
||||
})
|
@ -173,6 +173,12 @@ import * as ToolsOzoneModerationQueryEvents from './types/tools/ozone/moderation
|
||||
import * as ToolsOzoneModerationQueryStatuses from './types/tools/ozone/moderation/queryStatuses'
|
||||
import * as ToolsOzoneModerationSearchRepos from './types/tools/ozone/moderation/searchRepos'
|
||||
import * as ToolsOzoneServerGetConfig from './types/tools/ozone/server/getConfig'
|
||||
import * as ToolsOzoneSetAddValues from './types/tools/ozone/set/addValues'
|
||||
import * as ToolsOzoneSetDeleteSet from './types/tools/ozone/set/deleteSet'
|
||||
import * as ToolsOzoneSetDeleteValues from './types/tools/ozone/set/deleteValues'
|
||||
import * as ToolsOzoneSetGetValues from './types/tools/ozone/set/getValues'
|
||||
import * as ToolsOzoneSetQuerySets from './types/tools/ozone/set/querySets'
|
||||
import * as ToolsOzoneSetUpsertSet from './types/tools/ozone/set/upsertSet'
|
||||
import * as ToolsOzoneSignatureFindCorrelation from './types/tools/ozone/signature/findCorrelation'
|
||||
import * as ToolsOzoneSignatureFindRelatedAccounts from './types/tools/ozone/signature/findRelatedAccounts'
|
||||
import * as ToolsOzoneSignatureSearchAccounts from './types/tools/ozone/signature/searchAccounts'
|
||||
@ -2164,6 +2170,7 @@ export class ToolsOzoneNS {
|
||||
communication: ToolsOzoneCommunicationNS
|
||||
moderation: ToolsOzoneModerationNS
|
||||
server: ToolsOzoneServerNS
|
||||
set: ToolsOzoneSetNS
|
||||
signature: ToolsOzoneSignatureNS
|
||||
team: ToolsOzoneTeamNS
|
||||
|
||||
@ -2172,6 +2179,7 @@ export class ToolsOzoneNS {
|
||||
this.communication = new ToolsOzoneCommunicationNS(server)
|
||||
this.moderation = new ToolsOzoneModerationNS(server)
|
||||
this.server = new ToolsOzoneServerNS(server)
|
||||
this.set = new ToolsOzoneSetNS(server)
|
||||
this.signature = new ToolsOzoneSignatureNS(server)
|
||||
this.team = new ToolsOzoneTeamNS(server)
|
||||
}
|
||||
@ -2355,6 +2363,80 @@ export class ToolsOzoneServerNS {
|
||||
}
|
||||
}
|
||||
|
||||
export class ToolsOzoneSetNS {
|
||||
_server: Server
|
||||
|
||||
constructor(server: Server) {
|
||||
this._server = server
|
||||
}
|
||||
|
||||
addValues<AV extends AuthVerifier>(
|
||||
cfg: ConfigOf<
|
||||
AV,
|
||||
ToolsOzoneSetAddValues.Handler<ExtractAuth<AV>>,
|
||||
ToolsOzoneSetAddValues.HandlerReqCtx<ExtractAuth<AV>>
|
||||
>,
|
||||
) {
|
||||
const nsid = 'tools.ozone.set.addValues' // @ts-ignore
|
||||
return this._server.xrpc.method(nsid, cfg)
|
||||
}
|
||||
|
||||
deleteSet<AV extends AuthVerifier>(
|
||||
cfg: ConfigOf<
|
||||
AV,
|
||||
ToolsOzoneSetDeleteSet.Handler<ExtractAuth<AV>>,
|
||||
ToolsOzoneSetDeleteSet.HandlerReqCtx<ExtractAuth<AV>>
|
||||
>,
|
||||
) {
|
||||
const nsid = 'tools.ozone.set.deleteSet' // @ts-ignore
|
||||
return this._server.xrpc.method(nsid, cfg)
|
||||
}
|
||||
|
||||
deleteValues<AV extends AuthVerifier>(
|
||||
cfg: ConfigOf<
|
||||
AV,
|
||||
ToolsOzoneSetDeleteValues.Handler<ExtractAuth<AV>>,
|
||||
ToolsOzoneSetDeleteValues.HandlerReqCtx<ExtractAuth<AV>>
|
||||
>,
|
||||
) {
|
||||
const nsid = 'tools.ozone.set.deleteValues' // @ts-ignore
|
||||
return this._server.xrpc.method(nsid, cfg)
|
||||
}
|
||||
|
||||
getValues<AV extends AuthVerifier>(
|
||||
cfg: ConfigOf<
|
||||
AV,
|
||||
ToolsOzoneSetGetValues.Handler<ExtractAuth<AV>>,
|
||||
ToolsOzoneSetGetValues.HandlerReqCtx<ExtractAuth<AV>>
|
||||
>,
|
||||
) {
|
||||
const nsid = 'tools.ozone.set.getValues' // @ts-ignore
|
||||
return this._server.xrpc.method(nsid, cfg)
|
||||
}
|
||||
|
||||
querySets<AV extends AuthVerifier>(
|
||||
cfg: ConfigOf<
|
||||
AV,
|
||||
ToolsOzoneSetQuerySets.Handler<ExtractAuth<AV>>,
|
||||
ToolsOzoneSetQuerySets.HandlerReqCtx<ExtractAuth<AV>>
|
||||
>,
|
||||
) {
|
||||
const nsid = 'tools.ozone.set.querySets' // @ts-ignore
|
||||
return this._server.xrpc.method(nsid, cfg)
|
||||
}
|
||||
|
||||
upsertSet<AV extends AuthVerifier>(
|
||||
cfg: ConfigOf<
|
||||
AV,
|
||||
ToolsOzoneSetUpsertSet.Handler<ExtractAuth<AV>>,
|
||||
ToolsOzoneSetUpsertSet.HandlerReqCtx<ExtractAuth<AV>>
|
||||
>,
|
||||
) {
|
||||
const nsid = 'tools.ozone.set.upsertSet' // @ts-ignore
|
||||
return this._server.xrpc.method(nsid, cfg)
|
||||
}
|
||||
}
|
||||
|
||||
export class ToolsOzoneSignatureNS {
|
||||
_server: Server
|
||||
|
||||
|
@ -12139,6 +12139,300 @@ export const schemaDict = {
|
||||
},
|
||||
},
|
||||
},
|
||||
ToolsOzoneSetAddValues: {
|
||||
lexicon: 1,
|
||||
id: 'tools.ozone.set.addValues',
|
||||
defs: {
|
||||
main: {
|
||||
type: 'procedure',
|
||||
description:
|
||||
'Add values to a specific set. Attempting to add values to a set that does not exist will result in an error.',
|
||||
input: {
|
||||
encoding: 'application/json',
|
||||
schema: {
|
||||
type: 'object',
|
||||
required: ['name', 'values'],
|
||||
properties: {
|
||||
name: {
|
||||
type: 'string',
|
||||
description: 'Name of the set to add values to',
|
||||
},
|
||||
values: {
|
||||
type: 'array',
|
||||
minLength: 1,
|
||||
maxLength: 1000,
|
||||
items: {
|
||||
type: 'string',
|
||||
},
|
||||
description: 'Array of string values to add to the set',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
ToolsOzoneSetDefs: {
|
||||
lexicon: 1,
|
||||
id: 'tools.ozone.set.defs',
|
||||
defs: {
|
||||
set: {
|
||||
type: 'object',
|
||||
required: ['name'],
|
||||
properties: {
|
||||
name: {
|
||||
type: 'string',
|
||||
minLength: 3,
|
||||
maxLength: 128,
|
||||
},
|
||||
description: {
|
||||
type: 'string',
|
||||
maxGraphemes: 1024,
|
||||
maxLength: 10240,
|
||||
},
|
||||
},
|
||||
},
|
||||
setView: {
|
||||
type: 'object',
|
||||
required: ['name', 'setSize', 'createdAt', 'updatedAt'],
|
||||
properties: {
|
||||
name: {
|
||||
type: 'string',
|
||||
minLength: 3,
|
||||
maxLength: 128,
|
||||
},
|
||||
description: {
|
||||
type: 'string',
|
||||
maxGraphemes: 1024,
|
||||
maxLength: 10240,
|
||||
},
|
||||
setSize: {
|
||||
type: 'integer',
|
||||
},
|
||||
createdAt: {
|
||||
type: 'string',
|
||||
format: 'datetime',
|
||||
},
|
||||
updatedAt: {
|
||||
type: 'string',
|
||||
format: 'datetime',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
ToolsOzoneSetDeleteSet: {
|
||||
lexicon: 1,
|
||||
id: 'tools.ozone.set.deleteSet',
|
||||
defs: {
|
||||
main: {
|
||||
type: 'procedure',
|
||||
description:
|
||||
'Delete an entire set. Attempting to delete a set that does not exist will result in an error.',
|
||||
input: {
|
||||
encoding: 'application/json',
|
||||
schema: {
|
||||
type: 'object',
|
||||
required: ['name'],
|
||||
properties: {
|
||||
name: {
|
||||
type: 'string',
|
||||
description: 'Name of the set to delete',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
output: {
|
||||
encoding: 'application/json',
|
||||
schema: {
|
||||
type: 'object',
|
||||
properties: {},
|
||||
},
|
||||
},
|
||||
errors: [
|
||||
{
|
||||
name: 'SetNotFound',
|
||||
description: 'set with the given name does not exist',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
ToolsOzoneSetDeleteValues: {
|
||||
lexicon: 1,
|
||||
id: 'tools.ozone.set.deleteValues',
|
||||
defs: {
|
||||
main: {
|
||||
type: 'procedure',
|
||||
description:
|
||||
'Delete values from a specific set. Attempting to delete values that are not in the set will not result in an error',
|
||||
input: {
|
||||
encoding: 'application/json',
|
||||
schema: {
|
||||
type: 'object',
|
||||
required: ['name', 'values'],
|
||||
properties: {
|
||||
name: {
|
||||
type: 'string',
|
||||
description: 'Name of the set to delete values from',
|
||||
},
|
||||
values: {
|
||||
type: 'array',
|
||||
minLength: 1,
|
||||
items: {
|
||||
type: 'string',
|
||||
},
|
||||
description: 'Array of string values to delete from the set',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
errors: [
|
||||
{
|
||||
name: 'SetNotFound',
|
||||
description: 'set with the given name does not exist',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
ToolsOzoneSetGetValues: {
|
||||
lexicon: 1,
|
||||
id: 'tools.ozone.set.getValues',
|
||||
defs: {
|
||||
main: {
|
||||
type: 'query',
|
||||
description: 'Get a specific set and its values',
|
||||
parameters: {
|
||||
type: 'params',
|
||||
required: ['name'],
|
||||
properties: {
|
||||
name: {
|
||||
type: 'string',
|
||||
},
|
||||
limit: {
|
||||
type: 'integer',
|
||||
minimum: 1,
|
||||
maximum: 1000,
|
||||
default: 100,
|
||||
},
|
||||
cursor: {
|
||||
type: 'string',
|
||||
},
|
||||
},
|
||||
},
|
||||
output: {
|
||||
encoding: 'application/json',
|
||||
schema: {
|
||||
type: 'object',
|
||||
required: ['set', 'values'],
|
||||
properties: {
|
||||
set: {
|
||||
type: 'ref',
|
||||
ref: 'lex:tools.ozone.set.defs#setView',
|
||||
},
|
||||
values: {
|
||||
type: 'array',
|
||||
items: {
|
||||
type: 'string',
|
||||
},
|
||||
},
|
||||
cursor: {
|
||||
type: 'string',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
errors: [
|
||||
{
|
||||
name: 'SetNotFound',
|
||||
description: 'set with the given name does not exist',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
ToolsOzoneSetQuerySets: {
|
||||
lexicon: 1,
|
||||
id: 'tools.ozone.set.querySets',
|
||||
defs: {
|
||||
main: {
|
||||
type: 'query',
|
||||
description: 'Query available sets',
|
||||
parameters: {
|
||||
type: 'params',
|
||||
properties: {
|
||||
limit: {
|
||||
type: 'integer',
|
||||
minimum: 1,
|
||||
maximum: 100,
|
||||
default: 50,
|
||||
},
|
||||
cursor: {
|
||||
type: 'string',
|
||||
},
|
||||
namePrefix: {
|
||||
type: 'string',
|
||||
},
|
||||
sortBy: {
|
||||
type: 'string',
|
||||
enum: ['name', 'createdAt', 'updatedAt'],
|
||||
default: 'name',
|
||||
},
|
||||
sortDirection: {
|
||||
type: 'string',
|
||||
default: 'asc',
|
||||
enum: ['asc', 'desc'],
|
||||
description: 'Defaults to ascending order of name field.',
|
||||
},
|
||||
},
|
||||
},
|
||||
output: {
|
||||
encoding: 'application/json',
|
||||
schema: {
|
||||
type: 'object',
|
||||
required: ['sets'],
|
||||
properties: {
|
||||
sets: {
|
||||
type: 'array',
|
||||
items: {
|
||||
type: 'ref',
|
||||
ref: 'lex:tools.ozone.set.defs#setView',
|
||||
},
|
||||
},
|
||||
cursor: {
|
||||
type: 'string',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
ToolsOzoneSetUpsertSet: {
|
||||
lexicon: 1,
|
||||
id: 'tools.ozone.set.upsertSet',
|
||||
defs: {
|
||||
main: {
|
||||
type: 'procedure',
|
||||
description: 'Create or update set metadata',
|
||||
input: {
|
||||
encoding: 'application/json',
|
||||
schema: {
|
||||
type: 'ref',
|
||||
ref: 'lex:tools.ozone.set.defs#set',
|
||||
},
|
||||
},
|
||||
output: {
|
||||
encoding: 'application/json',
|
||||
schema: {
|
||||
type: 'ref',
|
||||
ref: 'lex:tools.ozone.set.defs#setView',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
ToolsOzoneSignatureDefs: {
|
||||
lexicon: 1,
|
||||
id: 'tools.ozone.signature.defs',
|
||||
@ -12764,6 +13058,13 @@ export const ids = {
|
||||
ToolsOzoneModerationQueryStatuses: 'tools.ozone.moderation.queryStatuses',
|
||||
ToolsOzoneModerationSearchRepos: 'tools.ozone.moderation.searchRepos',
|
||||
ToolsOzoneServerGetConfig: 'tools.ozone.server.getConfig',
|
||||
ToolsOzoneSetAddValues: 'tools.ozone.set.addValues',
|
||||
ToolsOzoneSetDefs: 'tools.ozone.set.defs',
|
||||
ToolsOzoneSetDeleteSet: 'tools.ozone.set.deleteSet',
|
||||
ToolsOzoneSetDeleteValues: 'tools.ozone.set.deleteValues',
|
||||
ToolsOzoneSetGetValues: 'tools.ozone.set.getValues',
|
||||
ToolsOzoneSetQuerySets: 'tools.ozone.set.querySets',
|
||||
ToolsOzoneSetUpsertSet: 'tools.ozone.set.upsertSet',
|
||||
ToolsOzoneSignatureDefs: 'tools.ozone.signature.defs',
|
||||
ToolsOzoneSignatureFindCorrelation: 'tools.ozone.signature.findCorrelation',
|
||||
ToolsOzoneSignatureFindRelatedAccounts:
|
||||
|
41
packages/pds/src/lexicon/types/tools/ozone/set/addValues.ts
Normal file
41
packages/pds/src/lexicon/types/tools/ozone/set/addValues.ts
Normal file
@ -0,0 +1,41 @@
|
||||
/**
|
||||
* GENERATED CODE - DO NOT MODIFY
|
||||
*/
|
||||
import express from 'express'
|
||||
import { ValidationResult, BlobRef } from '@atproto/lexicon'
|
||||
import { lexicons } from '../../../../lexicons'
|
||||
import { isObj, hasProp } from '../../../../util'
|
||||
import { CID } from 'multiformats/cid'
|
||||
import { HandlerAuth, HandlerPipeThrough } from '@atproto/xrpc-server'
|
||||
|
||||
export interface QueryParams {}
|
||||
|
||||
export interface InputSchema {
|
||||
/** Name of the set to add values to */
|
||||
name: string
|
||||
/** Array of string values to add to the set */
|
||||
values: string[]
|
||||
[k: string]: unknown
|
||||
}
|
||||
|
||||
export interface HandlerInput {
|
||||
encoding: 'application/json'
|
||||
body: InputSchema
|
||||
}
|
||||
|
||||
export interface HandlerError {
|
||||
status: number
|
||||
message?: string
|
||||
}
|
||||
|
||||
export type HandlerOutput = HandlerError | void
|
||||
export type HandlerReqCtx<HA extends HandlerAuth = never> = {
|
||||
auth: HA
|
||||
params: QueryParams
|
||||
input: HandlerInput
|
||||
req: express.Request
|
||||
res: express.Response
|
||||
}
|
||||
export type Handler<HA extends HandlerAuth = never> = (
|
||||
ctx: HandlerReqCtx<HA>,
|
||||
) => Promise<HandlerOutput> | HandlerOutput
|
44
packages/pds/src/lexicon/types/tools/ozone/set/defs.ts
Normal file
44
packages/pds/src/lexicon/types/tools/ozone/set/defs.ts
Normal file
@ -0,0 +1,44 @@
|
||||
/**
|
||||
* GENERATED CODE - DO NOT MODIFY
|
||||
*/
|
||||
import { ValidationResult, BlobRef } from '@atproto/lexicon'
|
||||
import { lexicons } from '../../../../lexicons'
|
||||
import { isObj, hasProp } from '../../../../util'
|
||||
import { CID } from 'multiformats/cid'
|
||||
|
||||
export interface Set {
|
||||
name: string
|
||||
description?: string
|
||||
[k: string]: unknown
|
||||
}
|
||||
|
||||
export function isSet(v: unknown): v is Set {
|
||||
return (
|
||||
isObj(v) && hasProp(v, '$type') && v.$type === 'tools.ozone.set.defs#set'
|
||||
)
|
||||
}
|
||||
|
||||
export function validateSet(v: unknown): ValidationResult {
|
||||
return lexicons.validate('tools.ozone.set.defs#set', v)
|
||||
}
|
||||
|
||||
export interface SetView {
|
||||
name: string
|
||||
description?: string
|
||||
setSize: number
|
||||
createdAt: string
|
||||
updatedAt: string
|
||||
[k: string]: unknown
|
||||
}
|
||||
|
||||
export function isSetView(v: unknown): v is SetView {
|
||||
return (
|
||||
isObj(v) &&
|
||||
hasProp(v, '$type') &&
|
||||
v.$type === 'tools.ozone.set.defs#setView'
|
||||
)
|
||||
}
|
||||
|
||||
export function validateSetView(v: unknown): ValidationResult {
|
||||
return lexicons.validate('tools.ozone.set.defs#setView', v)
|
||||
}
|
50
packages/pds/src/lexicon/types/tools/ozone/set/deleteSet.ts
Normal file
50
packages/pds/src/lexicon/types/tools/ozone/set/deleteSet.ts
Normal file
@ -0,0 +1,50 @@
|
||||
/**
|
||||
* GENERATED CODE - DO NOT MODIFY
|
||||
*/
|
||||
import express from 'express'
|
||||
import { ValidationResult, BlobRef } from '@atproto/lexicon'
|
||||
import { lexicons } from '../../../../lexicons'
|
||||
import { isObj, hasProp } from '../../../../util'
|
||||
import { CID } from 'multiformats/cid'
|
||||
import { HandlerAuth, HandlerPipeThrough } from '@atproto/xrpc-server'
|
||||
|
||||
export interface QueryParams {}
|
||||
|
||||
export interface InputSchema {
|
||||
/** Name of the set to delete */
|
||||
name: string
|
||||
[k: string]: unknown
|
||||
}
|
||||
|
||||
export interface OutputSchema {
|
||||
[k: string]: unknown
|
||||
}
|
||||
|
||||
export interface HandlerInput {
|
||||
encoding: 'application/json'
|
||||
body: InputSchema
|
||||
}
|
||||
|
||||
export interface HandlerSuccess {
|
||||
encoding: 'application/json'
|
||||
body: OutputSchema
|
||||
headers?: { [key: string]: string }
|
||||
}
|
||||
|
||||
export interface HandlerError {
|
||||
status: number
|
||||
message?: string
|
||||
error?: 'SetNotFound'
|
||||
}
|
||||
|
||||
export type HandlerOutput = HandlerError | HandlerSuccess | HandlerPipeThrough
|
||||
export type HandlerReqCtx<HA extends HandlerAuth = never> = {
|
||||
auth: HA
|
||||
params: QueryParams
|
||||
input: HandlerInput
|
||||
req: express.Request
|
||||
res: express.Response
|
||||
}
|
||||
export type Handler<HA extends HandlerAuth = never> = (
|
||||
ctx: HandlerReqCtx<HA>,
|
||||
) => Promise<HandlerOutput> | HandlerOutput
|
@ -0,0 +1,42 @@
|
||||
/**
|
||||
* GENERATED CODE - DO NOT MODIFY
|
||||
*/
|
||||
import express from 'express'
|
||||
import { ValidationResult, BlobRef } from '@atproto/lexicon'
|
||||
import { lexicons } from '../../../../lexicons'
|
||||
import { isObj, hasProp } from '../../../../util'
|
||||
import { CID } from 'multiformats/cid'
|
||||
import { HandlerAuth, HandlerPipeThrough } from '@atproto/xrpc-server'
|
||||
|
||||
export interface QueryParams {}
|
||||
|
||||
export interface InputSchema {
|
||||
/** Name of the set to delete values from */
|
||||
name: string
|
||||
/** Array of string values to delete from the set */
|
||||
values: string[]
|
||||
[k: string]: unknown
|
||||
}
|
||||
|
||||
export interface HandlerInput {
|
||||
encoding: 'application/json'
|
||||
body: InputSchema
|
||||
}
|
||||
|
||||
export interface HandlerError {
|
||||
status: number
|
||||
message?: string
|
||||
error?: 'SetNotFound'
|
||||
}
|
||||
|
||||
export type HandlerOutput = HandlerError | void
|
||||
export type HandlerReqCtx<HA extends HandlerAuth = never> = {
|
||||
auth: HA
|
||||
params: QueryParams
|
||||
input: HandlerInput
|
||||
req: express.Request
|
||||
res: express.Response
|
||||
}
|
||||
export type Handler<HA extends HandlerAuth = never> = (
|
||||
ctx: HandlerReqCtx<HA>,
|
||||
) => Promise<HandlerOutput> | HandlerOutput
|
51
packages/pds/src/lexicon/types/tools/ozone/set/getValues.ts
Normal file
51
packages/pds/src/lexicon/types/tools/ozone/set/getValues.ts
Normal file
@ -0,0 +1,51 @@
|
||||
/**
|
||||
* GENERATED CODE - DO NOT MODIFY
|
||||
*/
|
||||
import express from 'express'
|
||||
import { ValidationResult, BlobRef } from '@atproto/lexicon'
|
||||
import { lexicons } from '../../../../lexicons'
|
||||
import { isObj, hasProp } from '../../../../util'
|
||||
import { CID } from 'multiformats/cid'
|
||||
import { HandlerAuth, HandlerPipeThrough } from '@atproto/xrpc-server'
|
||||
import * as ToolsOzoneSetDefs from './defs'
|
||||
|
||||
export interface QueryParams {
|
||||
name: string
|
||||
limit: number
|
||||
cursor?: string
|
||||
}
|
||||
|
||||
export type InputSchema = undefined
|
||||
|
||||
export interface OutputSchema {
|
||||
set: ToolsOzoneSetDefs.SetView
|
||||
values: string[]
|
||||
cursor?: string
|
||||
[k: string]: unknown
|
||||
}
|
||||
|
||||
export type HandlerInput = undefined
|
||||
|
||||
export interface HandlerSuccess {
|
||||
encoding: 'application/json'
|
||||
body: OutputSchema
|
||||
headers?: { [key: string]: string }
|
||||
}
|
||||
|
||||
export interface HandlerError {
|
||||
status: number
|
||||
message?: string
|
||||
error?: 'SetNotFound'
|
||||
}
|
||||
|
||||
export type HandlerOutput = HandlerError | HandlerSuccess | HandlerPipeThrough
|
||||
export type HandlerReqCtx<HA extends HandlerAuth = never> = {
|
||||
auth: HA
|
||||
params: QueryParams
|
||||
input: HandlerInput
|
||||
req: express.Request
|
||||
res: express.Response
|
||||
}
|
||||
export type Handler<HA extends HandlerAuth = never> = (
|
||||
ctx: HandlerReqCtx<HA>,
|
||||
) => Promise<HandlerOutput> | HandlerOutput
|
52
packages/pds/src/lexicon/types/tools/ozone/set/querySets.ts
Normal file
52
packages/pds/src/lexicon/types/tools/ozone/set/querySets.ts
Normal file
@ -0,0 +1,52 @@
|
||||
/**
|
||||
* GENERATED CODE - DO NOT MODIFY
|
||||
*/
|
||||
import express from 'express'
|
||||
import { ValidationResult, BlobRef } from '@atproto/lexicon'
|
||||
import { lexicons } from '../../../../lexicons'
|
||||
import { isObj, hasProp } from '../../../../util'
|
||||
import { CID } from 'multiformats/cid'
|
||||
import { HandlerAuth, HandlerPipeThrough } from '@atproto/xrpc-server'
|
||||
import * as ToolsOzoneSetDefs from './defs'
|
||||
|
||||
export interface QueryParams {
|
||||
limit: number
|
||||
cursor?: string
|
||||
namePrefix?: string
|
||||
sortBy: 'name' | 'createdAt' | 'updatedAt'
|
||||
/** Defaults to ascending order of name field. */
|
||||
sortDirection: 'asc' | 'desc'
|
||||
}
|
||||
|
||||
export type InputSchema = undefined
|
||||
|
||||
export interface OutputSchema {
|
||||
sets: ToolsOzoneSetDefs.SetView[]
|
||||
cursor?: string
|
||||
[k: string]: unknown
|
||||
}
|
||||
|
||||
export type HandlerInput = undefined
|
||||
|
||||
export interface HandlerSuccess {
|
||||
encoding: 'application/json'
|
||||
body: OutputSchema
|
||||
headers?: { [key: string]: string }
|
||||
}
|
||||
|
||||
export interface HandlerError {
|
||||
status: number
|
||||
message?: string
|
||||
}
|
||||
|
||||
export type HandlerOutput = HandlerError | HandlerSuccess | HandlerPipeThrough
|
||||
export type HandlerReqCtx<HA extends HandlerAuth = never> = {
|
||||
auth: HA
|
||||
params: QueryParams
|
||||
input: HandlerInput
|
||||
req: express.Request
|
||||
res: express.Response
|
||||
}
|
||||
export type Handler<HA extends HandlerAuth = never> = (
|
||||
ctx: HandlerReqCtx<HA>,
|
||||
) => Promise<HandlerOutput> | HandlerOutput
|
43
packages/pds/src/lexicon/types/tools/ozone/set/upsertSet.ts
Normal file
43
packages/pds/src/lexicon/types/tools/ozone/set/upsertSet.ts
Normal file
@ -0,0 +1,43 @@
|
||||
/**
|
||||
* GENERATED CODE - DO NOT MODIFY
|
||||
*/
|
||||
import express from 'express'
|
||||
import { ValidationResult, BlobRef } from '@atproto/lexicon'
|
||||
import { lexicons } from '../../../../lexicons'
|
||||
import { isObj, hasProp } from '../../../../util'
|
||||
import { CID } from 'multiformats/cid'
|
||||
import { HandlerAuth, HandlerPipeThrough } from '@atproto/xrpc-server'
|
||||
import * as ToolsOzoneSetDefs from './defs'
|
||||
|
||||
export interface QueryParams {}
|
||||
|
||||
export type InputSchema = ToolsOzoneSetDefs.Set
|
||||
export type OutputSchema = ToolsOzoneSetDefs.SetView
|
||||
|
||||
export interface HandlerInput {
|
||||
encoding: 'application/json'
|
||||
body: InputSchema
|
||||
}
|
||||
|
||||
export interface HandlerSuccess {
|
||||
encoding: 'application/json'
|
||||
body: OutputSchema
|
||||
headers?: { [key: string]: string }
|
||||
}
|
||||
|
||||
export interface HandlerError {
|
||||
status: number
|
||||
message?: string
|
||||
}
|
||||
|
||||
export type HandlerOutput = HandlerError | HandlerSuccess | HandlerPipeThrough
|
||||
export type HandlerReqCtx<HA extends HandlerAuth = never> = {
|
||||
auth: HA
|
||||
params: QueryParams
|
||||
input: HandlerInput
|
||||
req: express.Request
|
||||
res: express.Response
|
||||
}
|
||||
export type Handler<HA extends HandlerAuth = never> = (
|
||||
ctx: HandlerReqCtx<HA>,
|
||||
) => Promise<HandlerOutput> | HandlerOutput
|
Loading…
x
Reference in New Issue
Block a user