+23
-38
.tangled/workflows/deploy.yaml
+23
-38
.tangled/workflows/deploy.yaml
···
1
-
name: Deploy
1
+
engine: nixery
2
+
when:
3
+
- event: ["push", "pull_request"]
4
+
branch: ["main"]
2
5
3
-
on:
4
-
push:
5
-
branches: [main]
6
+
dependencies:
7
+
nixpkgs:
8
+
- nodejs
9
+
- gnused
6
10
7
-
jobs:
8
-
deploy:
9
-
runs-on: ubuntu-latest
10
-
steps:
11
-
- uses: actions/checkout@v4
12
-
13
-
- uses: pnpm/action-setup@v4
14
-
with:
15
-
version: 9
16
-
17
-
- uses: actions/setup-node@v4
18
-
with:
19
-
node-version: '20'
20
-
cache: 'pnpm'
21
-
22
-
- name: Install dependencies
23
-
run: pnpm install
24
-
25
-
- name: Build website
26
-
run: pnpm run build
27
-
working-directory: ./packages/website
28
-
29
-
- name: Build playground
30
-
run: pnpm run build
31
-
working-directory: ./packages/playground
32
-
33
-
Deployment commands (commented out - uncomment when ready to deploy):
34
-
- name: Deploy playground
35
-
run: npx --yes wrangler pages deploy --branch main --project-name typelex-playground ./dist/
36
-
working-directory: ./packages/playground
37
-
38
-
- name: Deploy website
39
-
run: npx --yes wrangler pages deploy --branch main --project-name typelex ./dist/
40
-
working-directory: ./packages/website
11
+
steps:
12
+
- name: install and build
13
+
command: |
14
+
npx pnpm install
15
+
cd packages/emitter && npx pnpm run build
16
+
cd ../website && npx pnpm run build
17
+
cd ../playground && npx pnpm run build
18
+
- name: deploy playground
19
+
command: |
20
+
cd packages/playground
21
+
npx --yes wrangler pages deploy --branch main --project-name typelex-playground ./dist/
22
+
- name: deploy website
23
+
command: |
24
+
cd packages/website
25
+
npx --yes wrangler pages deploy --branch main --project-name typelex ./dist/
+23
CHANGELOG.md
+23
CHANGELOG.md
···
1
+
### 0.2.0
2
+
3
+
- Add `@external` support
4
+
5
+
### 0.1.6
6
+
7
+
- Rebuild
8
+
9
+
### 0.1.5
10
+
11
+
- Allow tokens in string unions
12
+
13
+
### 0.1.4
14
+
15
+
- Fix some namespaces failing to emit
16
+
17
+
### 0.1.3
18
+
19
+
- Fix some namespaces failing to emit
20
+
21
+
### 0.1.2
22
+
23
+
- Disallow mixing `@required` with `?:`
+11
-34
CLAUDE.md
+11
-34
CLAUDE.md
···
1
-
you're working on a TypeSpec emitter for atproto lexicons. you have these commands: `pnpm run build` builds the example (you can inspect the generated lexicons in the `packages/example/lexicon`) and `pnpm test` runs tests (they are in `packages/emitter/test/`).
1
+
you're working on a TypeSpec emitter for atproto Lexicons. the goal is to make a more comfortable language for writing lexicons, kind of like "coffeescript for lexicons" (however terrible that may be). one may imagine it getting supplanted by a proper atproto IDL someday. however, we're staying within what TypeSpec offers, which means we want to stay idiomatic both to atproto and TypeSpec, or rather, to try to translate atproto idioms into TypeSpec idioms as closely as we can.
2
2
3
-
what i want you to do is to gradually keep adding features to typelex so that in the end it's possible to express all Lexicon code with that language. you have the following resources:
3
+
you have the following resources you're encouraged to explore on your own whenever they seem relevant to the task:
4
4
5
-
- read `DOCS.md`!!! it's the main guideline
5
+
- `DOCS.md` is a must-read. it gives you an intro to typelex and how its conventions map to atproto. it also gives you a sense of the project philosophy.
6
+
- `../atproto-website/` has a Lexicon spec (look for `lexicon/en.mdx`) which you'll want to consult
7
+
- `../typespec/` is the TypeSpec repo. you can consult the source code of other emitters (in `packages`, e.g. `packages/protobuf` and `packages/json-schema`) and `website` folder for documentation of TypeSpec syntax and idioms.
6
8
7
-
- `../typespec/packages` has a bunch of other emitters (so you can check how they're implemented and common patterns)
9
+
as a part of your workflow, you will:
8
10
9
-
- `../typespec/website/src/content` has typescpec docs (which you might find very useful)
11
+
- run `pnpm test` whenever you make changes to verify no regressions. note a few test suites: an `atproto` test suite with definitions from upstream (`.tsp` files produce expected `.json` files), `lexicon-examples` suite with third party lexicons, and `spec` with a more focused suite. use checked-in `*.tsp` files liberally to learn typelex conventions. we have a LOT of them!
10
12
11
-
- `../atproto-website/src/app/[locale]/specs/lexicon` contains lexicon spec (where we want to reach feature parity), and most importantly
13
+
- if you're working on `packages/example`, use `pnpm run build` to run it and observe the output. you may also want to look at codegen output (it's hooked up to atproto codegen).
12
14
13
-
- `test/scenarios/atproto/output` contains a TON of lexicon definitions which i want you to translate to typespec one by one. for each atproto lexicon you're porting, your job is to create the corresponding "`input`s" for them (and fix bugs or add missing features along the way).
15
+
- we also have a playground in `packages/playground` and website in `packages/website`.
14
16
15
-
the goal is to end up with a language that feels nice and concise, not some weird interop thing. so try to do things "typespec" way as you go through each lexicon. and try to respect atproto too. this should feel like a *language for atproto*. consider whether your design is elegant. and make sure to look at other typespec emitters for design ideas!
16
-
17
-
remember NOT to change the output to fit the input -- your job is to make the input MATCH the output. if some lexicon is too hard, you can give up on it and try another one. good luck!
18
-
19
-
the workflow is: pick some new lexicons, create the input files, figure out missing features / bugs, and try to get tests to pass. repeat. when you make nontrivial progress, you'll want to prepare a commit.
20
-
21
-
before you want to make a commit, make sure `pnpm test` and `pnpm run build` passes and, ideally, inspect the `example` app output (and maybe add the features you've just implemented there for parity). then stop and notify me.
22
-
23
-
ps. be mindful of the code style. we only put decorators on same line if it's `@required` alone; otherwise, put each on newline and add a newline after. see existing files for a hint.
17
+
you'll approach the project thoughtfully. while `playground` and `website` are more vibey and can be garbage code, it's essential to keep the `emitter` making sense. this doesn't just mean always verifying the tests pass (that's a given), but also making each decision *based on the spec* and a good understanding of atproto semantics. always think: is this the simplest solution? does it still make sense if you forget the code that exists now and think from first principles? don't hesitate to pause and ask or rethink if something actually doesn't make sense.
24
18
25
19
good luck! i believe in you
26
20
27
-
28
-
---
29
-
30
-
whenever you get stuck (try `npm test`) because you don't have a convention for how to define some pattern yetm i want you to read these sources
31
-
32
-
- `../typespec/packages` has a bunch of other emitters (so you can check how they're implemented and common patterns)
33
-
34
-
- `../typespec/website/src/content` has typescpec docs (which you might find very useful)
35
-
36
-
- `../atproto-website/src/app/[locale]/specs/lexicon` contains lexicon spec
37
-
38
-
and ultrathink about what's the most appropriate way to define defs like you want would be in this typespec translation of atproto. you can research these sources for what feels most idiomatic to define that syntax, and how to make
39
-
the formatter understand that convention and emit the JSON we want.
40
-
41
-
also note that you can always look at generated atproto lexicons in ../atproto/lexicons -- use these!! look at the TS types there for corresponding
42
-
models to inspire how you represent things in tsp syntax.
43
-
44
-
- read `DOCS.md`!!! it's the main guideline
21
+
and read the `DOCS.md` (and `*.tsp` files in this repo)!!! they're your most important sources of information.
+711
-395
DOCS.md
+711
-395
DOCS.md
···
1
-
# Typelex Docs
1
+
# typelex docs
2
+
3
+
Typelex is a [TypeSpec](https://typespec.io/) emitter that outputs [AT Lexicon](https://atproto.com/specs/lexicon) JSON files.
4
+
5
+
## Introduction
6
+
7
+
### What's Lexicon?
8
+
9
+
[Lexicon](https://atproto.com/specs/lexicon) is a schema format used by [AT](https://atproto.com/) applications. Here's a small example:
10
+
11
+
```json
12
+
{
13
+
"lexicon": 1,
14
+
"id": "app.bsky.bookmark.defs",
15
+
"defs": {
16
+
"listItemView": {
17
+
"type": "object",
18
+
"properties": {
19
+
"uri": { "type": "string", "format": "at-uri" }
20
+
},
21
+
"required": ["uri"]
22
+
}
23
+
}
24
+
}
25
+
```
2
26
3
-
This maps [atproto Lexicon](https://atproto.com/specs/lexicon) JSON syntax to typelex (which is a [TypeSpec](https://typespec.io/) emitter). It assumes you're familiar with Lexicon and want to understand how to express it in TypeSpec. Consult [TypeSpec docs](https://typespec.io/) on details of TypeSpec syntax.
27
+
This schema is then used to generate code for parsing of these objects, their validation, and their types.
4
28
5
-
This page was mostly written by Claude based on the test fixtures from this repo (which are [deployed in the playground](https://playground.typelex.org/)). I hope it's mostly correct and comprehensible. When in doubt, refer to those fixtures.
29
+
### What's TypeSpec?
6
30
7
-
## Playground
31
+
[TypeSpec](https://typespec.io/) is a TypeScript-like language for writing schemas for data and API calls. It offers flexible syntax and tooling (like LSP), but doesn't specify output formatโthat's what *emitters* do. For example, there's a [JSON Schema emitter](https://typespec.io/docs/emitters/json-schema/reference/) and a [Protobuf emitter](https://typespec.io/docs/emitters/protobuf/reference/).
8
32
9
-
Go to https://playground.typelex.org/ to play with a bunch of lexicons.
33
+
### What's typelex?
34
+
35
+
Typelex is a TypeSpec emitter targeting Lexicon. Here's the same schema in TypeSpec:
36
+
37
+
```typescript
38
+
import "@typelex/emitter";
39
+
40
+
namespace app.bsky.bookmark.defs {
41
+
model ListItemView {
42
+
@required uri: atUri;
43
+
}
44
+
}
45
+
```
46
+
47
+
Run the compiler, and it generates Lexicon JSON for you.
48
+
49
+
The JSON is what you'll publishโtypelex just makes authoring easier. Think of it as "CoffeeScript for Lexicon" (however terrible that may be).
50
+
51
+
Typelex tries to stay faithful to both TypeSpec idioms and Lexicon concepts, which is a tricky balance. Since we can't add keywords to TypeSpec, decorators fill the gapsโyou'll write `@procedure op` instead of `procedure`, or `model` for what Lexicon calls a "def". One downside of this approach is you'll need to learn both Lexicon *and* TypeSpec to know what you're doing. Scan the [TypeSpec language overview](https://typespec.io/docs/language-basics/overview/) to get a feel for it.
52
+
53
+
Personally, I find JSON Lexicons hard to read and author, so the tradeoff works for me.
54
+
55
+
### Playground
56
+
57
+
[Open Playground](https://playground.typelex.org/) to play with a bunch of lexicons and to see how typelex code translates to Lexicon JSON.
58
+
59
+
If you already know Lexicon, you can learn the syntax by just opening the Lexicons you're familiar with.
10
60
11
61
## Quick Start
12
62
13
-
Every TypeSpec file starts with an import and namespace:
63
+
### Namespaces
64
+
65
+
A namespace corresponds to a Lexicon file:
14
66
15
67
```typescript
16
68
import "@typelex/emitter";
17
69
18
-
/** Common definitions used by other lexicons */
19
-
namespace com.example.defs {
20
-
// definitions here
70
+
namespace app.bsky.feed.defs {
71
+
model PostView {
72
+
// ...
73
+
}
21
74
}
22
75
```
23
76
24
-
**Maps to:**
77
+
This emits `app/bsky/feed/defs.json`:
78
+
25
79
```json
26
80
{
27
81
"lexicon": 1,
28
-
"id": "com.example.defs",
29
-
"description": "Common definitions used by other lexicons",
82
+
"id": "app.bsky.feed.defs",
30
83
"defs": { ... }
31
84
}
32
85
```
33
86
34
-
Use `/** */` doc comments for descriptions (or `@doc()` decorator as alternative).
87
+
[Try it in the playground](https://playground.typelex.org/?c=aW1wb3J0ICJAdHlwZWxleC9lbWl0dGVyIjsKCm5hbWVzcGFjZSBhcHAuYnNreS5mZWVkLmRlZnMgewogIG1vZGVsIFBvc3RWaWV3xRMgIHJlcGx5Q291bnQ%2FOiBpbnRlZ2VyO8gab3N01RtsaWtl0xl9Cn0K&e=%40typelex%2Femitter&options=%7B%7D&vs=%7B%7D).
35
88
36
-
## Top-Level Lexicon Types
89
+
If TypeSpec complains about reserved words in namespaces, use backticks:
90
+
91
+
```typescript
92
+
import "@typelex/emitter";
93
+
94
+
namespace app.bsky.feed.post.`record` { }
95
+
namespace `pub`.blocks.blockquote { }
96
+
```
37
97
38
-
### Query (XRPC Query)
98
+
You can define multiple namespaces in one file:
39
99
40
100
```typescript
41
-
namespace com.example.getRecord {
42
-
/** Retrieve a record by ID */
43
-
@query
44
-
op main(
45
-
/** The record identifier */
46
-
@required id: string
47
-
): {
48
-
@required record: com.example.record.Main;
49
-
};
101
+
import "@typelex/emitter";
102
+
103
+
namespace com.example.foo {
104
+
model Main { /* ... */ }
105
+
}
106
+
107
+
namespace com.example.bar {
108
+
model Main { /* ... */ }
50
109
}
51
110
```
52
111
53
-
**Maps to:** `{"type": "query", ...}` with `parameters` and `output`
112
+
This emits two files: `com/example/foo.json` and `com/example/bar.json`.
113
+
114
+
You can `import` other `.tsp` files to reuse definitions. Output structure is determined solely by namespaces, not by source file organization.
54
115
55
-
### Procedure (XRPC Procedure)
116
+
## Models
117
+
118
+
By default, **every `model` becomes a Lexicon definition**:
56
119
57
120
```typescript
58
-
namespace com.example.createRecord {
59
-
/** Create a new record */
60
-
@procedure
61
-
op main(input: {
62
-
@required text: string;
63
-
}): {
64
-
@required uri: atUri;
65
-
@required cid: cid;
66
-
};
121
+
import "@typelex/emitter";
122
+
123
+
namespace app.bsky.feed.defs {
124
+
model PostView { /* ... */ }
125
+
model ViewerState { /* ... */ }
126
+
}
127
+
```
128
+
129
+
Model names convert PascalCase โ camelCase. For example, `PostView` becomes `postView`:
130
+
131
+
```json
132
+
{
133
+
"id": "app.bsky.feed.defs",
134
+
"defs": {
135
+
"postView": { /* ... */ },
136
+
"viewerState": { /* ... */ }
137
+
}
138
+
// ...
67
139
}
68
140
```
69
141
70
-
**Maps to:** `{"type": "procedure", ...}` with `input` and `output`
142
+
Models in the same namespace can be in separate `namespace` blocks or even different files (via [`import`](https://typespec.io/docs/language-basics/imports/)). TypeSpec bundles them all into one Lexicon file per namespace.
143
+
144
+
### Namespace Conventions: `.defs` vs `Main`
71
145
72
-
### Subscription (XRPC Subscription)
146
+
By convention, a namespace must either end with `.defs` or have a `Main` model.
147
+
148
+
Use `.defs` for a grabbag of reusable definitions:
73
149
74
150
```typescript
75
-
namespace com.example.subscribeRecords {
76
-
/** Subscribe to record updates */
77
-
@subscription
78
-
op main(cursor?: integer): (Record | Delete);
151
+
import "@typelex/emitter";
152
+
153
+
namespace app.bsky.feed.defs {
154
+
model PostView { /* ... */ }
155
+
model ViewerState { /* ... */ }
156
+
}
157
+
```
158
+
159
+
For a Lexicon about one main concept, add a `Main` model instead:
79
160
80
-
model Record {
81
-
@required uri: atUri;
82
-
@required record: com.example.record.Main;
83
-
}
161
+
```typescript
162
+
import "@typelex/emitter";
84
163
85
-
model Delete {
86
-
@required uri: atUri;
87
-
}
164
+
namespace app.bsky.embed.video {
165
+
model Main { /* ... */ }
166
+
model Caption { /* ... */ }
88
167
}
89
168
```
90
169
91
-
**Maps to:** `{"type": "subscription", ...}` with `message` containing union
170
+
Pick one or the otherโthe compiler will error if you don't.
171
+
172
+
### References
92
173
93
-
### Record
174
+
Models can reference other models:
94
175
95
176
```typescript
96
-
namespace com.example.post {
97
-
@rec("tid")
98
-
/** A post record */
177
+
import "@typelex/emitter";
178
+
179
+
namespace app.bsky.embed.video {
99
180
model Main {
100
-
@required text: string;
101
-
@required createdAt: datetime;
181
+
captions?: Caption[];
102
182
}
183
+
model Caption { /* ... */ }
103
184
}
104
185
```
105
186
106
-
**Maps to:** `{"type": "record", "key": "tid", "record": {...}}`
187
+
This becomes a `ref` to the `caption` definition in the same file:
107
188
108
-
**Record key types:** `@rec("tid")`, `@rec("any")`, `@rec("nsid")`
189
+
```json
190
+
// ...
191
+
"defs": {
192
+
"main": {
193
+
// ...
194
+
"properties": {
195
+
"captions": {
196
+
// ...
197
+
"items": { "type": "ref", "ref": "#caption" }
198
+
}
199
+
}
200
+
},
201
+
"caption": {
202
+
"type": "object",
203
+
"properties": {}
204
+
}
205
+
// ...
206
+
```
109
207
110
-
### Object (Plain Definition)
208
+
You can also reference models from other namespaces:
111
209
112
210
```typescript
113
-
namespace com.example.defs {
114
-
/** User metadata */
115
-
model Metadata {
116
-
version?: integer = 1;
117
-
tags?: string[];
211
+
import "@typelex/emitter";
212
+
213
+
namespace app.bsky.actor.profile {
214
+
model Main {
215
+
labels?: (com.atproto.label.defs.SelfLabels | unknown);
118
216
}
119
217
}
218
+
219
+
namespace com.atproto.label.defs {
220
+
model SelfLabels { /* ... */ }
221
+
}
120
222
```
121
223
122
-
**Maps to:** `{"type": "object", "properties": {...}}`
224
+
This becomes a fully qualified reference to another Lexicon:
123
225
124
-
## Reserved Keywords
226
+
```json
227
+
// ...
228
+
"labels": {
229
+
"type": "union",
230
+
"refs": ["com.atproto.label.defs#selfLabels"]
231
+
}
232
+
// ...
233
+
```
125
234
126
-
Use backticks for TypeScript/TypeSpec reserved words:
235
+
([See it in the Playground](https://playground.typelex.org/?c=aW1wb3J0ICJAdHlwZWxleC9lbWl0dGVyIjsKCm5hbWVzcGFjZSBhcHAuYnNreS5hY3Rvci5wcm9maWxlIHsKICBAcmVjKCJsaXRlcmFsOnNlbGYiKQogIG1vZGVsIE1haW7FJiAgZGlzcGxheU5hbWU%2FOiBzdHJpbmc7xRpsYWJlbHM%2FOiAoY29tLmF0cHJvdG8uxRYuZGVmcy5TZWxmTMUlIHwgdW5rbm93binEPH0KfewAptY%2F5QCA5gCPy0nEFSAgLy8gLi4uxko%3D&e=%40typelex%2Femitter&options=%7B%7D&vs=%7B%7D).)
127
236
128
-
```typescript
129
-
namespace app.bsky.feed.post.`record` { ... }
130
-
namespace `pub`.leaflet.subscription { ... }
131
-
```
237
+
This works across files tooโjust remember to `import` the file with the definition.
132
238
133
-
## Inline vs Definitions
239
+
### External Stubs
134
240
135
-
**By default, models become separate defs.** Use `@inline` to prevent this:
241
+
If you don't have TypeSpec definitions for external Lexicons, you can stub them out using the `@external` decorator:
136
242
137
243
```typescript
138
-
// Without @inline - becomes separate def "statusEnum"
139
-
union StatusEnum {
140
-
"active",
141
-
"inactive",
244
+
import "@typelex/emitter";
245
+
246
+
namespace app.bsky.actor.profile {
247
+
model Main {
248
+
labels?: (com.atproto.label.defs.SelfLabels | unknown);
249
+
}
142
250
}
143
251
144
-
// With @inline - inlined where used
145
-
@inline
146
-
union StatusEnum {
147
-
"active",
148
-
"inactive",
252
+
// Empty stub (like .d.ts in TypeScript)
253
+
@external
254
+
namespace com.atproto.label.defs {
255
+
model SelfLabels { }
149
256
}
150
257
```
151
258
152
-
Use `@inline` when you want the type directly embedded rather than referenced.
259
+
The `@external` decorator tells the emitter to skip JSON output for that namespace. This is useful when referencing definitions from other Lexicons that you don't want to re-emit.
260
+
261
+
You could collect external stubs in one file and import them:
262
+
263
+
```typescript
264
+
import "@typelex/emitter";
265
+
import "../atproto-stubs.tsp";
153
266
154
-
## Optional vs Required Fields
267
+
namespace app.bsky.actor.profile {
268
+
model Main {
269
+
labels?: (com.atproto.label.defs.SelfLabels | unknown);
270
+
}
271
+
}
272
+
```
155
273
156
-
**In lexicons, optional fields are the norm.** Required fields are discouraged and need explicit `@required`:
274
+
Then in `atproto-stubs.tsp`:
157
275
158
276
```typescript
159
-
model Post {
160
-
text?: string; // optional (common)
161
-
@required createdAt: datetime; // required (discouraged, needs decorator)
277
+
import "@typelex/emitter";
278
+
279
+
@external
280
+
namespace com.atproto.label.defs {
281
+
model SelfLabels { }
162
282
}
163
-
```
164
283
165
-
**Maps to:**
166
-
```json
167
-
{
168
-
"type": "object",
169
-
"required": ["createdAt"],
170
-
"properties": {
171
-
"text": {"type": "string"},
172
-
"createdAt": {"type": "string", "format": "datetime"}
173
-
}
284
+
@external
285
+
namespace com.atproto.repo.defs {
286
+
model StrongRef { }
287
+
@token model SomeToken { } // Note: Tokens still need @token
174
288
}
289
+
// ... more stubs
175
290
```
176
291
177
-
## Primitive Types
292
+
You'll want to ensure the real JSON for external Lexicons is available before running codegen.
178
293
179
-
| TypeSpec | Lexicon JSON |
180
-
|----------|--------------|
181
-
| `boolean` | `{"type": "boolean"}` |
182
-
| `integer` | `{"type": "integer"}` |
183
-
| `string` | `{"type": "string"}` |
184
-
| `bytes` | `{"type": "bytes"}` |
185
-
| `cidLink` | `{"type": "cid-link"}` |
186
-
| `unknown` | `{"type": "unknown"}` |
294
+
### Inline Models
187
295
188
-
## Format Types
296
+
By default, every `model` becomes a top-level def:
189
297
190
-
Specialized string formats:
191
-
192
-
| TypeSpec | Lexicon Format |
193
-
|----------|----------------|
194
-
| `atIdentifier` | `at-identifier` - Handle or DID |
195
-
| `atUri` | `at-uri` - AT Protocol URI |
196
-
| `cid` | `cid` - Content ID |
197
-
| `datetime` | `datetime` - ISO 8601 datetime |
198
-
| `did` | `did` - DID identifier |
199
-
| `handle` | `handle` - Handle identifier |
200
-
| `nsid` | `nsid` - Namespaced ID |
201
-
| `tid` | `tid` - Timestamp ID |
202
-
| `recordKey` | `record-key` - Record key |
203
-
| `uri` | `uri` - Generic URI |
204
-
| `language` | `language` - Language tag |
298
+
```typescript
299
+
import "@typelex/emitter";
205
300
206
-
## Unions
301
+
namespace app.bsky.embed.video {
302
+
model Main {
303
+
captions?: Caption[];
304
+
}
305
+
model Caption { /* ... */ }
306
+
}
307
+
```
207
308
208
-
### Open Unions (Common Pattern)
309
+
This creates two defs: `main` and `caption`.
209
310
210
-
**Open unions are the default and preferred in lexicons.** Add `unknown` to mark as open:
311
+
Use `@inline` to expand a model inline instead:
211
312
212
313
```typescript
213
-
model Main {
214
-
/** Can be any of these types or future additions */
215
-
@required item: TypeA | TypeB | TypeC | unknown;
216
-
}
314
+
import "@typelex/emitter";
217
315
218
-
model TypeA {
219
-
@readOnly @required kind: string = "a";
220
-
@required valueA: string;
316
+
namespace app.bsky.embed.video {
317
+
model Main {
318
+
captions?: Caption[];
319
+
}
320
+
321
+
@inline
322
+
model Caption {
323
+
text?: string
324
+
}
221
325
}
222
326
```
223
327
224
-
**Maps to:**
328
+
Now `Caption` is expanded inline:
329
+
225
330
```json
226
-
{
227
-
"properties": {
228
-
"item": {
229
-
"type": "union",
230
-
"refs": ["#typeA", "#typeB", "#typeC"]
231
-
}
331
+
// ...
332
+
"captions": {
333
+
"type": "array",
334
+
"items": {
335
+
"type": "object",
336
+
"properties": { "text": { "type": "string" } }
232
337
}
233
338
}
339
+
// ...
234
340
```
235
341
236
-
The `unknown` makes it open but doesn't appear in refs.
342
+
Note that `Caption` won't exist as a separate defโthe abstraction is erased in the output.
343
+
344
+
## Top-Level Lexicon Types
345
+
346
+
TypeSpec uses `model` for almost everything. Decorators specify what kind of Lexicon type it becomes.
237
347
238
-
### Known Values (Open String Enum)
348
+
### Objects
239
349
240
-
Suggest values but allow others:
350
+
A plain `model` becomes a Lexicon object:
241
351
242
352
```typescript
243
-
model Main {
244
-
/** Language - suggests common values but allows any */
245
-
lang?: "en" | "es" | "fr" | string;
353
+
import "@typelex/emitter";
354
+
355
+
namespace com.example.post {
356
+
model Main { /* ... */ }
246
357
}
247
358
```
248
359
249
-
**Maps to:**
360
+
Output:
361
+
250
362
```json
251
-
{
252
-
"properties": {
253
-
"lang": {
254
-
"type": "string",
255
-
"knownValues": ["en", "es", "fr"]
256
-
}
257
-
}
363
+
// ...
364
+
"main": {
365
+
"type": "object",
366
+
"properties": { /* ... */ }
258
367
}
368
+
// ...
259
369
```
260
370
261
-
### Closed Unions (Discouraged)
371
+
### Records
262
372
263
-
**โ ๏ธ Closed unions are discouraged in lexicons** as they prevent future additions. Use only when absolutely necessary:
373
+
Use `@rec` to make a model a Lexicon record:
264
374
265
375
```typescript
266
-
@closed
267
-
@inline
268
-
union Action {
269
-
Create,
270
-
Update,
271
-
Delete,
272
-
}
376
+
import "@typelex/emitter";
273
377
274
-
model Main {
275
-
@required action: Action;
378
+
namespace com.example.post {
379
+
@rec("tid")
380
+
model Main { /* ... */ }
276
381
}
277
382
```
278
383
279
-
**Maps to:**
384
+
Output:
385
+
280
386
```json
281
-
{
282
-
"properties": {
283
-
"action": {
284
-
"type": "union",
285
-
"refs": ["#create", "#update", "#delete"],
286
-
"closed": true
287
-
}
288
-
}
387
+
// ...
388
+
"main": {
389
+
"type": "record",
390
+
"key": "tid",
391
+
"record": { "type": "object", "properties": { /* ... */ } }
289
392
}
393
+
// ...
290
394
```
291
395
292
-
### Closed Enums (Discouraged)
396
+
You can pass any [Record Key Type](https://atproto.com/specs/record-key): `@rec("tid")`, `@rec("nsid")`, `@rec("literal:self")`, etc.
397
+
398
+
(It's `@rec` not `@record` because "record" is reserved in TypeSpec.)
399
+
400
+
### Queries
293
401
294
-
**โ ๏ธ Closed enums are also discouraged.** Use `@closed @inline union` for fixed value sets:
402
+
In TypeSpec, use [`op`](https://typespec.io/docs/language-basics/operations/) for functions. Mark with `@query` for queries:
295
403
296
404
```typescript
297
-
@closed
298
-
@inline
299
-
union Status {
300
-
"active",
301
-
"inactive",
302
-
"pending",
405
+
import "@typelex/emitter";
406
+
407
+
namespace com.atproto.repo.getRecord {
408
+
@query
409
+
op main(
410
+
@required repo: atIdentifier,
411
+
@required collection: nsid,
412
+
@required rkey: recordKey,
413
+
cid?: cid
414
+
): {
415
+
@required uri: atUri;
416
+
cid?: cid;
417
+
};
303
418
}
304
419
```
305
420
306
-
**Maps to:**
421
+
Arguments become `parameters`, return type becomes `output`:
422
+
307
423
```json
308
-
{
309
-
"type": "string",
310
-
"enum": ["active", "inactive", "pending"]
424
+
// ...
425
+
"main": {
426
+
"type": "query",
427
+
"parameters": {
428
+
"type": "params",
429
+
"properties": {
430
+
"repo": { /* ... */ },
431
+
"collection": { /* ... */ },
432
+
// ...
433
+
},
434
+
"required": ["repo", "collection", "rkey"]
435
+
},
436
+
"output": {
437
+
"encoding": "application/json",
438
+
"schema": {
439
+
"type": "object",
440
+
"properties": {
441
+
"uri": { /* ... */ },
442
+
"cid": { /* ... */ }
443
+
},
444
+
"required": ["uri"]
445
+
}
446
+
}
311
447
}
448
+
// ...
312
449
```
313
450
314
-
Integer enums work the same way:
451
+
`encoding` defaults to `"application/json"`. Override with `@encoding("foo/bar")` on the `op`.
452
+
453
+
Declare errors with `@errors`:
315
454
316
455
```typescript
317
-
@closed
318
-
@inline
319
-
union Fibonacci {
320
-
1, 2, 3, 5, 8,
456
+
import "@typelex/emitter";
457
+
458
+
namespace com.atproto.repo.getRecord {
459
+
@query
460
+
@errors(FooError, BarError)
461
+
op main(/* ... */): { /* ... */ };
462
+
463
+
model FooError {}
464
+
model BarError {}
321
465
}
322
466
```
323
467
324
-
## Arrays
468
+
You can extract the `{ /* ... */ }` output type to a separate `@inline` model if you prefer.
469
+
470
+
### Procedures
325
471
326
-
Use `[]` suffix:
472
+
Use `@procedure` for procedures. The first argument must be called `input`:
327
473
328
474
```typescript
329
-
model Main {
330
-
/** Array of strings */
331
-
stringArray?: string[];
475
+
import "@typelex/emitter";
332
476
333
-
/** Array with size constraints */
334
-
@minItems(1)
335
-
@maxItems(10)
336
-
limitedArray?: integer[];
477
+
namespace com.example.createRecord {
478
+
@procedure
479
+
op main(input: {
480
+
@required text: string;
481
+
}): {
482
+
@required uri: atUri;
483
+
@required cid: cid;
484
+
};
485
+
}
486
+
```
337
487
338
-
/** Array of references */
339
-
items?: Item[];
488
+
Output:
340
489
341
-
/** Array of union types */
342
-
mixed?: (TypeA | TypeB | unknown)[];
490
+
```json
491
+
// ...
492
+
"main": {
493
+
"type": "procedure",
494
+
"input": {
495
+
"encoding": "application/json",
496
+
"schema": {
497
+
"type": "object",
498
+
"properties": { "text": { "type": "string" } },
499
+
"required": ["text"]
500
+
}
501
+
},
502
+
"output": {
503
+
"encoding": "application/json",
504
+
"schema": {
505
+
"type": "object",
506
+
"properties": {
507
+
"uri": { /* ... */ },
508
+
"cid": { /* ... */ }
509
+
},
510
+
"required": ["uri", "cid"]
511
+
}
512
+
}
343
513
}
514
+
// ...
344
515
```
345
516
346
-
**Maps to:** `{"type": "array", "items": {...}}`
517
+
Procedures can also receive parameters (rarely used): `op main(input: {}, parameters: {})`.
518
+
519
+
Use `: void` for no output, or `: never` with `@encoding()` on the `op` for output with encoding but no schema.
347
520
348
-
**Note:** `@minItems`/`@maxItems` in TypeSpec map to `minLength`/`maxLength` in JSON.
521
+
### Subscriptions
349
522
350
-
## Blobs
523
+
Use `@subscription` for subscriptions:
351
524
352
525
```typescript
353
-
model Main {
354
-
/** Basic blob */
355
-
file?: Blob;
526
+
import "@typelex/emitter";
356
527
357
-
/** Image up to 5MB */
358
-
image?: Blob<#["image/*"], 5000000>;
528
+
namespace com.atproto.sync.subscribeRepos {
529
+
@subscription
530
+
@errors(FutureCursor, ConsumerTooSlow)
531
+
op main(cursor?: integer): Commit | Sync | unknown;
359
532
360
-
/** Specific types up to 2MB */
361
-
photo?: Blob<#["image/png", "image/jpeg"], 2000000>;
533
+
model Commit { /* ... */ }
534
+
model Sync { /* ... */ }
535
+
model FutureCursor {}
536
+
model ConsumerTooSlow {}
362
537
}
363
538
```
364
539
365
-
**Maps to:**
540
+
Output:
541
+
366
542
```json
367
-
{
368
-
"file": {"type": "blob"},
369
-
"image": {
370
-
"type": "blob",
371
-
"accept": ["image/*"],
372
-
"maxSize": 5000000
373
-
}
543
+
// ...
544
+
"main": {
545
+
"type": "subscription",
546
+
"parameters": {
547
+
"type": "params",
548
+
"properties": { "cursor": { /* ... */ } }
549
+
},
550
+
"message": {
551
+
"schema": {
552
+
"type": "union",
553
+
"refs": ["#commit", "#sync"]
554
+
}
555
+
},
556
+
"errors": [{ "name": "FutureCursor" }, { "name": "ConsumerTooSlow" }]
374
557
}
558
+
// ...
375
559
```
376
560
377
-
## References
561
+
### Tokens
378
562
379
-
### Local References
563
+
Use `@token` for empty token models:
380
564
381
-
Same namespace, uses `#`:
565
+
```typescript
566
+
namespace com.example.moderation.defs {
567
+
@token
568
+
model ReasonSpam {}
382
569
383
-
```typescript
384
-
model Main {
385
-
metadata?: Metadata;
570
+
@token
571
+
model ReasonViolation {}
572
+
573
+
model Report {
574
+
@required reason: (ReasonSpam | ReasonViolation | unknown);
575
+
}
386
576
}
577
+
```
387
578
388
-
model Metadata {
389
-
@required key: string;
579
+
Output:
580
+
581
+
```json
582
+
// ...
583
+
"reasonSpam": { "type": "token" },
584
+
"reasonViolation": { "type": "token" },
585
+
"report": {
586
+
"type": "object",
587
+
"properties": {
588
+
"reason": {
589
+
"type": "union",
590
+
"refs": ["#reasonSpam", "#reasonViolation"]
591
+
}
592
+
},
593
+
"required": ["reason"]
390
594
}
595
+
// ...
391
596
```
392
597
393
-
**Maps to:** `{"type": "ref", "ref": "#metadata"}`
598
+
## Data Types
599
+
600
+
All [Lexicon data types](https://atproto.com/specs/lexicon#overview-of-types) are supported.
601
+
602
+
### Primitive Types
603
+
604
+
| TypeSpec | Lexicon JSON |
605
+
|----------|--------------|
606
+
| `boolean` | `{"type": "boolean"}` |
607
+
| `integer` | `{"type": "integer"}` |
608
+
| `string` | `{"type": "string"}` |
609
+
| `bytes` | `{"type": "bytes"}` |
610
+
| `cidLink` | `{"type": "cid-link"}` |
611
+
| `unknown` | `{"type": "unknown"}` |
612
+
613
+
### Format Types
614
+
615
+
Specialized string formats:
616
+
617
+
| TypeSpec | Lexicon Format |
618
+
|----------|----------------|
619
+
| `atIdentifier` | `at-identifier` - Handle or DID |
620
+
| `atUri` | `at-uri` - AT Protocol URI |
621
+
| `cid` | `cid` - Content ID |
622
+
| `datetime` | `datetime` - ISO 8601 datetime |
623
+
| `did` | `did` - DID identifier |
624
+
| `handle` | `handle` - Handle identifier |
625
+
| `nsid` | `nsid` - Namespaced ID |
626
+
| `tid` | `tid` - Timestamp ID |
627
+
| `recordKey` | `record-key` - Record key |
628
+
| `uri` | `uri` - Generic URI |
629
+
| `language` | `language` - Language tag |
394
630
395
-
### External References
631
+
### Arrays
396
632
397
-
Different namespace to specific def:
633
+
Use `[]` suffix:
398
634
399
635
```typescript
400
-
model Main {
401
-
externalRef?: com.example.defs.Metadata;
402
-
}
403
-
```
636
+
import "@typelex/emitter";
404
637
405
-
**Maps to:** `{"type": "ref", "ref": "com.example.defs#metadata"}`
638
+
namespace com.example.arrays {
639
+
model Main {
640
+
stringArray?: string[];
406
641
407
-
Different namespace to main def (no fragment):
642
+
@minItems(1)
643
+
@maxItems(10)
644
+
limitedArray?: integer[];
408
645
409
-
```typescript
410
-
model Main {
411
-
mainRef?: com.example.post.Main;
646
+
items?: Item[];
647
+
mixed?: (TypeA | TypeB | unknown)[];
648
+
}
649
+
// ...
412
650
}
413
651
```
414
652
415
-
**Maps to:** `{"type": "ref", "ref": "com.example.post"}`
653
+
Output: `{ "type": "array", "items": {...} }`.
416
654
417
-
## Tokens
655
+
Note: `@minItems`/`@maxItems` map to `minLength`/`maxLength` in JSON.
418
656
419
-
Empty models marked with `@token`:
657
+
### Blobs
420
658
421
659
```typescript
422
-
/** Indicates spam content */
423
-
@token
424
-
model ReasonSpam {}
660
+
import "@typelex/emitter";
425
661
426
-
/** Indicates policy violation */
427
-
@token
428
-
model ReasonViolation {}
429
-
430
-
model Report {
431
-
@required reason: (ReasonSpam | ReasonViolation | unknown);
662
+
namespace com.example.blobs {
663
+
model Main {
664
+
file?: Blob;
665
+
image?: Blob<#["image/*"], 5000000>;
666
+
photo?: Blob<#["image/png", "image/jpeg"], 2000000>;
667
+
}
432
668
}
433
669
```
434
670
435
-
**Maps to:**
671
+
Output:
672
+
436
673
```json
437
-
{
438
-
"report": {
439
-
"properties": {
440
-
"reason": {
441
-
"type": "union",
442
-
"refs": ["#reasonSpam", "#reasonViolation"]
443
-
}
444
-
}
445
-
},
446
-
"reasonSpam": {
447
-
"type": "token",
448
-
"description": "Indicates spam content"
449
-
}
674
+
// ...
675
+
"image": {
676
+
"type": "blob",
677
+
"accept": ["image/*"],
678
+
"maxSize": 5000000
450
679
}
680
+
// ...
451
681
```
452
682
453
-
## Operation Details
683
+
## Required and Optional Fields
454
684
455
-
### Query Parameters
685
+
In Lexicon, fields are optional by default. Use `?:`:
456
686
457
687
```typescript
458
-
@query
459
-
op main(
460
-
@required search: string,
461
-
limit?: integer = 50,
462
-
tags?: string[]
463
-
): { ... };
688
+
import "@typelex/emitter";
689
+
690
+
namespace tools.ozone.moderation.defs {
691
+
model SubjectStatusView {
692
+
subjectRepoHandle?: string;
693
+
}
694
+
}
464
695
```
465
696
466
-
Parameters can be inline with decorators before each.
697
+
**Think thrice before adding required fields**โyou can't make them optional later.
467
698
468
-
### Procedure with Input and Parameters
699
+
This is why `@required` is explicit:
469
700
470
701
```typescript
471
-
@procedure
472
-
op main(
473
-
input: {
474
-
@required data: string;
475
-
},
476
-
parameters: {
477
-
@required repo: atIdentifier;
478
-
validate?: boolean = true;
702
+
import "@typelex/emitter";
703
+
704
+
namespace tools.ozone.moderation.defs {
705
+
model SubjectStatusView {
706
+
subjectRepoHandle?: string;
707
+
@required createdAt: datetime;
479
708
}
480
-
): { ... };
709
+
}
481
710
```
482
711
483
-
Use `input:` for body, `parameters:` for query params.
712
+
Output:
484
713
485
-
### No Output
486
-
487
-
```typescript
488
-
@procedure
489
-
op main(input: {
490
-
@required uri: atUri;
491
-
}): void;
714
+
```json
715
+
// ...
716
+
"required": ["createdAt"]
717
+
// ...
492
718
```
493
719
494
-
Use `: void` for procedures with no output.
720
+
## Unions
721
+
722
+
### Open Unions (Recommended)
495
723
496
-
### Output Without Schema
724
+
Unions default to being *open*โallowing you to add more options later. Write `| unknown`:
497
725
498
726
```typescript
499
-
@query
500
-
@encoding("application/json")
501
-
op main(id?: string): never;
727
+
import "@typelex/emitter";
728
+
729
+
namespace app.bsky.feed.post {
730
+
model Main {
731
+
embed?: Images | Video | unknown;
732
+
}
733
+
734
+
model Images { /* ... */ }
735
+
model Video { /* ... */ }
736
+
}
502
737
```
503
738
504
-
Use `: never` with `@encoding()` for output with encoding but no schema.
739
+
Output:
505
740
506
-
### Errors
741
+
```json
742
+
// ...
743
+
"embed": {
744
+
"type": "union",
745
+
"refs": ["#images", "#video"]
746
+
}
747
+
// ...
748
+
```
749
+
750
+
You can also use the `union` syntax to give it a name:
507
751
508
752
```typescript
509
-
/** The provided text is invalid */
510
-
model InvalidText {}
753
+
import "@typelex/emitter";
754
+
755
+
namespace app.bsky.feed.post {
756
+
model Main {
757
+
embed?: EmbedType;
758
+
}
511
759
512
-
/** User not found */
513
-
model NotFound {}
760
+
@inline union EmbedType { Images, Video, unknown }
514
761
515
-
@procedure
516
-
@errors(InvalidText, NotFound)
517
-
op main(...): ...;
762
+
model Images { /* ... */ }
763
+
model Video { /* ... */ }
764
+
}
518
765
```
519
766
520
-
Empty models with descriptions become error definitions.
767
+
The `@inline` prevents it from becoming a separate def in the output.
521
768
522
-
## Constraints
769
+
### Known Values (Open Enums)
523
770
524
-
### String Constraints
771
+
Suggest common values but allow others with `| string`:
525
772
526
773
```typescript
527
-
model Main {
528
-
/** Byte length constraints */
529
-
@minLength(1)
530
-
@maxLength(100)
531
-
text?: string;
774
+
import "@typelex/emitter";
532
775
533
-
/** Grapheme cluster length constraints */
534
-
@minGraphemes(1)
535
-
@maxGraphemes(50)
536
-
displayName?: string;
776
+
namespace com.example {
777
+
model Main {
778
+
lang?: "en" | "es" | "fr" | string;
779
+
}
537
780
}
538
781
```
539
782
540
-
**Maps to:** `minLength`/`maxLength`, `minGraphemes`/`maxGraphemes`
783
+
The `union` syntax works here too:
784
+
785
+
```typescript
786
+
import "@typelex/emitter";
541
787
542
-
### Integer Constraints
788
+
namespace com.example {
789
+
model Main {
790
+
lang?: Languages;
791
+
}
543
792
544
-
```typescript
545
-
model Main {
546
-
@minValue(1)
547
-
@maxValue(100)
548
-
score?: integer;
793
+
@inline union Languages { "en", "es", "fr", string }
549
794
}
550
795
```
551
796
552
-
**Maps to:** `minimum`/`maximum`
797
+
You can remove `@inline` to make it a reusable `def` accessible from other Lexicons.
798
+
799
+
### Closed Unions and Enums (Discouraged)
800
+
801
+
**Heavily discouraged** in Lexicon.
553
802
554
-
### Bytes Constraints
803
+
Marking a `union` as `@closed` lets you remove `unknown` from the list of options:
555
804
556
805
```typescript
557
-
model Main {
558
-
@minBytes(1)
559
-
@maxBytes(1024)
560
-
data?: bytes;
806
+
import "@typelex/emitter";
807
+
808
+
namespace com.atproto.repo.applyWrites {
809
+
model Main {
810
+
@required writes: WriteAction[];
811
+
}
812
+
813
+
@closed // Discouraged!
814
+
@inline
815
+
union WriteAction { Create, Update, Delete }
816
+
817
+
model Create { /* ... */ }
818
+
model Update { /* ... */ }
819
+
model Delete { /* ... */ }
561
820
}
562
821
```
563
822
564
-
**Maps to:** `minLength`/`maxLength`
823
+
Output:
565
824
566
-
**Note:** Use `@minBytes`/`@maxBytes` in TypeSpec, but they map to `minLength`/`maxLength` in JSON.
825
+
```json
826
+
// ...
827
+
"writes": {
828
+
"type": "array",
829
+
"items": {
830
+
"type": "union",
831
+
"refs": ["#create", "#update", "#delete"],
832
+
"closed": true
833
+
}
834
+
}
835
+
// ...
836
+
```
567
837
568
-
### Array Constraints
838
+
With strings or numbers, this becomes a closed `enum`:
569
839
570
840
```typescript
571
-
model Main {
572
-
@minItems(1)
573
-
@maxItems(10)
574
-
items?: string[];
841
+
import "@typelex/emitter";
842
+
843
+
namespace com.atproto.repo.applyWrites {
844
+
model Main {
845
+
@required action: WriteAction;
846
+
}
847
+
848
+
@closed // Discouraged!
849
+
@inline
850
+
union WriteAction { "create", "update", "delete" }
575
851
}
576
852
```
577
853
578
-
**Maps to:** `minLength`/`maxLength`
854
+
Output:
579
855
580
-
**Note:** Use `@minItems`/`@maxItems` in TypeSpec, but they map to `minLength`/`maxLength` in JSON.
856
+
```json
857
+
// ...
858
+
"type": "string",
859
+
"enum": ["create", "update", "delete"]
860
+
// ...
861
+
```
581
862
582
-
## Default and Constant Values
863
+
Avoid closed unions/enums when possible.
583
864
584
-
### Defaults
865
+
## Constraints
866
+
867
+
### Strings
585
868
586
869
```typescript
587
-
model Main {
588
-
version?: integer = 1;
589
-
lang?: string = "en";
870
+
import "@typelex/emitter";
871
+
872
+
namespace com.example {
873
+
model Main {
874
+
@minLength(1)
875
+
@maxLength(100)
876
+
text?: string;
877
+
878
+
@minGraphemes(1)
879
+
@maxGraphemes(50)
880
+
displayName?: string;
881
+
}
590
882
}
591
883
```
592
884
593
-
**Maps to:** `{"default": 1}`, `{"default": "en"}`
885
+
Maps to: `minLength`/`maxLength`, `minGraphemes`/`maxGraphemes`
594
886
595
-
### Constants
887
+
### Integers
596
888
597
-
Use `@readOnly` with default value:
889
+
```typescript
890
+
import "@typelex/emitter";
598
891
599
-
```typescript
600
-
model Main {
601
-
@readOnly status?: string = "active";
892
+
namespace com.example {
893
+
model Main {
894
+
@minValue(1)
895
+
@maxValue(100)
896
+
score?: integer;
897
+
}
602
898
}
603
899
```
604
900
605
-
**Maps to:** `{"const": "active"}`
901
+
Maps to: `minimum`/`maximum`
606
902
607
-
## Nullable Fields
903
+
### Bytes
608
904
609
-
Use `| null` for nullable fields:
905
+
```typescript
906
+
import "@typelex/emitter";
610
907
611
-
```typescript
612
-
model Main {
613
-
@required createdAt: datetime;
614
-
updatedAt?: datetime | null; // can be omitted or null
615
-
deletedAt?: datetime; // can only be omitted
908
+
namespace com.example {
909
+
model Main {
910
+
@minBytes(1)
911
+
@maxBytes(1024)
912
+
data?: bytes;
913
+
}
616
914
}
617
915
```
618
916
619
-
**Maps to:**
620
-
```json
621
-
{
622
-
"required": ["createdAt"],
623
-
"nullable": ["updatedAt"],
624
-
"properties": { ... }
917
+
Maps to: `minLength`/`maxLength`
918
+
919
+
### Arrays
920
+
921
+
```typescript
922
+
import "@typelex/emitter";
923
+
924
+
namespace com.example {
925
+
model Main {
926
+
@minItems(1)
927
+
@maxItems(10)
928
+
items?: string[];
929
+
}
625
930
}
626
931
```
627
932
628
-
## Common Patterns
933
+
Maps to: `minLength`/`maxLength`
629
934
630
-
### Discriminated Unions
935
+
## Defaults and Constants
631
936
632
-
Use `@readOnly` with const for discriminator:
937
+
### Defaults
633
938
634
939
```typescript
635
-
model Create {
636
-
@readOnly @required type: string = "create";
637
-
@required data: string;
638
-
}
940
+
import "@typelex/emitter";
639
941
640
-
model Update {
641
-
@readOnly @required type: string = "update";
642
-
@required id: string;
942
+
namespace com.example {
943
+
model Main {
944
+
version?: integer = 1;
945
+
lang?: string = "en";
946
+
}
643
947
}
644
948
```
645
949
646
-
### Nested Unions
950
+
Maps to: `{"default": 1}`, `{"default": "en"}`
951
+
952
+
### Constants
953
+
954
+
Use `@readOnly` with a default:
647
955
648
956
```typescript
649
-
model Container {
650
-
@required id: string;
651
-
@required payload: (PayloadA | PayloadB | unknown);
957
+
import "@typelex/emitter";
958
+
959
+
namespace com.example {
960
+
model Main {
961
+
@readOnly status?: string = "active";
962
+
}
652
963
}
653
964
```
654
965
655
-
Unions can be nested in objects and arrays.
966
+
Maps to: `{"const": "active"}`
656
967
657
-
## Naming Conventions
968
+
## Nullable Fields
658
969
659
-
Model names convert from PascalCase to camelCase in defs:
970
+
Use `| null` for nullable fields:
660
971
661
972
```typescript
662
-
model StatusEnum { ... } // becomes "statusEnum"
663
-
model UserMetadata { ... } // becomes "userMetadata"
664
-
model Main { ... } // becomes "main"
973
+
import "@typelex/emitter";
974
+
975
+
namespace com.example {
976
+
model Main {
977
+
@required createdAt: datetime;
978
+
updatedAt?: datetime | null; // can be omitted or null
979
+
deletedAt?: datetime; // can only be omitted
980
+
}
981
+
}
665
982
```
666
983
667
-
## Decorator Style
984
+
Output:
668
985
669
-
- Single `@required` goes on same line: `@required text: string`
670
-
- Multiple decorators go on separate lines with blank line after:
671
-
```typescript
672
-
@minLength(1)
673
-
@maxLength(100)
674
-
text?: string;
675
-
```
986
+
```json
987
+
// ...
988
+
"required": ["createdAt"],
989
+
"nullable": ["updatedAt"]
990
+
// ...
991
+
```
+6
-4
README.md
+6
-4
README.md
···
2
2
3
3
An experimental [TypeSpec](https://typespec.io/) syntax for [Lexicon](https://atproto.com/specs/lexicon).
4
4
5
-
See https://typelex.pages.dev/
6
-
7
-
**This is a hobby project but maybe somebody will find it helpful.**
5
+
See https://typelex.org/
8
6
9
7
Design is not final and might change. Ideas welcome.
10
8
···
14
12
15
13
## Documentation
16
14
17
-
No "proper" docs yet. See [DOCS.md](./DOCS.md) for now.
15
+
See [DOCS.md](./DOCS.md).
16
+
17
+
## Alternatives
18
+
19
+
* [MFL](https://mlf.lol/)
18
20
19
21
## License
20
22
+2
-1
package.json
+2
-1
package.json
···
10
10
"example": "pnpm --filter @typelex/example build",
11
11
"playground": "pnpm --filter @typelex/playground dev",
12
12
"validate": "pnpm build && pnpm run validate-lexicons && pnpm test",
13
-
"validate-lexicons": "node scripts/validate-lexicons.js"
13
+
"validate-lexicons": "node scripts/validate-lexicons.js",
14
+
"cli": "pnpm --filter @typelex/cli"
14
15
},
15
16
"repository": {
16
17
"type": "git",
+66
packages/cli/README.md
+66
packages/cli/README.md
···
1
+
# @typelex/cli
2
+
3
+
Experimental CLI for typelex
4
+
5
+
## Installation
6
+
7
+
```bash
8
+
pnpm add -D @typelex/cli @typelex/emitter
9
+
```
10
+
11
+
## Usage
12
+
13
+
```bash
14
+
typelex compile xyz.statusphere.*
15
+
```
16
+
17
+
This command:
18
+
1. Scans `lexicons/` for all external lexicons (not matching `xyz.statusphere`)
19
+
2. Generates `typelex/externals.tsp` with `@external` stubs
20
+
3. Compiles `typelex/main.tsp` to `lexicons/` (or custom output via `--out`)
21
+
22
+
Fixed paths:
23
+
- Entry point: `typelex/main.tsp`
24
+
- Externals: `typelex/externals.tsp`
25
+
26
+
## Example
27
+
28
+
```typescript
29
+
// typelex/main.tsp
30
+
import "@typelex/emitter";
31
+
import "./externals.tsp";
32
+
33
+
namespace xyz.statusphere.defs {
34
+
model StatusView {
35
+
@required uri: atUri;
36
+
@required status: string;
37
+
@required profile: app.bsky.actor.defs.ProfileView;
38
+
}
39
+
}
40
+
```
41
+
42
+
```bash
43
+
typelex compile 'xyz.statusphere.*'
44
+
```
45
+
46
+
The CLI scans `lexicons/` for external types and auto-generates `typelex/externals.tsp` with stubs
47
+
48
+
### Integration
49
+
50
+
```json
51
+
{
52
+
"scripts": {
53
+
"build:lexicons": "typelex compile 'xyz.statusphere.*'",
54
+
"build:codegen": "lex gen-server --yes ./src lexicons/xyz/statusphere/*.json"
55
+
}
56
+
}
57
+
```
58
+
59
+
## Options
60
+
61
+
- `--out <directory>` - Output directory for generated Lexicon files (default: `./lexicons`)
62
+
- `--watch` - Watch mode for continuous compilation
63
+
64
+
## License
65
+
66
+
MIT
+40
packages/cli/package.json
+40
packages/cli/package.json
···
1
+
{
2
+
"name": "@typelex/cli",
3
+
"version": "0.2.0",
4
+
"description": "CLI for typelex - TypeSpec-based IDL for ATProto Lexicons",
5
+
"main": "dist/index.js",
6
+
"type": "module",
7
+
"bin": {
8
+
"typelex": "dist/cli.js"
9
+
},
10
+
"files": [
11
+
"dist",
12
+
"src"
13
+
],
14
+
"scripts": {
15
+
"build": "tsc",
16
+
"clean": "rm -rf dist",
17
+
"watch": "tsc --watch",
18
+
"prepublishOnly": "npm run build"
19
+
},
20
+
"keywords": [
21
+
"typespec",
22
+
"atproto",
23
+
"lexicon",
24
+
"cli"
25
+
],
26
+
"author": "Dan Abramov <dan.abramov@gmail.com>",
27
+
"license": "MIT",
28
+
"dependencies": {
29
+
"@typespec/compiler": "^1.4.0",
30
+
"yargs": "^18.0.0"
31
+
},
32
+
"devDependencies": {
33
+
"@types/node": "^20.0.0",
34
+
"@types/yargs": "^17.0.33",
35
+
"typescript": "^5.0.0"
36
+
},
37
+
"peerDependencies": {
38
+
"@typelex/emitter": "^0.2.0"
39
+
}
40
+
}
+64
packages/cli/src/cli.ts
+64
packages/cli/src/cli.ts
···
1
+
#!/usr/bin/env node
2
+
import yargs from "yargs";
3
+
import { hideBin } from "yargs/helpers";
4
+
import { compileCommand } from "./commands/compile.js";
5
+
6
+
async function main() {
7
+
await yargs(hideBin(process.argv))
8
+
.scriptName("typelex")
9
+
.usage("$0 compile <namespace>")
10
+
.command(
11
+
"compile <namespace>",
12
+
"Compile TypeSpec files to Lexicon JSON",
13
+
(yargs) => {
14
+
return yargs
15
+
.positional("namespace", {
16
+
describe: "Primary namespace pattern (e.g., app.bsky.*)",
17
+
type: "string",
18
+
demandOption: true,
19
+
})
20
+
.option("out", {
21
+
describe: "Output directory for generated Lexicon files (relative to cwd)",
22
+
type: "string",
23
+
default: "./lexicons",
24
+
});
25
+
},
26
+
async (argv) => {
27
+
const options: Record<string, unknown> = {};
28
+
if (argv.watch) {
29
+
options.watch = true;
30
+
}
31
+
if (argv.out) {
32
+
options.out = argv.out;
33
+
}
34
+
await compileCommand(argv.namespace, options);
35
+
}
36
+
)
37
+
.option("watch", {
38
+
describe: "Watch mode",
39
+
type: "boolean",
40
+
default: false,
41
+
})
42
+
.demandCommand(1, "You must specify a command")
43
+
.help()
44
+
.version()
45
+
.fail((msg, err) => {
46
+
if (err) {
47
+
console.error(err);
48
+
} else {
49
+
console.error(msg);
50
+
}
51
+
process.exit(1);
52
+
}).argv;
53
+
}
54
+
55
+
process.on("unhandledRejection", (error: unknown) => {
56
+
console.error("Unhandled promise rejection!");
57
+
console.error(error);
58
+
process.exit(1);
59
+
});
60
+
61
+
main().catch((error) => {
62
+
console.error(error);
63
+
process.exit(1);
64
+
});
+68
packages/cli/src/commands/compile.ts
+68
packages/cli/src/commands/compile.ts
···
1
+
import { resolve } from "path";
2
+
import { spawn } from "child_process";
3
+
import { generateExternalsFile } from "../utils/externals-generator.js";
4
+
import { ensureMainImports } from "../utils/ensure-imports.js";
5
+
6
+
/**
7
+
* Compile TypeSpec files to Lexicon JSON
8
+
*
9
+
* @param namespace - Primary namespace pattern (e.g., "app.bsky.*")
10
+
* @param options - Additional compiler options
11
+
*/
12
+
export async function compileCommand(
13
+
namespace: string,
14
+
options: Record<string, unknown> = {}
15
+
): Promise<void> {
16
+
const cwd = process.cwd();
17
+
const outDir = (options.out as string) || "./lexicons";
18
+
19
+
// Validate that output directory ends with 'lexicons'
20
+
const normalizedPath = outDir.replace(/\\/g, '/').replace(/\/+$/, '');
21
+
if (!normalizedPath.endsWith('/lexicons') && normalizedPath !== 'lexicons' && normalizedPath !== './lexicons') {
22
+
console.error(`Error: Output directory must end with 'lexicons'`);
23
+
console.error(`Got: ${outDir}`);
24
+
console.error(`Valid examples: ./lexicons, ../../lexicons, /path/to/lexicons`);
25
+
process.exit(1);
26
+
}
27
+
28
+
// Generate externals first (scans the output directory for external lexicons)
29
+
await generateExternalsFile(namespace, cwd, outDir);
30
+
31
+
// Ensure required imports are present in main.tsp
32
+
await ensureMainImports(cwd);
33
+
34
+
// Compile TypeSpec using the TypeSpec CLI
35
+
const entrypoint = resolve(cwd, "typelex/main.tsp");
36
+
const args = [
37
+
"compile",
38
+
entrypoint,
39
+
"--emit",
40
+
"@typelex/emitter",
41
+
"--option",
42
+
`@typelex/emitter.emitter-output-dir={project-root}/${outDir}`,
43
+
];
44
+
45
+
if (options.watch) {
46
+
args.push("--watch");
47
+
}
48
+
49
+
return new Promise((resolve, reject) => {
50
+
const tsp = spawn("tsp", args, {
51
+
cwd,
52
+
stdio: "inherit",
53
+
});
54
+
55
+
tsp.on("close", (code) => {
56
+
if (code === 0) {
57
+
resolve();
58
+
} else {
59
+
process.exit(code ?? 1);
60
+
}
61
+
});
62
+
63
+
tsp.on("error", (err) => {
64
+
console.error("Failed to start TypeSpec compiler:", err);
65
+
reject(err);
66
+
});
67
+
});
68
+
}
+1
packages/cli/src/index.ts
+1
packages/cli/src/index.ts
···
1
+
export { compileCommand } from "./commands/compile.js";
+38
packages/cli/src/utils/ensure-imports.ts
+38
packages/cli/src/utils/ensure-imports.ts
···
1
+
import { readFile } from "fs/promises";
2
+
import { resolve } from "path";
3
+
4
+
const REQUIRED_FIRST_LINE = 'import "@typelex/emitter";';
5
+
const REQUIRED_SECOND_LINE = 'import "./externals.tsp";';
6
+
7
+
/**
8
+
* Validates that main.tsp starts with the required imports.
9
+
* Fails the build if the first two lines are not exactly as expected.
10
+
*
11
+
* @param cwd - Current working directory
12
+
*/
13
+
export async function ensureMainImports(cwd: string): Promise<void> {
14
+
const mainPath = resolve(cwd, "typelex/main.tsp");
15
+
16
+
try {
17
+
const content = await readFile(mainPath, "utf-8");
18
+
const lines = content.split("\n");
19
+
20
+
if (lines[0]?.trim() !== REQUIRED_FIRST_LINE) {
21
+
console.error(`Error: main.tsp must start with: ${REQUIRED_FIRST_LINE}`);
22
+
console.error(`Found: ${lines[0] || "(empty line)"}`);
23
+
process.exit(1);
24
+
}
25
+
26
+
if (lines[1]?.trim() !== REQUIRED_SECOND_LINE) {
27
+
console.error(`Error: Line 2 of main.tsp must be: ${REQUIRED_SECOND_LINE}`);
28
+
console.error(`Found: ${lines[1] || "(empty line)"}`);
29
+
process.exit(1);
30
+
}
31
+
} catch (err) {
32
+
if ((err as NodeJS.ErrnoException).code === "ENOENT") {
33
+
console.error("Error: typelex/main.tsp not found");
34
+
process.exit(1);
35
+
}
36
+
throw err;
37
+
}
38
+
}
+105
packages/cli/src/utils/externals-generator.ts
+105
packages/cli/src/utils/externals-generator.ts
···
1
+
import { resolve } from "path";
2
+
import { writeFile, mkdir } from "fs/promises";
3
+
import { findExternalLexicons, LexiconDoc, isTokenDef, isModelDef } from "./lexicon.js";
4
+
5
+
/**
6
+
* Convert camelCase to PascalCase
7
+
*/
8
+
function toPascalCase(str: string): string {
9
+
return str.charAt(0).toUpperCase() + str.slice(1);
10
+
}
11
+
12
+
/**
13
+
* Extract namespace prefix from pattern (e.g., "app.bsky.*" -> "app.bsky")
14
+
*/
15
+
function getNamespacePrefix(pattern: string): string {
16
+
if (!pattern.endsWith(".*")) {
17
+
throw new Error(`Namespace pattern must end with .*: ${pattern}`);
18
+
}
19
+
return pattern.slice(0, -2);
20
+
}
21
+
22
+
/**
23
+
* Generate TypeSpec external definitions from lexicon documents
24
+
*/
25
+
function generateExternalsCode(lexicons: Map<string, LexiconDoc>): string {
26
+
const lines: string[] = [];
27
+
28
+
lines.push('import "@typelex/emitter";');
29
+
lines.push("");
30
+
lines.push("// Generated by typelex");
31
+
lines.push("// This file is auto-generated. Do not edit manually.");
32
+
lines.push("");
33
+
34
+
// Sort namespaces for consistent output
35
+
const sortedNamespaces = Array.from(lexicons.entries()).sort(([a], [b]) =>
36
+
a.localeCompare(b)
37
+
);
38
+
39
+
for (const [nsid, lexicon] of sortedNamespaces) {
40
+
lines.push("@external");
41
+
// Escape reserved keywords in namespace (like 'record')
42
+
const escapedNsid = nsid.replace(/\b(record|union|enum|interface|namespace|model|op|import|using|extends|is|scalar|alias|if|else|return|void|never|unknown|any|true|false|null)\b/g, '`$1`');
43
+
lines.push(`namespace ${escapedNsid} {`);
44
+
45
+
// Sort definitions for consistent output
46
+
const sortedDefs = Object.entries(lexicon.defs).sort(([a], [b]) =>
47
+
a.localeCompare(b)
48
+
);
49
+
50
+
for (const [defName, def] of sortedDefs) {
51
+
if (!isModelDef(def)) {
52
+
continue;
53
+
}
54
+
55
+
const modelName = toPascalCase(defName);
56
+
const isToken = isTokenDef(def);
57
+
58
+
if (isToken) {
59
+
lines.push(` @token model ${modelName} { }`);
60
+
} else {
61
+
lines.push(` model ${modelName} { }`);
62
+
}
63
+
}
64
+
65
+
lines.push("}");
66
+
lines.push("");
67
+
}
68
+
69
+
return lines.join("\n");
70
+
}
71
+
72
+
/**
73
+
* Generate externals.tsp file for the given namespace pattern
74
+
*/
75
+
export async function generateExternalsFile(
76
+
namespacePattern: string,
77
+
cwd: string,
78
+
outDir: string = "./lexicons"
79
+
): Promise<void> {
80
+
try {
81
+
const prefix = getNamespacePrefix(namespacePattern);
82
+
const lexiconsDir = resolve(cwd, outDir);
83
+
const outputFile = resolve(cwd, "typelex/externals.tsp");
84
+
85
+
const externals = await findExternalLexicons(lexiconsDir, prefix);
86
+
87
+
if (externals.size === 0) {
88
+
// No externals, create empty file
89
+
await mkdir(resolve(cwd, "typelex"), { recursive: true });
90
+
await writeFile(
91
+
outputFile,
92
+
'import "@typelex/emitter";\n\n// Generated by typelex\n// No external lexicons found\n',
93
+
"utf-8"
94
+
);
95
+
return;
96
+
}
97
+
98
+
const code = generateExternalsCode(externals);
99
+
await mkdir(resolve(cwd, "typelex"), { recursive: true });
100
+
await writeFile(outputFile, code, "utf-8");
101
+
} catch (error) {
102
+
// Re-throw with better context
103
+
throw new Error(`Failed to generate externals: ${error instanceof Error ? error.message : String(error)}`);
104
+
}
105
+
}
+78
packages/cli/src/utils/lexicon.ts
+78
packages/cli/src/utils/lexicon.ts
···
1
+
import { readFile } from "fs/promises";
2
+
import { resolve } from "path";
3
+
import { globby } from "globby";
4
+
5
+
export interface LexiconDef {
6
+
type: string;
7
+
[key: string]: unknown;
8
+
}
9
+
10
+
export interface LexiconDoc {
11
+
lexicon: number;
12
+
id: string;
13
+
defs: Record<string, LexiconDef>;
14
+
}
15
+
16
+
/**
17
+
* Read and parse a lexicon JSON file
18
+
*/
19
+
export async function readLexicon(path: string): Promise<LexiconDoc> {
20
+
const content = await readFile(path, "utf-8");
21
+
return JSON.parse(content);
22
+
}
23
+
24
+
/**
25
+
* Find all lexicon files in a directory
26
+
*/
27
+
export async function findLexicons(dir: string): Promise<string[]> {
28
+
try {
29
+
const pattern = resolve(dir, "**/*.json");
30
+
return await globby(pattern);
31
+
} catch {
32
+
// If directory doesn't exist, return empty array
33
+
return [];
34
+
}
35
+
}
36
+
37
+
/**
38
+
* Extract external lexicons that don't match the given namespace
39
+
*/
40
+
export async function findExternalLexicons(
41
+
lexiconsDir: string,
42
+
primaryNamespace: string
43
+
): Promise<Map<string, LexiconDoc>> {
44
+
const files = await findLexicons(lexiconsDir);
45
+
const externals = new Map<string, LexiconDoc>();
46
+
47
+
for (const file of files) {
48
+
const lexicon = await readLexicon(file);
49
+
if (!lexicon.id.startsWith(primaryNamespace)) {
50
+
externals.set(lexicon.id, lexicon);
51
+
}
52
+
}
53
+
54
+
return externals;
55
+
}
56
+
57
+
/**
58
+
* Check if a definition is a token type
59
+
*/
60
+
export function isTokenDef(def: LexiconDef): boolean {
61
+
return def.type === "token";
62
+
}
63
+
64
+
/**
65
+
* Check if a definition should become a model in TypeSpec
66
+
*/
67
+
export function isModelDef(def: LexiconDef): boolean {
68
+
const type = def.type;
69
+
return (
70
+
type === "object" ||
71
+
type === "token" ||
72
+
type === "record" ||
73
+
type === "union" ||
74
+
type === "string" ||
75
+
type === "bytes" ||
76
+
type === "cid-link"
77
+
);
78
+
}
+20
packages/cli/tsconfig.json
+20
packages/cli/tsconfig.json
···
1
+
{
2
+
"compilerOptions": {
3
+
"target": "ES2022",
4
+
"module": "Node16",
5
+
"moduleResolution": "Node16",
6
+
"lib": ["ES2022"],
7
+
"outDir": "dist",
8
+
"rootDir": "src",
9
+
"declaration": true,
10
+
"declarationMap": true,
11
+
"sourceMap": true,
12
+
"strict": true,
13
+
"esModuleInterop": true,
14
+
"skipLibCheck": true,
15
+
"forceConsistentCasingInFileNames": true,
16
+
"resolveJsonModule": true
17
+
},
18
+
"include": ["src/**/*"],
19
+
"exclude": ["node_modules", "dist"]
20
+
}
+4
packages/cli/typelex/externals.tsp
+4
packages/cli/typelex/externals.tsp
+15
packages/emitter/lib/decorators.tsp
+15
packages/emitter/lib/decorators.tsp
···
1
1
import "../dist/tsp-index.js";
2
2
3
+
using TypeSpec.Reflection;
4
+
3
5
/**
4
6
* Specifies the maximum number of graphemes (user-perceived characters) allowed.
5
7
* Used alongside maxLength for proper Unicode text handling.
···
159
161
* ```
160
162
*/
161
163
extern dec errors(target: unknown, ...errors: unknown[]);
164
+
165
+
/**
166
+
* Marks a namespace as external, preventing it from emitting JSON output.
167
+
* This decorator can only be applied to namespaces.
168
+
* Useful for importing definitions from other lexicons without re-emitting them.
169
+
*
170
+
* @example
171
+
* ```typespec
172
+
* @external
173
+
* namespace com.atproto.repo.defs;
174
+
* ```
175
+
*/
176
+
extern dec external(target: Namespace);
+5
-3
packages/emitter/package.json
+5
-3
packages/emitter/package.json
···
1
1
{
2
2
"name": "@typelex/emitter",
3
-
"version": "0.1.0",
3
+
"version": "0.2.0",
4
4
"description": "TypeSpec emitter for ATProto Lexicon definitions",
5
5
"main": "dist/index.js",
6
6
"type": "module",
7
7
"files": [
8
8
"lib",
9
-
"src"
9
+
"src",
10
+
"dist"
10
11
],
11
12
"exports": {
12
13
".": {
···
26
27
"test:ci": "npm run build && vitest run",
27
28
"test:watch": "tsc-watch --onSuccess \"vitest run\"",
28
29
"clean": "rm -rf dist",
29
-
"watch": "tsc --watch"
30
+
"watch": "tsc --watch",
31
+
"prepublishOnly": "npm test"
30
32
},
31
33
"keywords": [
32
34
"typespec",
+23
packages/emitter/src/decorators.ts
+23
packages/emitter/src/decorators.ts
···
24
24
const inlineKey = Symbol("inline");
25
25
const maxBytesKey = Symbol("maxBytes");
26
26
const minBytesKey = Symbol("minBytes");
27
+
const externalKey = Symbol("external");
27
28
28
29
/**
29
30
* @maxBytes decorator for maximum length of bytes type
···
294
295
export function isReadOnly(program: Program, target: Type): boolean {
295
296
return program.stateSet(readOnlyKey).has(target);
296
297
}
298
+
299
+
/**
300
+
* @external decorator for marking a namespace as external
301
+
* External namespaces are skipped during emission and don't produce JSON files
302
+
*/
303
+
export function $external(context: DecoratorContext, target: Type) {
304
+
if (target.kind !== "Namespace") {
305
+
context.program.reportDiagnostic({
306
+
code: "external-not-on-namespace",
307
+
severity: "error",
308
+
message: "@external decorator can only be applied to namespaces",
309
+
target: target,
310
+
});
311
+
return;
312
+
}
313
+
314
+
context.program.stateSet(externalKey).add(target);
315
+
}
316
+
317
+
export function isExternal(program: Program, target: Type): boolean {
318
+
return program.stateSet(externalKey).has(target);
319
+
}
+164
-29
packages/emitter/src/emitter.ts
+164
-29
packages/emitter/src/emitter.ts
···
39
39
LexObjectProperty,
40
40
LexArrayItem,
41
41
LexXrpcParameterProperty,
42
-
LexInteger,
43
-
LexString,
44
42
LexRefUnion,
45
43
LexUserType,
46
44
LexRecord,
···
48
46
LexXrpcParameters,
49
47
LexBytes,
50
48
LexCidLink,
51
-
LexRef,
52
49
LexRefVariant,
50
+
LexToken,
53
51
} from "./types.js";
54
52
55
53
import {
···
69
67
isInline,
70
68
getMaxBytes,
71
69
getMinBytes,
70
+
isExternal,
72
71
} from "./decorators.js";
73
72
74
73
export interface EmitterOptions {
···
123
122
return;
124
123
}
125
124
125
+
// Skip external namespaces - they don't emit JSON files
126
+
if (isExternal(this.program, ns)) {
127
+
// Validate that all models in external namespaces are empty (stub-only)
128
+
for (const [_, model] of ns.models) {
129
+
if (model.properties && model.properties.size > 0) {
130
+
this.program.reportDiagnostic({
131
+
code: "external-model-not-empty",
132
+
severity: "error",
133
+
message: `Models in @external namespaces must be empty stubs. Model '${model.name}' in namespace '${fullName}' has properties.`,
134
+
target: model,
135
+
});
136
+
}
137
+
}
138
+
return;
139
+
}
140
+
126
141
// Check for TypeSpec enum syntax and throw error
127
142
if (ns.enums && ns.enums.size > 0) {
128
143
for (const [_, enumType] of ns.enums) {
···
166
181
const hasScalars = ns.scalars.size > 0;
167
182
const hasUnions = ns.unions?.size > 0;
168
183
const hasOperations = ns.operations?.size > 0;
169
-
const hasChildNamespaces = ns.namespaces.size > 0;
170
184
const hasContent = hasModels || hasScalars || hasUnions;
171
185
172
186
if (hasOperations) {
173
187
return "operation";
174
188
}
175
189
176
-
if (hasContent && hasChildNamespaces) {
177
-
return "defs";
178
-
}
179
-
180
-
if (hasContent && !hasChildNamespaces) {
190
+
if (hasContent) {
181
191
return "content";
182
192
}
183
193
···
267
277
};
268
278
}
269
279
270
-
private createMainDef(mainModel: Model): LexRecord | LexObject {
280
+
private createMainDef(mainModel: Model): LexRecord | LexObject | LexToken {
271
281
const modelDescription = getDoc(this.program, mainModel);
282
+
283
+
// Check if this is a token type
284
+
if (isToken(this.program, mainModel)) {
285
+
return {
286
+
type: "token",
287
+
description: modelDescription,
288
+
};
289
+
}
290
+
272
291
const recordKey = getRecordKey(this.program, mainModel);
273
292
const modelDef = this.modelToLexiconObject(mainModel, !!modelDescription);
274
293
···
367
386
return;
368
387
}
369
388
370
-
// Only string enums can be added as defs
389
+
// Only string enums (including token refs) can be added as defs
371
390
// Union refs (type: "union") must be inlined at usage sites
372
391
if (unionDef.type === "string" && (unionDef.knownValues || unionDef.enum)) {
373
392
const defName = name.charAt(0).toLowerCase() + name.slice(1);
···
378
397
code: "union-refs-not-allowed-as-def",
379
398
severity: "error",
380
399
message:
381
-
`Named unions of model references cannot be defined as standalone defs. ` +
382
-
`Use @inline to inline them at usage sites, or use string enums instead.`,
400
+
`Named unions of non-token model references cannot be defined as standalone defs. ` +
401
+
`Use @inline to inline them at usage sites, use @token models for known values, or use string literals.`,
383
402
target: union,
384
403
});
385
404
}
···
459
478
private unionToLexiconProperty(
460
479
unionType: Union,
461
480
prop?: ModelProperty,
481
+
isDefining?: boolean,
462
482
): LexObjectProperty | null {
463
483
const variants = this.parseUnionVariants(unionType);
464
484
···
501
521
(variants.stringLiterals.length > 0 &&
502
522
!variants.hasStringType &&
503
523
variants.unionRefs.length === 0 &&
524
+
variants.knownValueRefs.length === 0 &&
504
525
isClosed(this.program, unionType))
505
526
) {
506
527
const isClosedUnion = isClosed(this.program, unionType);
···
512
533
const minLength = getMinLength(this.program, unionType);
513
534
const maxGraphemes = getMaxGraphemes(this.program, unionType);
514
535
const minGraphemes = getMinGraphemes(this.program, unionType);
536
+
537
+
// Combine string literals and token refs for known values
538
+
const allKnownValues = [
539
+
...variants.stringLiterals,
540
+
...variants.knownValueRefs,
541
+
];
542
+
515
543
return {
516
544
type: "string",
517
-
[isClosedUnion ? "enum" : "knownValues"]: variants.stringLiterals,
545
+
[isClosedUnion ? "enum" : "knownValues"]: allKnownValues,
518
546
...(propDesc && { description: propDesc }),
519
547
...(defaultValue !== undefined &&
520
548
typeof defaultValue === "string" && { default: defaultValue }),
···
527
555
528
556
// Model reference union (including empty union with unknown)
529
557
if (variants.unionRefs.length > 0 || variants.hasUnknown) {
530
-
if (variants.stringLiterals.length > 0) {
558
+
if (
559
+
variants.stringLiterals.length > 0 ||
560
+
variants.knownValueRefs.length > 0
561
+
) {
531
562
this.program.reportDiagnostic({
532
563
code: "union-mixed-refs-literals",
533
564
severity: "error",
534
565
message:
535
-
`Union contains both model references and string literals. Lexicon unions must be either: ` +
536
-
`(1) model references only (type: "union"), ` +
537
-
`(2) string literals + string type (type: "string" with knownValues), or ` +
566
+
`Union contains both non-token model references and string literals/token refs. Lexicon unions must be either: ` +
567
+
`(1) non-token model references only (type: "union"), ` +
568
+
`(2) token refs + string literals + string type (type: "string" with knownValues), or ` +
538
569
`(3) integer literals + integer type (type: "integer" with knownValues). ` +
539
570
`Separate these into distinct fields or nested unions.`,
540
571
target: unionType,
···
607
638
const stringLiterals: string[] = [];
608
639
const numericLiterals: number[] = [];
609
640
const booleanLiterals: boolean[] = [];
641
+
const tokenModels: Model[] = [];
610
642
let hasStringType = false;
611
643
let hasUnknown = false;
612
644
613
645
for (const variant of unionType.variants.values()) {
614
646
switch (variant.type.kind) {
615
647
case "Model":
616
-
const ref = this.getModelReference(variant.type as Model);
617
-
if (ref) unionRefs.push(ref);
648
+
const model = variant.type as Model;
649
+
// Collect token models separately - they're treated differently based on hasStringType
650
+
if (isToken(this.program, model)) {
651
+
tokenModels.push(model);
652
+
} else {
653
+
const ref = this.getModelReference(model);
654
+
if (ref) unionRefs.push(ref);
655
+
}
618
656
break;
619
657
case "String":
620
658
stringLiterals.push((variant.type as StringLiteral).value);
···
639
677
}
640
678
}
641
679
680
+
// Validate: tokens must appear with | string
681
+
// Per Lexicon spec line 240: "unions can not reference token"
682
+
if (tokenModels.length > 0 && !hasStringType) {
683
+
this.program.reportDiagnostic({
684
+
code: "tokens-require-string",
685
+
severity: "error",
686
+
message:
687
+
"Tokens must be used with | string. Per Lexicon spec, tokens encode as string values and cannot appear in union refs.",
688
+
target: unionType,
689
+
});
690
+
}
691
+
692
+
// Token models become "known values" (always fully qualified refs)
693
+
const knownValueRefs = tokenModels
694
+
.map((m) => this.getModelReference(m, true))
695
+
.filter((ref): ref is string => ref !== null);
696
+
642
697
const isStringEnum =
643
-
stringLiterals.length > 0 && hasStringType && unionRefs.length === 0;
698
+
(stringLiterals.length > 0 || knownValueRefs.length > 0) &&
699
+
hasStringType &&
700
+
unionRefs.length === 0;
644
701
645
702
return {
646
703
unionRefs,
647
704
stringLiterals,
648
705
numericLiterals,
649
706
booleanLiterals,
707
+
knownValueRefs,
650
708
hasStringType,
651
709
hasUnknown,
652
710
isStringEnum,
···
705
763
const required: string[] = [];
706
764
707
765
for (const [paramName, param] of operation.parameters.properties) {
766
+
// Check for conflicting @required on optional property
767
+
if (param.optional && isRequired(this.program, param)) {
768
+
this.program.reportDiagnostic({
769
+
code: "required-on-optional",
770
+
message:
771
+
`Parameter "${paramName}" has conflicting markers: @required decorator with optional "?". ` +
772
+
`Either remove @required to make it optional (preferred), or remove the "?".`,
773
+
target: param,
774
+
severity: "error",
775
+
});
776
+
}
777
+
778
+
if (!param.optional) {
779
+
if (!isRequired(this.program, param)) {
780
+
this.program.reportDiagnostic({
781
+
code: "parameter-missing-required",
782
+
message:
783
+
`Required parameter "${paramName}" must be explicitly marked with @required decorator. ` +
784
+
`In atproto, required fields are discouraged and must be intentional. ` +
785
+
`Either add @required to the parameter or make it optional with "?".`,
786
+
target: param,
787
+
severity: "error",
788
+
});
789
+
}
790
+
required.push(paramName);
791
+
}
792
+
708
793
const paramDef = this.typeToLexiconDefinition(param.type, param);
709
794
if (paramDef && this.isXrpcParameterProperty(paramDef)) {
710
795
properties[paramName] = paramDef;
711
-
if (!param.optional) required.push(paramName);
712
796
}
713
797
}
714
798
···
844
928
const required: string[] = [];
845
929
846
930
for (const [propName, prop] of parametersModel.properties) {
931
+
// Check for conflicting @required on optional property
932
+
if (prop.optional && isRequired(this.program, prop)) {
933
+
this.program.reportDiagnostic({
934
+
code: "required-on-optional",
935
+
message:
936
+
`Parameter "${propName}" has conflicting markers: @required decorator with optional "?". ` +
937
+
`Either remove @required to make it optional (preferred), or remove the "?".`,
938
+
target: prop,
939
+
severity: "error",
940
+
});
941
+
}
942
+
943
+
if (!prop.optional) {
944
+
if (!isRequired(this.program, prop)) {
945
+
this.program.reportDiagnostic({
946
+
code: "parameter-missing-required",
947
+
message:
948
+
`Required parameter "${propName}" must be explicitly marked with @required decorator. ` +
949
+
`In atproto, required fields are discouraged and must be intentional. ` +
950
+
`Either add @required to the parameter or make it optional with "?".`,
951
+
target: prop,
952
+
severity: "error",
953
+
});
954
+
}
955
+
required.push(propName);
956
+
}
957
+
847
958
const propDef = this.typeToLexiconDefinition(prop.type, prop);
848
959
if (propDef && this.isXrpcParameterProperty(propDef)) {
849
960
properties[propName] = propDef;
850
-
if (!prop.optional) {
851
-
required.push(propName);
852
-
}
853
961
}
854
962
}
855
963
···
947
1055
const properties: Record<string, LexObjectProperty> = {};
948
1056
949
1057
for (const [name, prop] of model.properties) {
1058
+
// Check for conflicting @required on optional property
1059
+
if (prop.optional && isRequired(this.program, prop)) {
1060
+
this.program.reportDiagnostic({
1061
+
code: "required-on-optional",
1062
+
message:
1063
+
`Property "${name}" has conflicting markers: @required decorator with optional "?". ` +
1064
+
`Either remove @required to make it optional (preferred), or remove the "?".`,
1065
+
target: prop,
1066
+
severity: "error",
1067
+
});
1068
+
}
1069
+
950
1070
if (!prop.optional) {
951
1071
if (!isRequired(this.program, prop)) {
952
1072
this.program.reportDiagnostic({
···
1130
1250
}
1131
1251
}
1132
1252
1133
-
const unionDef = this.unionToLexiconProperty(unionType, prop);
1253
+
const unionDef = this.unionToLexiconProperty(unionType, prop, isDefining);
1134
1254
if (!unionDef) return null;
1135
1255
1136
1256
// Inherit description from union if no prop description and union is @inline
···
1331
1451
entity: Model | Union,
1332
1452
name: string | undefined,
1333
1453
namespace: Namespace | undefined,
1454
+
fullyQualified = false,
1334
1455
): string | null {
1335
1456
if (!name || !namespace || namespace.name === "TypeSpec") return null;
1336
1457
···
1350
1471
});
1351
1472
}
1352
1473
1353
-
// Local reference (same namespace)
1474
+
// For knownValues (fullyQualified=true), always use fully qualified refs
1475
+
if (fullyQualified) {
1476
+
return `${namespaceName}#${defName}`;
1477
+
}
1478
+
1479
+
// Local reference (same namespace) - use short ref
1354
1480
if (
1355
1481
this.currentLexiconId === namespaceName ||
1356
1482
this.currentLexiconId === `${namespaceName}.defs`
···
1363
1489
return namespaceName;
1364
1490
}
1365
1491
1492
+
// All other refs use fully qualified format
1366
1493
return `${namespaceName}#${defName}`;
1367
1494
}
1368
1495
1369
-
private getModelReference(model: Model): string | null {
1370
-
return this.getReference(model, model.name, model.namespace);
1496
+
private getModelReference(
1497
+
model: Model,
1498
+
fullyQualified = false,
1499
+
): string | null {
1500
+
return this.getReference(
1501
+
model,
1502
+
model.name,
1503
+
model.namespace,
1504
+
fullyQualified,
1505
+
);
1371
1506
}
1372
1507
1373
1508
private getUnionReference(union: Union): string | null {
+2
packages/emitter/src/tsp-index.ts
+2
packages/emitter/src/tsp-index.ts
+94
-48
packages/emitter/test/integration/atproto/input/app/bsky/actor/defs.tsp
+94
-48
packages/emitter/test/integration/atproto/input/app/bsky/actor/defs.tsp
···
90
90
@required allowSubscriptions: "followers" | "mutuals" | "none" | string;
91
91
}
92
92
93
-
@doc("Metadata about the requesting account's relationship with the subject account. Only has meaningful content for authed requests.")
93
+
/** Metadata about the requesting account's relationship with the subject account. Only has meaningful content for authed requests. */
94
94
model ViewerState {
95
95
muted?: boolean;
96
96
mutedByList?: app.bsky.graph.defs.ListViewBasic;
···
100
100
following?: atUri;
101
101
followedBy?: atUri;
102
102
103
-
@doc("This property is present only in selected cases, as an optimization.")
103
+
/** This property is present only in selected cases, as an optimization. */
104
104
knownFollowers?: KnownFollowers;
105
105
106
-
@doc("This property is present only in selected cases, as an optimization.")
106
+
/** This property is present only in selected cases, as an optimization. */
107
107
activitySubscription?: app.bsky.notification.defs.ActivitySubscription;
108
108
}
109
109
110
-
@doc("The subject's followers whom you also follow")
110
+
/** The subject's followers whom you also follow */
111
111
model KnownFollowers {
112
112
@required count: integer;
113
113
···
117
117
followers: ProfileViewBasic[];
118
118
}
119
119
120
-
@doc("Represents the verification information about the user this object is attached to.")
120
+
/** Represents the verification information about the user this object is attached to. */
121
121
model VerificationState {
122
-
@doc("All verifications issued by trusted verifiers on behalf of this user. Verifications by untrusted verifiers are not included.")
122
+
/** All verifications issued by trusted verifiers on behalf of this user. Verifications by untrusted verifiers are not included. */
123
123
@required
124
124
verifications: VerificationView[];
125
125
126
-
@doc("The user's status as a verified account.")
126
+
/** The user's status as a verified account. */
127
127
@required
128
128
verifiedStatus: "valid" | "invalid" | "none" | string;
129
129
130
-
@doc("The user's status as a trusted verifier.")
130
+
/** The user's status as a trusted verifier. */
131
131
@required
132
132
trustedVerifierStatus: "valid" | "invalid" | "none" | string;
133
133
}
134
134
135
-
@doc("An individual verification for an associated subject.")
135
+
/** An individual verification for an associated subject. */
136
136
model VerificationView {
137
-
@doc("The user who issued this verification.")
137
+
/** The user who issued this verification. */
138
138
@required
139
139
issuer: did;
140
140
141
-
@doc("The AT-URI of the verification record.")
141
+
/** The AT-URI of the verification record. */
142
142
@required
143
143
uri: atUri;
144
144
145
-
@doc("True if the verification passes validation, otherwise false.")
145
+
/** True if the verification passes validation, otherwise false. */
146
146
@required
147
147
isValid: boolean;
148
148
149
-
@doc("Timestamp when the verification was created.")
149
+
/** Timestamp when the verification was created. */
150
150
@required
151
151
createdAt: datetime;
152
152
}
···
174
174
}
175
175
176
176
model ContentLabelPref {
177
-
@doc("Which labeler does this preference apply to? If undefined, applies globally.")
177
+
/** Which labeler does this preference apply to? If undefined, applies globally. */
178
178
labelerDid?: did;
179
179
180
180
@required label: string;
···
199
199
}
200
200
201
201
model PersonalDetailsPref {
202
-
@doc("The birth date of account owner.")
202
+
/** The birth date of account owner. */
203
203
birthDate?: datetime;
204
204
}
205
205
206
206
model FeedViewPref {
207
-
@doc("The URI of the feed, or an identifier which describes the feed.")
207
+
/** The URI of the feed, or an identifier which describes the feed. */
208
208
@required
209
209
feed: string;
210
210
211
-
@doc("Hide replies in the feed.")
211
+
/** Hide replies in the feed. */
212
212
hideReplies?: boolean;
213
213
214
-
@doc("Hide replies in the feed if they are not by followed users.")
214
+
/** Hide replies in the feed if they are not by followed users. */
215
215
hideRepliesByUnfollowed?: boolean = true;
216
216
217
-
@doc("Hide replies in the feed if they do not have this number of likes.")
217
+
/** Hide replies in the feed if they do not have this number of likes. */
218
218
hideRepliesByLikeCount?: integer;
219
219
220
-
@doc("Hide reposts in the feed.")
220
+
/** Hide reposts in the feed. */
221
221
hideReposts?: boolean;
222
222
223
-
@doc("Hide quote posts in the feed.")
223
+
/** Hide quote posts in the feed. */
224
224
hideQuotePosts?: boolean;
225
225
}
226
226
227
227
model ThreadViewPref {
228
-
@doc("Sorting mode for threads.")
228
+
/** Sorting mode for threads. */
229
229
sort?: "oldest" | "newest" | "most-likes" | "random" | "hotness" | string;
230
230
231
-
@doc("Show followed users at the top of all replies.")
231
+
/** Show followed users at the top of all replies. */
232
232
prioritizeFollowedUsers?: boolean;
233
233
}
234
234
···
237
237
scalar InterestTag extends string;
238
238
239
239
model InterestsPref {
240
-
@doc("A list of tags which describe the account owner's interests gathered during onboarding.")
240
+
/** A list of tags which describe the account owner's interests gathered during onboarding. */
241
241
@maxItems(100)
242
242
@required
243
243
tags: InterestTag[];
···
251
251
string,
252
252
}
253
253
254
-
@doc("A word that the account owner has muted.")
254
+
/** A word that the account owner has muted. */
255
255
model MutedWord {
256
256
id?: string;
257
257
258
-
@doc("The muted word itself.")
258
+
/** The muted word itself. */
259
259
@maxGraphemes(1000)
260
260
@maxLength(10000)
261
261
@required
262
262
value: string;
263
263
264
-
@doc("The intended targets of the muted word.")
264
+
/** The intended targets of the muted word. */
265
265
@required
266
266
targets: MutedWordTarget[];
267
267
268
-
@doc("Groups of users to apply the muted word to. If undefined, applies to all users.")
268
+
/** Groups of users to apply the muted word to. If undefined, applies to all users. */
269
269
actorTarget?: "all" | "exclude-following" | string = "all";
270
270
271
-
@doc("The date and time at which the muted word will expire and no longer be applied.")
271
+
/** The date and time at which the muted word will expire and no longer be applied. */
272
272
expiresAt?: datetime;
273
273
}
274
274
275
275
model MutedWordsPref {
276
-
@doc("A list of words the account owner has muted.")
276
+
/** A list of words the account owner has muted. */
277
277
@required
278
278
items: MutedWord[];
279
279
}
280
280
281
281
model HiddenPostsPref {
282
-
@doc("A list of URIs of posts the account owner has hidden.")
282
+
/** A list of URIs of posts the account owner has hidden. */
283
283
@required
284
284
items: atUri[];
285
285
}
···
295
295
@maxLength(100)
296
296
scalar NudgeToken extends string;
297
297
298
-
@doc("A grab bag of state that's specific to the bsky.app program. Third-party apps shouldn't use this.")
298
+
/** A grab bag of state that's specific to the bsky.app program. Third-party apps shouldn't use this. */
299
299
model BskyAppStatePref {
300
300
activeProgressGuide?: BskyAppProgressGuide;
301
301
302
-
@doc("An array of tokens which identify nudges (modals, popups, tours, highlight dots) that should be shown to the user.")
302
+
/** An array of tokens which identify nudges (modals, popups, tours, highlight dots) that should be shown to the user. */
303
303
@maxItems(1000)
304
304
queuedNudges?: NudgeToken[];
305
305
306
-
@doc("Storage for NUXs the user has encountered.")
306
+
/** Storage for NUXs the user has encountered. */
307
307
@maxItems(100)
308
308
nuxs?: Nux[];
309
309
}
310
310
311
-
@doc("If set, an active progress guide. Once completed, can be set to undefined. Should have unspecced fields tracking progress.")
311
+
/** If set, an active progress guide. Once completed, can be set to undefined. Should have unspecced fields tracking progress. */
312
312
model BskyAppProgressGuide {
313
313
@maxLength(100)
314
314
@required
315
315
guide: string;
316
316
}
317
317
318
-
@doc("A new user experiences (NUX) storage object")
318
+
/** A new user experiences (NUX) storage object */
319
319
model Nux {
320
320
@maxLength(100)
321
321
@required
···
323
323
324
324
@required completed: boolean = false;
325
325
326
-
@doc("Arbitrary data for the NUX. The structure is defined by the NUX itself. Limited to 300 characters.")
326
+
/** Arbitrary data for the NUX. The structure is defined by the NUX itself. Limited to 300 characters. */
327
327
@maxGraphemes(300)
328
328
@maxLength(3000)
329
329
data?: string;
330
330
331
-
@doc("The date and time at which the NUX will expire and should be considered completed.")
331
+
/** The date and time at which the NUX will expire and should be considered completed. */
332
332
expiresAt?: datetime;
333
333
}
334
334
335
-
@doc("Preferences for how verified accounts appear in the app.")
335
+
/** Preferences for how verified accounts appear in the app. */
336
336
model VerificationPrefs {
337
-
@doc("Hide the blue check badges for verified accounts and trusted verifiers.")
337
+
/** Hide the blue check badges for verified accounts and trusted verifiers. */
338
338
hideBadges?: boolean = false;
339
339
}
340
340
341
-
@doc("Default post interaction settings for the account. These values should be applied as default values when creating new posts. These refs should mirror the threadgate and postgate records exactly.")
341
+
/** Default post interaction settings for the account. These values should be applied as default values when creating new posts. These refs should mirror the threadgate and postgate records exactly. */
342
342
model PostInteractionSettingsPref {
343
-
@doc("Matches threadgate record. List of rules defining who can reply to this users posts. If value is an empty array, no one can reply. If value is undefined, anyone can reply.")
343
+
/** Matches threadgate record. List of rules defining who can reply to this users posts. If value is an empty array, no one can reply. If value is undefined, anyone can reply. */
344
344
@maxItems(5)
345
345
threadgateAllowRules?: (
346
346
| app.bsky.feed.threadgate.MentionRule
···
350
350
| unknown
351
351
)[];
352
352
353
-
@doc("Matches postgate record. List of rules defining who can embed this users posts. If value is an empty array or is undefined, no particular rules apply and anyone can embed.")
353
+
/** Matches postgate record. List of rules defining who can embed this users posts. If value is an empty array or is undefined, no particular rules apply and anyone can embed. */
354
354
@maxItems(5)
355
355
postgateEmbeddingRules?: (app.bsky.feed.postgate.DisableRule | unknown)[];
356
356
}
357
357
358
358
model StatusView {
359
-
@doc("The status for the account.")
359
+
/** The status for the account. */
360
360
@required
361
-
status: "app.bsky.actor.status#live" | string;
361
+
status: app.bsky.actor.status.Live | string;
362
362
363
363
@required record: unknown;
364
364
365
-
@doc("An optional embed associated with the status.")
365
+
/** An optional embed associated with the status. */
366
366
embed?: app.bsky.embed.external.View;
367
367
368
-
@doc("The date when this status will expire. The application might choose to no longer return the status after expiration.")
368
+
/** The date when this status will expire. The application might choose to no longer return the status after expiration. */
369
369
expiresAt?: datetime;
370
370
371
-
@doc("True if the status is not expired, false if it is expired. Only present if expiration was set.")
371
+
/** True if the status is not expired, false if it is expired. Only present if expiration was set. */
372
372
isActive?: boolean;
373
373
}
374
374
}
375
+
376
+
// --- Externals ---
377
+
378
+
@external
379
+
namespace com.atproto.label.defs {
380
+
model Label { }
381
+
}
382
+
383
+
@external
384
+
namespace app.bsky.graph.defs {
385
+
model StarterPackViewBasic { }
386
+
model ListViewBasic { }
387
+
}
388
+
389
+
@external
390
+
namespace com.atproto.repo.strongRef {
391
+
model Main { }
392
+
}
393
+
394
+
@external
395
+
namespace app.bsky.notification.defs {
396
+
model ActivitySubscription { }
397
+
}
398
+
399
+
@external
400
+
namespace app.bsky.feed.threadgate {
401
+
model MentionRule { }
402
+
model FollowerRule { }
403
+
model FollowingRule { }
404
+
model ListRule { }
405
+
}
406
+
407
+
@external
408
+
namespace app.bsky.feed.postgate {
409
+
model DisableRule { }
410
+
}
411
+
412
+
@external
413
+
namespace app.bsky.actor.status {
414
+
@token model Live { }
415
+
}
416
+
417
+
@external
418
+
namespace app.bsky.embed.external {
419
+
model View { }
420
+
}
+8
-1
packages/emitter/test/integration/atproto/input/app/bsky/actor/getPreferences.tsp
+8
-1
packages/emitter/test/integration/atproto/input/app/bsky/actor/getPreferences.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace app.bsky.actor.getPreferences {
4
-
@doc("Get private preferences attached to the current account. Expected use is synchronization between multiple devices, and import/export during account migration. Requires auth.")
4
+
/** Get private preferences attached to the current account. Expected use is synchronization between multiple devices, and import/export during account migration. Requires auth. */
5
5
@query
6
6
op main(): {
7
7
@required preferences: app.bsky.actor.defs.Preferences;
8
8
};
9
9
}
10
+
11
+
// --- Externals ---
12
+
13
+
@external
14
+
namespace app.bsky.actor.defs {
15
+
model Preferences { }
16
+
}
+10
-3
packages/emitter/test/integration/atproto/input/app/bsky/actor/getProfile.tsp
+10
-3
packages/emitter/test/integration/atproto/input/app/bsky/actor/getProfile.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace app.bsky.actor.getProfile {
4
-
@doc("Get detailed profile view of an actor. Does not require auth, but contains relevant metadata with auth.")
4
+
/** Get detailed profile view of an actor. Does not require auth, but contains relevant metadata with auth. */
5
5
@query
6
6
op main(
7
-
@doc("Handle or DID of account to fetch profile of.")
8
-
actor: atIdentifier
7
+
/** Handle or DID of account to fetch profile of. */
8
+
@required actor: atIdentifier
9
9
): app.bsky.actor.defs.ProfileViewDetailed;
10
10
}
11
+
12
+
// --- Externals ---
13
+
14
+
@external
15
+
namespace app.bsky.actor.defs {
16
+
model ProfileViewDetailed { }
17
+
}
+9
-2
packages/emitter/test/integration/atproto/input/app/bsky/actor/getProfiles.tsp
+9
-2
packages/emitter/test/integration/atproto/input/app/bsky/actor/getProfiles.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace app.bsky.actor.getProfiles {
4
-
@doc("Get detailed profile views of multiple actors.")
4
+
/** Get detailed profile views of multiple actors. */
5
5
@query
6
6
op main(
7
7
@maxItems(25)
8
-
actors: atIdentifier[]
8
+
@required actors: atIdentifier[]
9
9
): {
10
10
@required profiles: app.bsky.actor.defs.ProfileViewDetailed[];
11
11
};
12
12
}
13
+
14
+
// --- Externals ---
15
+
16
+
@external
17
+
namespace app.bsky.actor.defs {
18
+
model ProfileViewDetailed { }
19
+
}
+9
-2
packages/emitter/test/integration/atproto/input/app/bsky/actor/getSuggestions.tsp
+9
-2
packages/emitter/test/integration/atproto/input/app/bsky/actor/getSuggestions.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace app.bsky.actor.getSuggestions {
4
-
@doc("Get a list of suggested actors. Expected use is discovery of accounts to follow during new account onboarding.")
4
+
/** Get a list of suggested actors. Expected use is discovery of accounts to follow during new account onboarding. */
5
5
@query
6
6
op main(
7
7
@minValue(1)
···
15
15
@required
16
16
actors: app.bsky.actor.defs.ProfileView[];
17
17
18
-
@doc("Snowflake for this recommendation, use when submitting recommendation events.")
18
+
/** Snowflake for this recommendation, use when submitting recommendation events. */
19
19
recId?: int32;
20
20
};
21
21
}
22
+
23
+
// --- Externals ---
24
+
25
+
@external
26
+
namespace app.bsky.actor.defs {
27
+
model ProfileView { }
28
+
}
+18
-6
packages/emitter/test/integration/atproto/input/app/bsky/actor/profile.tsp
+18
-6
packages/emitter/test/integration/atproto/input/app/bsky/actor/profile.tsp
···
2
2
3
3
namespace app.bsky.actor.profile {
4
4
@rec("literal:self")
5
-
@doc("A declaration of a Bluesky account profile.")
5
+
/** A declaration of a Bluesky account profile. */
6
6
model Main {
7
7
@maxGraphemes(64)
8
8
@maxLength(640)
9
9
displayName?: string;
10
10
11
-
@doc("Free-form profile description text.")
11
+
/** Free-form profile description text. */
12
12
@maxGraphemes(256)
13
13
@maxLength(2560)
14
14
description?: string;
15
15
16
-
@doc("Free-form pronouns text.")
16
+
/** Free-form pronouns text. */
17
17
@maxGraphemes(20)
18
18
@maxLength(200)
19
19
pronouns?: string;
20
20
21
21
website?: uri;
22
22
23
-
@doc("Small image to be displayed next to posts from account. AKA, 'profile picture'")
23
+
/** Small image to be displayed next to posts from account. AKA, 'profile picture' */
24
24
avatar?: Blob<#["image/png", "image/jpeg"], 1000000>;
25
25
26
-
@doc("Larger horizontal image to display behind profile view.")
26
+
/** Larger horizontal image to display behind profile view. */
27
27
banner?: Blob<#["image/png", "image/jpeg"], 1000000>;
28
28
29
-
@doc("Self-label values, specific to the Bluesky application, on the overall account.")
29
+
/** Self-label values, specific to the Bluesky application, on the overall account. */
30
30
labels?: (com.atproto.label.defs.SelfLabels | unknown);
31
31
32
32
joinedViaStarterPack?: com.atproto.repo.strongRef.Main;
···
34
34
createdAt?: datetime;
35
35
}
36
36
}
37
+
38
+
// --- Externals ---
39
+
40
+
@external
41
+
namespace com.atproto.label.defs {
42
+
model SelfLabels { }
43
+
}
44
+
45
+
@external
46
+
namespace com.atproto.repo.strongRef {
47
+
model Main { }
48
+
}
+8
-1
packages/emitter/test/integration/atproto/input/app/bsky/actor/putPreferences.tsp
+8
-1
packages/emitter/test/integration/atproto/input/app/bsky/actor/putPreferences.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace app.bsky.actor.putPreferences {
4
-
@doc("Set the private preferences attached to the account.")
4
+
/** Set the private preferences attached to the account. */
5
5
@procedure
6
6
op main(input: {
7
7
@required preferences: app.bsky.actor.defs.Preferences;
8
8
}): void;
9
9
}
10
+
11
+
// --- Externals ---
12
+
13
+
@external
14
+
namespace app.bsky.actor.defs {
15
+
model Preferences { }
16
+
}
+10
-3
packages/emitter/test/integration/atproto/input/app/bsky/actor/searchActors.tsp
+10
-3
packages/emitter/test/integration/atproto/input/app/bsky/actor/searchActors.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace app.bsky.actor.searchActors {
4
-
@doc("Find actors (profiles) matching search criteria. Does not require auth.")
4
+
/** Find actors (profiles) matching search criteria. Does not require auth. */
5
5
@query
6
6
op main(
7
-
@doc("DEPRECATED: use 'q' instead.")
7
+
/** DEPRECATED: use 'q' instead. */
8
8
term?: string,
9
9
10
-
@doc("Search query string. Syntax, phrase, boolean, and faceting is unspecified, but Lucene query syntax is recommended.")
10
+
/** Search query string. Syntax, phrase, boolean, and faceting is unspecified, but Lucene query syntax is recommended. */
11
11
q?: string,
12
12
13
13
@minValue(1)
···
20
20
@required actors: app.bsky.actor.defs.ProfileView[];
21
21
};
22
22
}
23
+
24
+
// --- Externals ---
25
+
26
+
@external
27
+
namespace app.bsky.actor.defs {
28
+
model ProfileView { }
29
+
}
+10
-3
packages/emitter/test/integration/atproto/input/app/bsky/actor/searchActorsTypeahead.tsp
+10
-3
packages/emitter/test/integration/atproto/input/app/bsky/actor/searchActorsTypeahead.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace app.bsky.actor.searchActorsTypeahead {
4
-
@doc("Find actor suggestions for a prefix search term. Expected use is for auto-completion during text field entry. Does not require auth.")
4
+
/** Find actor suggestions for a prefix search term. Expected use is for auto-completion during text field entry. Does not require auth. */
5
5
@query
6
6
op main(
7
-
@doc("DEPRECATED: use 'q' instead.")
7
+
/** DEPRECATED: use 'q' instead. */
8
8
term?: string,
9
9
10
-
@doc("Search query prefix; not a full query string.")
10
+
/** Search query prefix; not a full query string. */
11
11
q?: string,
12
12
13
13
@minValue(1)
···
17
17
@required actors: app.bsky.actor.defs.ProfileViewBasic[];
18
18
};
19
19
}
20
+
21
+
// --- Externals ---
22
+
23
+
@external
24
+
namespace app.bsky.actor.defs {
25
+
model ProfileViewBasic { }
26
+
}
+13
-6
packages/emitter/test/integration/atproto/input/app/bsky/actor/status.tsp
+13
-6
packages/emitter/test/integration/atproto/input/app/bsky/actor/status.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace app.bsky.actor.status {
4
-
@doc("A declaration of a Bluesky account status.")
4
+
/** A declaration of a Bluesky account status. */
5
5
@rec("literal:self")
6
6
model Main {
7
-
@doc("The status for the account.")
7
+
/** The status for the account. */
8
8
@required
9
-
status: "app.bsky.actor.status#live" | string;
9
+
status: Live | string;
10
10
11
-
@doc("An optional embed associated with the status.")
11
+
/** An optional embed associated with the status. */
12
12
embed?: (app.bsky.embed.external.Main | unknown);
13
13
14
-
@doc("The duration of the status in minutes. Applications can choose to impose minimum and maximum limits.")
14
+
/** The duration of the status in minutes. Applications can choose to impose minimum and maximum limits. */
15
15
@minValue(1)
16
16
durationMinutes?: integer;
17
17
18
18
@required createdAt: datetime;
19
19
}
20
20
21
-
@doc("Advertises an account as currently offering live content.")
21
+
/** Advertises an account as currently offering live content. */
22
22
@token
23
23
model Live {}
24
24
}
25
+
26
+
// --- Externals ---
27
+
28
+
@external
29
+
namespace app.bsky.embed.external {
30
+
model Main { }
31
+
}
+2
-2
packages/emitter/test/integration/atproto/input/app/bsky/bookmark/createBookmark.tsp
+2
-2
packages/emitter/test/integration/atproto/input/app/bsky/bookmark/createBookmark.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace app.bsky.bookmark.createBookmark {
4
-
@doc("Creates a private bookmark for the specified record. Currently, only `app.bsky.feed.post` records are supported. Requires authentication.")
4
+
/** Creates a private bookmark for the specified record. Currently, only `app.bsky.feed.post` records are supported. Requires authentication. */
5
5
@errors(UnsupportedCollection)
6
6
@procedure
7
7
op main(input: {
···
9
9
@required cid: cid;
10
10
}): void;
11
11
12
-
@doc("The URI to be bookmarked is for an unsupported collection.")
12
+
/** The URI to be bookmarked is for an unsupported collection. */
13
13
model UnsupportedCollection {}
14
14
}
+17
-3
packages/emitter/test/integration/atproto/input/app/bsky/bookmark/defs.tsp
+17
-3
packages/emitter/test/integration/atproto/input/app/bsky/bookmark/defs.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace app.bsky.bookmark.defs {
4
-
@doc("Object used to store bookmark data in stash.")
4
+
/** Object used to store bookmark data in stash. */
5
5
model Bookmark {
6
-
@doc("A strong ref to the record to be bookmarked. Currently, only `app.bsky.feed.post` records are supported.")
6
+
/** A strong ref to the record to be bookmarked. Currently, only `app.bsky.feed.post` records are supported. */
7
7
@required
8
8
subject: com.atproto.repo.strongRef.Main;
9
9
}
10
10
11
11
model BookmarkView {
12
-
@doc("A strong ref to the bookmarked record.")
12
+
/** A strong ref to the bookmarked record. */
13
13
@required
14
14
subject: com.atproto.repo.strongRef.Main;
15
15
···
24
24
);
25
25
}
26
26
}
27
+
28
+
// --- Externals ---
29
+
30
+
@external
31
+
namespace com.atproto.repo.strongRef {
32
+
model Main { }
33
+
}
34
+
35
+
@external
36
+
namespace app.bsky.feed.defs {
37
+
model BlockedPost { }
38
+
model NotFoundPost { }
39
+
model PostView { }
40
+
}
+2
-2
packages/emitter/test/integration/atproto/input/app/bsky/bookmark/deleteBookmark.tsp
+2
-2
packages/emitter/test/integration/atproto/input/app/bsky/bookmark/deleteBookmark.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace app.bsky.bookmark.deleteBookmark {
4
-
@doc("Deletes a private bookmark for the specified record. Currently, only `app.bsky.feed.post` records are supported. Requires authentication.")
4
+
/** Deletes a private bookmark for the specified record. Currently, only `app.bsky.feed.post` records are supported. Requires authentication. */
5
5
@errors(UnsupportedCollection)
6
6
@procedure
7
7
op main(input: {
8
8
@required uri: atUri;
9
9
}): void;
10
10
11
-
@doc("The URI to be bookmarked is for an unsupported collection.")
11
+
/** The URI to be bookmarked is for an unsupported collection. */
12
12
model UnsupportedCollection {}
13
13
}
+8
-1
packages/emitter/test/integration/atproto/input/app/bsky/bookmark/getBookmarks.tsp
+8
-1
packages/emitter/test/integration/atproto/input/app/bsky/bookmark/getBookmarks.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace app.bsky.bookmark.getBookmarks {
4
-
@doc("Gets views of records bookmarked by the authenticated user. Requires authentication.")
4
+
/** Gets views of records bookmarked by the authenticated user. Requires authentication. */
5
5
@query
6
6
op main(
7
7
@minValue(1)
···
14
14
@required bookmarks: app.bsky.bookmark.defs.BookmarkView[];
15
15
};
16
16
}
17
+
18
+
// --- Externals ---
19
+
20
+
@external
21
+
namespace app.bsky.bookmark.defs {
22
+
model BookmarkView { }
23
+
}
+1
-1
packages/emitter/test/integration/atproto/input/app/bsky/embed/defs.tsp
+1
-1
packages/emitter/test/integration/atproto/input/app/bsky/embed/defs.tsp
···
2
2
3
3
namespace app.bsky.embed.defs {
4
4
// Description goes on the model for defs, unlike standalone lexicons where it goes at lexicon level
5
-
@doc("width:height represents an aspect ratio. It may be approximate, and may not correspond to absolute dimensions in any given unit.")
5
+
/** width:height represents an aspect ratio. It may be approximate, and may not correspond to absolute dimensions in any given unit. */
6
6
model AspectRatio {
7
7
@minValue(1)
8
8
@required
+1
-1
packages/emitter/test/integration/atproto/input/app/bsky/embed/external.tsp
+1
-1
packages/emitter/test/integration/atproto/input/app/bsky/embed/external.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace app.bsky.embed.external {
4
-
@doc("A representation of some externally linked content (eg, a URL and 'card'), embedded in a Bluesky record (eg, a post).")
4
+
/** A representation of some externally linked content (eg, a URL and 'card'), embedded in a Bluesky record (eg, a post). */
5
5
model Main {
6
6
@required external: External;
7
7
}
+12
-5
packages/emitter/test/integration/atproto/input/app/bsky/embed/images.tsp
+12
-5
packages/emitter/test/integration/atproto/input/app/bsky/embed/images.tsp
···
1
1
import "@typelex/emitter";
2
2
3
-
@doc("A set of images embedded in a Bluesky record (eg, a post).")
3
+
/** A set of images embedded in a Bluesky record (eg, a post). */
4
4
namespace app.bsky.embed.images {
5
5
model Main {
6
6
@maxItems(4)
···
11
11
model Image {
12
12
@required image: Blob<#["image/*"], 1000000>;
13
13
14
-
@doc("Alt text description of the image, for accessibility.")
14
+
/** Alt text description of the image, for accessibility. */
15
15
@required
16
16
alt: string;
17
17
···
25
25
}
26
26
27
27
model ViewImage {
28
-
@doc("Fully-qualified URL where a thumbnail of the image can be fetched. For example, CDN location provided by the App View.")
28
+
/** Fully-qualified URL where a thumbnail of the image can be fetched. For example, CDN location provided by the App View. */
29
29
@required
30
30
thumb: uri;
31
31
32
-
@doc("Fully-qualified URL where a large version of the image can be fetched. May or may not be the exact original blob. For example, CDN location provided by the App View.")
32
+
/** Fully-qualified URL where a large version of the image can be fetched. May or may not be the exact original blob. For example, CDN location provided by the App View. */
33
33
@required
34
34
fullsize: uri;
35
35
36
-
@doc("Alt text description of the image, for accessibility.")
36
+
/** Alt text description of the image, for accessibility. */
37
37
@required
38
38
alt: string;
39
39
40
40
aspectRatio?: app.bsky.embed.defs.AspectRatio;
41
41
}
42
42
}
43
+
44
+
// --- Externals ---
45
+
46
+
@external
47
+
namespace app.bsky.embed.defs {
48
+
model AspectRatio { }
49
+
}
+56
-2
packages/emitter/test/integration/atproto/input/app/bsky/embed/record.tsp
+56
-2
packages/emitter/test/integration/atproto/input/app/bsky/embed/record.tsp
···
1
1
import "@typelex/emitter";
2
2
3
-
@doc("A representation of a record embedded in a Bluesky record (eg, a post). For example, a quote-post, or sharing a feed generator record.")
3
+
/** A representation of a record embedded in a Bluesky record (eg, a post). For example, a quote-post, or sharing a feed generator record. */
4
4
namespace app.bsky.embed.`record` {
5
5
model Main {
6
6
@required record: com.atproto.repo.strongRef.Main;
···
26
26
@required cid: cid;
27
27
@required author: app.bsky.actor.defs.ProfileViewBasic;
28
28
29
-
@doc("The record data itself.")
29
+
/** The record data itself. */
30
30
@required
31
31
value: unknown;
32
32
···
74
74
detached: boolean = true;
75
75
}
76
76
}
77
+
78
+
// --- Externals ---
79
+
80
+
@external
81
+
namespace com.atproto.repo.strongRef {
82
+
model Main { }
83
+
}
84
+
85
+
@external
86
+
namespace app.bsky.feed.defs {
87
+
model GeneratorView { }
88
+
model BlockedAuthor { }
89
+
}
90
+
91
+
@external
92
+
namespace app.bsky.graph.defs {
93
+
model ListView { }
94
+
model StarterPackViewBasic { }
95
+
}
96
+
97
+
@external
98
+
namespace app.bsky.labeler.defs {
99
+
model LabelerView { }
100
+
}
101
+
102
+
@external
103
+
namespace app.bsky.actor.defs {
104
+
model ProfileViewBasic { }
105
+
}
106
+
107
+
@external
108
+
namespace com.atproto.label.defs {
109
+
model Label { }
110
+
}
111
+
112
+
@external
113
+
namespace app.bsky.embed.images {
114
+
model View { }
115
+
}
116
+
117
+
@external
118
+
namespace app.bsky.embed.video {
119
+
model View { }
120
+
}
121
+
122
+
@external
123
+
namespace app.bsky.embed.external {
124
+
model View { }
125
+
}
126
+
127
+
@external
128
+
namespace app.bsky.embed.recordWithMedia {
129
+
model View { }
130
+
}
+27
-1
packages/emitter/test/integration/atproto/input/app/bsky/embed/recordWithMedia.tsp
+27
-1
packages/emitter/test/integration/atproto/input/app/bsky/embed/recordWithMedia.tsp
···
1
1
import "@typelex/emitter";
2
2
3
-
@doc("A representation of a record embedded in a Bluesky record (eg, a post), alongside other compatible embeds. For example, a quote post and image, or a quote post and external URL card.")
3
+
/** A representation of a record embedded in a Bluesky record (eg, a post), alongside other compatible embeds. For example, a quote post and image, or a quote post and external URL card. */
4
4
namespace app.bsky.embed.recordWithMedia {
5
5
model Main {
6
6
@required record: app.bsky.embed.record.Main;
···
26
26
);
27
27
}
28
28
}
29
+
30
+
// --- Externals ---
31
+
32
+
@external
33
+
namespace app.bsky.embed.`record` {
34
+
model Main { }
35
+
model View { }
36
+
}
37
+
38
+
@external
39
+
namespace app.bsky.embed.images {
40
+
model Main { }
41
+
model View { }
42
+
}
43
+
44
+
@external
45
+
namespace app.bsky.embed.video {
46
+
model Main { }
47
+
model View { }
48
+
}
49
+
50
+
@external
51
+
namespace app.bsky.embed.external {
52
+
model Main { }
53
+
model View { }
54
+
}
+10
-3
packages/emitter/test/integration/atproto/input/app/bsky/embed/video.tsp
+10
-3
packages/emitter/test/integration/atproto/input/app/bsky/embed/video.tsp
···
1
1
import "@typelex/emitter";
2
2
3
-
@doc("A video embedded in a Bluesky record (eg, a post).")
3
+
/** A video embedded in a Bluesky record (eg, a post). */
4
4
namespace app.bsky.embed.video {
5
5
model Main {
6
-
@doc("The mp4 video file. May be up to 100mb, formerly limited to 50mb.")
6
+
/** The mp4 video file. May be up to 100mb, formerly limited to 50mb. */
7
7
@required
8
8
video: Blob<#["video/mp4"], 100000000>;
9
9
10
10
@maxItems(20)
11
11
captions?: Caption[];
12
12
13
-
@doc("Alt text description of the video, for accessibility.")
13
+
/** Alt text description of the video, for accessibility. */
14
14
@maxGraphemes(1000)
15
15
@maxLength(10000)
16
16
alt?: string;
···
36
36
aspectRatio?: app.bsky.embed.defs.AspectRatio;
37
37
}
38
38
}
39
+
40
+
// --- Externals ---
41
+
42
+
@external
43
+
namespace app.bsky.embed.defs {
44
+
model AspectRatio { }
45
+
}
+84
-35
packages/emitter/test/integration/atproto/input/app/bsky/feed/defs.tsp
+84
-35
packages/emitter/test/integration/atproto/input/app/bsky/feed/defs.tsp
···
29
29
threadgate?: ThreadgateView;
30
30
}
31
31
32
-
@doc("Metadata about the requesting account's relationship with the subject content. Only has meaningful content for authed requests.")
32
+
/** Metadata about the requesting account's relationship with the subject content. Only has meaningful content for authed requests. */
33
33
model ViewerState {
34
34
repost?: atUri;
35
35
like?: atUri;
···
40
40
pinned?: boolean;
41
41
}
42
42
43
-
@doc("Metadata about this post within the context of the thread it is in.")
43
+
/** Metadata about this post within the context of the thread it is in. */
44
44
model ThreadContext {
45
45
rootAuthorLike?: atUri;
46
46
}
···
51
51
reply?: ReplyRef;
52
52
reason?: (ReasonRepost | ReasonPin | unknown);
53
53
54
-
@doc("Context provided by feed generator that may be passed back alongside interactions.")
54
+
/** Context provided by feed generator that may be passed back alongside interactions. */
55
55
@maxLength(2000)
56
56
feedContext?: string;
57
57
58
-
@doc("Unique identifier per request that may be passed back alongside interactions.")
58
+
/** Unique identifier per request that may be passed back alongside interactions. */
59
59
@maxLength(100)
60
60
reqId?: string;
61
61
}
···
64
64
@required root: (PostView | NotFoundPost | BlockedPost | unknown);
65
65
@required parent: (PostView | NotFoundPost | BlockedPost | unknown);
66
66
67
-
@doc("When parent is a reply to another post, this is the author of that post.")
67
+
/** When parent is a reply to another post, this is the author of that post. */
68
68
grandparentAuthor?: app.bsky.actor.defs.ProfileViewBasic;
69
69
}
70
70
···
133
133
acceptsInteractions?: boolean;
134
134
labels?: com.atproto.label.defs.Label[];
135
135
viewer?: GeneratorViewerState;
136
-
contentMode?: "app.bsky.feed.defs#contentModeUnspecified" | "app.bsky.feed.defs#contentModeVideo" | string;
136
+
contentMode?: ContentModeUnspecified | ContentModeVideo | string;
137
137
138
138
@required indexedAt: datetime;
139
139
}
···
147
147
148
148
reason?: (SkeletonReasonRepost | SkeletonReasonPin | unknown);
149
149
150
-
@doc("Context that will be passed through to client and may be passed to feed generator back alongside interactions.")
150
+
/** Context that will be passed through to client and may be passed to feed generator back alongside interactions. */
151
151
@maxLength(2000)
152
152
feedContext?: string;
153
153
}
···
167
167
168
168
model Interaction {
169
169
item?: atUri;
170
-
event?: "app.bsky.feed.defs#requestLess"
171
-
| "app.bsky.feed.defs#requestMore"
172
-
| "app.bsky.feed.defs#clickthroughItem"
173
-
| "app.bsky.feed.defs#clickthroughAuthor"
174
-
| "app.bsky.feed.defs#clickthroughReposter"
175
-
| "app.bsky.feed.defs#clickthroughEmbed"
176
-
| "app.bsky.feed.defs#interactionSeen"
177
-
| "app.bsky.feed.defs#interactionLike"
178
-
| "app.bsky.feed.defs#interactionRepost"
179
-
| "app.bsky.feed.defs#interactionReply"
180
-
| "app.bsky.feed.defs#interactionQuote"
181
-
| "app.bsky.feed.defs#interactionShare"
170
+
event?: RequestLess
171
+
| RequestMore
172
+
| ClickthroughItem
173
+
| ClickthroughAuthor
174
+
| ClickthroughReposter
175
+
| ClickthroughEmbed
176
+
| InteractionSeen
177
+
| InteractionLike
178
+
| InteractionRepost
179
+
| InteractionReply
180
+
| InteractionQuote
181
+
| InteractionShare
182
182
| string;
183
183
184
-
@doc("Context on a feed item that was originally supplied by the feed generator on getFeedSkeleton.")
184
+
/** Context on a feed item that was originally supplied by the feed generator on getFeedSkeleton. */
185
185
@maxLength(2000)
186
186
feedContext?: string;
187
187
188
-
@doc("Unique identifier per request that may be passed back alongside interactions.")
188
+
/** Unique identifier per request that may be passed back alongside interactions. */
189
189
@maxLength(100)
190
190
reqId?: string;
191
191
}
192
192
193
-
@doc("Request that less content like the given feed item be shown in the feed")
193
+
/** Request that less content like the given feed item be shown in the feed */
194
194
@token
195
195
model RequestLess {}
196
196
197
-
@doc("Request that more content like the given feed item be shown in the feed")
197
+
/** Request that more content like the given feed item be shown in the feed */
198
198
@token
199
199
model RequestMore {}
200
200
201
-
@doc("User clicked through to the feed item")
201
+
/** User clicked through to the feed item */
202
202
@token
203
203
model ClickthroughItem {}
204
204
205
-
@doc("User clicked through to the author of the feed item")
205
+
/** User clicked through to the author of the feed item */
206
206
@token
207
207
model ClickthroughAuthor {}
208
208
209
-
@doc("User clicked through to the reposter of the feed item")
209
+
/** User clicked through to the reposter of the feed item */
210
210
@token
211
211
model ClickthroughReposter {}
212
212
213
-
@doc("User clicked through to the embedded content of the feed item")
213
+
/** User clicked through to the embedded content of the feed item */
214
214
@token
215
215
model ClickthroughEmbed {}
216
216
217
-
@doc("Declares the feed generator returns any types of posts.")
217
+
/** Declares the feed generator returns any types of posts. */
218
218
@token
219
219
model ContentModeUnspecified {}
220
220
221
-
@doc("Declares the feed generator returns posts containing app.bsky.embed.video embeds.")
221
+
/** Declares the feed generator returns posts containing app.bsky.embed.video embeds. */
222
222
@token
223
223
model ContentModeVideo {}
224
224
225
-
@doc("Feed item was seen by user")
225
+
/** Feed item was seen by user */
226
226
@token
227
227
model InteractionSeen {}
228
228
229
-
@doc("User liked the feed item")
229
+
/** User liked the feed item */
230
230
@token
231
231
model InteractionLike {}
232
232
233
-
@doc("User reposted the feed item")
233
+
/** User reposted the feed item */
234
234
@token
235
235
model InteractionRepost {}
236
236
237
-
@doc("User replied to the feed item")
237
+
/** User replied to the feed item */
238
238
@token
239
239
model InteractionReply {}
240
240
241
-
@doc("User quoted the feed item")
241
+
/** User quoted the feed item */
242
242
@token
243
243
model InteractionQuote {}
244
244
245
-
@doc("User shared the feed item")
245
+
/** User shared the feed item */
246
246
@token
247
247
model InteractionShare {}
248
248
}
249
+
250
+
// --- Externals ---
251
+
252
+
@external
253
+
namespace app.bsky.actor.defs {
254
+
model ProfileViewBasic { }
255
+
model ViewerState { }
256
+
model ProfileView { }
257
+
}
258
+
259
+
@external
260
+
namespace app.bsky.embed.images {
261
+
model View { }
262
+
}
263
+
264
+
@external
265
+
namespace app.bsky.embed.video {
266
+
model View { }
267
+
}
268
+
269
+
@external
270
+
namespace app.bsky.embed.external {
271
+
model View { }
272
+
}
273
+
274
+
@external
275
+
namespace app.bsky.embed.`record` {
276
+
model View { }
277
+
}
278
+
279
+
@external
280
+
namespace app.bsky.embed.recordWithMedia {
281
+
model View { }
282
+
}
283
+
284
+
@external
285
+
namespace com.atproto.label.defs {
286
+
model Label { }
287
+
}
288
+
289
+
@external
290
+
namespace app.bsky.richtext.facet {
291
+
model Main { }
292
+
}
293
+
294
+
@external
295
+
namespace app.bsky.graph.defs {
296
+
model ListViewBasic { }
297
+
}
+1
-1
packages/emitter/test/integration/atproto/input/app/bsky/feed/describeFeedGenerator.tsp
+1
-1
packages/emitter/test/integration/atproto/input/app/bsky/feed/describeFeedGenerator.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace app.bsky.feed.describeFeedGenerator {
4
-
@doc("Get information about a feed generator, including policies and offered feed URIs. Does not require auth; implemented by Feed Generator services (not App View).")
4
+
/** Get information about a feed generator, including policies and offered feed URIs. Does not require auth; implemented by Feed Generator services (not App View). */
5
5
@query
6
6
op main(): {
7
7
@required did: did;
+22
-4
packages/emitter/test/integration/atproto/input/app/bsky/feed/generator.tsp
+22
-4
packages/emitter/test/integration/atproto/input/app/bsky/feed/generator.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace app.bsky.feed.generator {
4
-
@doc("Record declaring of the existence of a feed generator, and containing metadata about it. The record can exist in any repository.")
4
+
/** Record declaring of the existence of a feed generator, and containing metadata about it. The record can exist in any repository. */
5
5
@rec("any")
6
6
model Main {
7
7
@required did: did;
···
19
19
20
20
avatar?: Blob<#["image/png", "image/jpeg"], 1000000>;
21
21
22
-
@doc("Declaration that a feed accepts feedback interactions from a client through app.bsky.feed.sendInteractions")
22
+
/** Declaration that a feed accepts feedback interactions from a client through app.bsky.feed.sendInteractions */
23
23
acceptsInteractions?: boolean;
24
24
25
-
@doc("Self-label values")
25
+
/** Self-label values */
26
26
labels?: (com.atproto.label.defs.SelfLabels | unknown);
27
27
28
-
contentMode?: "app.bsky.feed.defs#contentModeUnspecified" | "app.bsky.feed.defs#contentModeVideo" | string;
28
+
contentMode?: app.bsky.feed.defs.ContentModeUnspecified | app.bsky.feed.defs.ContentModeVideo | string;
29
29
30
30
@required createdAt: datetime;
31
31
}
32
32
}
33
+
34
+
// --- Externals ---
35
+
36
+
@external
37
+
namespace app.bsky.richtext.facet {
38
+
model Main { }
39
+
}
40
+
41
+
@external
42
+
namespace com.atproto.label.defs {
43
+
model SelfLabels { }
44
+
}
45
+
46
+
@external
47
+
namespace app.bsky.feed.defs {
48
+
@token model ContentModeUnspecified { }
49
+
@token model ContentModeVideo { }
50
+
}
+9
-2
packages/emitter/test/integration/atproto/input/app/bsky/feed/getActorFeeds.tsp
+9
-2
packages/emitter/test/integration/atproto/input/app/bsky/feed/getActorFeeds.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace app.bsky.feed.getActorFeeds {
4
-
@doc("Get a list of feeds (feed generator records) created by the actor (in the actor's repo).")
4
+
/** Get a list of feeds (feed generator records) created by the actor (in the actor's repo). */
5
5
@query
6
6
op main(
7
-
actor: atIdentifier,
7
+
@required actor: atIdentifier,
8
8
9
9
@minValue(1)
10
10
@maxValue(100)
···
16
16
@required feeds: app.bsky.feed.defs.GeneratorView[];
17
17
};
18
18
}
19
+
20
+
// --- Externals ---
21
+
22
+
@external
23
+
namespace app.bsky.feed.defs {
24
+
model GeneratorView { }
25
+
}
+9
-2
packages/emitter/test/integration/atproto/input/app/bsky/feed/getActorLikes.tsp
+9
-2
packages/emitter/test/integration/atproto/input/app/bsky/feed/getActorLikes.tsp
···
4
4
model BlockedActor {}
5
5
model BlockedByActor {}
6
6
7
-
@doc("Get a list of posts liked by an actor. Requires auth, actor must be the requesting account.")
7
+
/** Get a list of posts liked by an actor. Requires auth, actor must be the requesting account. */
8
8
@query
9
9
@errors(BlockedActor, BlockedByActor)
10
10
op main(
11
-
actor: atIdentifier,
11
+
@required actor: atIdentifier,
12
12
13
13
@minValue(1)
14
14
@maxValue(100)
···
20
20
@required feed: app.bsky.feed.defs.FeedViewPost[];
21
21
};
22
22
}
23
+
24
+
// --- Externals ---
25
+
26
+
@external
27
+
namespace app.bsky.feed.defs {
28
+
model FeedViewPost { }
29
+
}
+10
-3
packages/emitter/test/integration/atproto/input/app/bsky/feed/getAuthorFeed.tsp
+10
-3
packages/emitter/test/integration/atproto/input/app/bsky/feed/getAuthorFeed.tsp
···
4
4
model BlockedActor {}
5
5
model BlockedByActor {}
6
6
7
-
@doc("Get a view of an actor's 'author feed' (post and reposts by the author). Does not require auth.")
7
+
/** Get a view of an actor's 'author feed' (post and reposts by the author). Does not require auth. */
8
8
@query
9
9
@errors(BlockedActor, BlockedByActor)
10
10
op main(
11
-
actor: atIdentifier,
11
+
@required actor: atIdentifier,
12
12
13
13
@minValue(1)
14
14
@maxValue(100)
···
16
16
17
17
cursor?: string,
18
18
19
-
@doc("Combinations of post/repost types to include in response.")
19
+
/** Combinations of post/repost types to include in response. */
20
20
filter?: "posts_with_replies" | "posts_no_replies" | "posts_with_media" | "posts_and_author_threads" | "posts_with_video" | string = "posts_with_replies",
21
21
22
22
includePins?: boolean = false
···
25
25
@required feed: app.bsky.feed.defs.FeedViewPost[];
26
26
};
27
27
}
28
+
29
+
// --- Externals ---
30
+
31
+
@external
32
+
namespace app.bsky.feed.defs {
33
+
model FeedViewPost { }
34
+
}
+9
-2
packages/emitter/test/integration/atproto/input/app/bsky/feed/getFeed.tsp
+9
-2
packages/emitter/test/integration/atproto/input/app/bsky/feed/getFeed.tsp
···
3
3
namespace app.bsky.feed.getFeed {
4
4
model UnknownFeed {}
5
5
6
-
@doc("Get a hydrated feed from an actor's selected feed generator. Implemented by App View.")
6
+
/** Get a hydrated feed from an actor's selected feed generator. Implemented by App View. */
7
7
@query
8
8
@errors(UnknownFeed)
9
9
op main(
10
-
feed: atUri,
10
+
@required feed: atUri,
11
11
12
12
@minValue(1)
13
13
@maxValue(100)
···
19
19
@required feed: app.bsky.feed.defs.FeedViewPost[];
20
20
};
21
21
}
22
+
23
+
// --- Externals ---
24
+
25
+
@external
26
+
namespace app.bsky.feed.defs {
27
+
model FeedViewPost { }
28
+
}
+12
-5
packages/emitter/test/integration/atproto/input/app/bsky/feed/getFeedGenerator.tsp
+12
-5
packages/emitter/test/integration/atproto/input/app/bsky/feed/getFeedGenerator.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace app.bsky.feed.getFeedGenerator {
4
-
@doc("Get information about a feed generator. Implemented by AppView.")
4
+
/** Get information about a feed generator. Implemented by AppView. */
5
5
@query
6
6
op main(
7
-
@doc("AT-URI of the feed generator record.")
8
-
feed: atUri
7
+
/** AT-URI of the feed generator record. */
8
+
@required feed: atUri
9
9
): {
10
10
@required view: app.bsky.feed.defs.GeneratorView;
11
11
12
-
@doc("Indicates whether the feed generator service has been online recently, or else seems to be inactive.")
12
+
/** Indicates whether the feed generator service has been online recently, or else seems to be inactive. */
13
13
@required
14
14
isOnline: boolean;
15
15
16
-
@doc("Indicates whether the feed generator service is compatible with the record declaration.")
16
+
/** Indicates whether the feed generator service is compatible with the record declaration. */
17
17
@required
18
18
isValid: boolean;
19
19
};
20
20
}
21
+
22
+
// --- Externals ---
23
+
24
+
@external
25
+
namespace app.bsky.feed.defs {
26
+
model GeneratorView { }
27
+
}
+9
-2
packages/emitter/test/integration/atproto/input/app/bsky/feed/getFeedGenerators.tsp
+9
-2
packages/emitter/test/integration/atproto/input/app/bsky/feed/getFeedGenerators.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace app.bsky.feed.getFeedGenerators {
4
-
@doc("Get information about a list of feed generators.")
4
+
/** Get information about a list of feed generators. */
5
5
@query
6
6
op main(
7
-
feeds: atUri[]
7
+
@required feeds: atUri[]
8
8
): {
9
9
@required feeds: app.bsky.feed.defs.GeneratorView[];
10
10
};
11
11
}
12
+
13
+
// --- Externals ---
14
+
15
+
@external
16
+
namespace app.bsky.feed.defs {
17
+
model GeneratorView { }
18
+
}
+11
-4
packages/emitter/test/integration/atproto/input/app/bsky/feed/getFeedSkeleton.tsp
+11
-4
packages/emitter/test/integration/atproto/input/app/bsky/feed/getFeedSkeleton.tsp
···
3
3
namespace app.bsky.feed.getFeedSkeleton {
4
4
model UnknownFeed {}
5
5
6
-
@doc("Get a skeleton of a feed provided by a feed generator. Auth is optional, depending on provider requirements, and provides the DID of the requester. Implemented by Feed Generator Service.")
6
+
/** Get a skeleton of a feed provided by a feed generator. Auth is optional, depending on provider requirements, and provides the DID of the requester. Implemented by Feed Generator Service. */
7
7
@query
8
8
@errors(UnknownFeed)
9
9
op main(
10
-
@doc("Reference to feed generator record describing the specific feed being requested.")
11
-
feed: atUri,
10
+
/** Reference to feed generator record describing the specific feed being requested. */
11
+
@required feed: atUri,
12
12
13
13
@minValue(1)
14
14
@maxValue(100)
···
21
21
@required
22
22
feed: app.bsky.feed.defs.SkeletonFeedPost[];
23
23
24
-
@doc("Unique identifier per request that may be passed back alongside interactions.")
24
+
/** Unique identifier per request that may be passed back alongside interactions. */
25
25
@maxLength(100)
26
26
reqId?: string;
27
27
};
28
28
}
29
+
30
+
// --- Externals ---
31
+
32
+
@external
33
+
namespace app.bsky.feed.defs {
34
+
model SkeletonFeedPost { }
35
+
}
+11
-4
packages/emitter/test/integration/atproto/input/app/bsky/feed/getLikes.tsp
+11
-4
packages/emitter/test/integration/atproto/input/app/bsky/feed/getLikes.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace app.bsky.feed.getLikes {
4
-
@doc("Get like records which reference a subject (by AT-URI and CID).")
4
+
/** Get like records which reference a subject (by AT-URI and CID). */
5
5
@query
6
6
op main(
7
-
@doc("AT-URI of the subject (eg, a post record).")
8
-
uri: atUri,
7
+
/** AT-URI of the subject (eg, a post record). */
8
+
@required uri: atUri,
9
9
10
-
@doc("CID of the subject record (aka, specific version of record), to filter likes.")
10
+
/** CID of the subject record (aka, specific version of record), to filter likes. */
11
11
cid?: cid,
12
12
13
13
@minValue(1)
···
28
28
@required actor: app.bsky.actor.defs.ProfileView;
29
29
}
30
30
}
31
+
32
+
// --- Externals ---
33
+
34
+
@external
35
+
namespace app.bsky.actor.defs {
36
+
model ProfileView { }
37
+
}
+10
-3
packages/emitter/test/integration/atproto/input/app/bsky/feed/getListFeed.tsp
+10
-3
packages/emitter/test/integration/atproto/input/app/bsky/feed/getListFeed.tsp
···
3
3
namespace app.bsky.feed.getListFeed {
4
4
model UnknownList {}
5
5
6
-
@doc("Get a feed of recent posts from a list (posts and reposts from any actors on the list). Does not require auth.")
6
+
/** Get a feed of recent posts from a list (posts and reposts from any actors on the list). Does not require auth. */
7
7
@query
8
8
@errors(UnknownList)
9
9
op main(
10
-
@doc("Reference (AT-URI) to the list record.")
11
-
list: atUri,
10
+
/** Reference (AT-URI) to the list record. */
11
+
@required list: atUri,
12
12
13
13
@minValue(1)
14
14
@maxValue(100)
···
20
20
@required feed: app.bsky.feed.defs.FeedViewPost[];
21
21
};
22
22
}
23
+
24
+
// --- Externals ---
25
+
26
+
@external
27
+
namespace app.bsky.feed.defs {
28
+
model FeedViewPost { }
29
+
}
+15
-5
packages/emitter/test/integration/atproto/input/app/bsky/feed/getPostThread.tsp
+15
-5
packages/emitter/test/integration/atproto/input/app/bsky/feed/getPostThread.tsp
···
3
3
namespace app.bsky.feed.getPostThread {
4
4
model NotFound {}
5
5
6
-
@doc("Get posts in a thread. Does not require auth, but additional metadata and filtering will be applied for authed requests.")
6
+
/** Get posts in a thread. Does not require auth, but additional metadata and filtering will be applied for authed requests. */
7
7
@query
8
8
@errors(NotFound)
9
9
op main(
10
-
@doc("Reference (AT-URI) to post record.")
11
-
uri: atUri,
10
+
/** Reference (AT-URI) to post record. */
11
+
@required uri: atUri,
12
12
13
-
@doc("How many levels of reply depth should be included in response.")
13
+
/** How many levels of reply depth should be included in response. */
14
14
@minValue(0)
15
15
@maxValue(1000)
16
16
depth?: int32 = 6,
17
17
18
-
@doc("How many levels of parent (and grandparent, etc) post to include.")
18
+
/** How many levels of parent (and grandparent, etc) post to include. */
19
19
@minValue(0)
20
20
@maxValue(1000)
21
21
parentHeight?: int32 = 80
···
26
26
threadgate?: app.bsky.feed.defs.ThreadgateView;
27
27
};
28
28
}
29
+
30
+
// --- Externals ---
31
+
32
+
@external
33
+
namespace app.bsky.feed.defs {
34
+
model ThreadViewPost { }
35
+
model NotFoundPost { }
36
+
model BlockedPost { }
37
+
model ThreadgateView { }
38
+
}
+10
-3
packages/emitter/test/integration/atproto/input/app/bsky/feed/getPosts.tsp
+10
-3
packages/emitter/test/integration/atproto/input/app/bsky/feed/getPosts.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace app.bsky.feed.getPosts {
4
-
@doc("Gets post views for a specified list of posts (by AT-URI). This is sometimes referred to as 'hydrating' a 'feed skeleton'.")
4
+
/** Gets post views for a specified list of posts (by AT-URI). This is sometimes referred to as 'hydrating' a 'feed skeleton'. */
5
5
@query
6
6
op main(
7
-
@doc("List of post AT-URIs to return hydrated views for.")
7
+
/** List of post AT-URIs to return hydrated views for. */
8
8
@maxItems(25)
9
-
uris: atUri[]
9
+
@required uris: atUri[]
10
10
): {
11
11
@required posts: app.bsky.feed.defs.PostView[];
12
12
};
13
13
}
14
+
15
+
// --- Externals ---
16
+
17
+
@external
18
+
namespace app.bsky.feed.defs {
19
+
model PostView { }
20
+
}
+11
-4
packages/emitter/test/integration/atproto/input/app/bsky/feed/getQuotes.tsp
+11
-4
packages/emitter/test/integration/atproto/input/app/bsky/feed/getQuotes.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace app.bsky.feed.getQuotes {
4
-
@doc("Get a list of quotes for a given post.")
4
+
/** Get a list of quotes for a given post. */
5
5
@query
6
6
op main(
7
-
@doc("Reference (AT-URI) of post record")
8
-
uri: atUri,
7
+
/** Reference (AT-URI) of post record */
8
+
@required uri: atUri,
9
9
10
-
@doc("If supplied, filters to quotes of specific version (by CID) of the post record.")
10
+
/** If supplied, filters to quotes of specific version (by CID) of the post record. */
11
11
cid?: cid,
12
12
13
13
@minValue(1)
···
22
22
@required posts: app.bsky.feed.defs.PostView[];
23
23
};
24
24
}
25
+
26
+
// --- Externals ---
27
+
28
+
@external
29
+
namespace app.bsky.feed.defs {
30
+
model PostView { }
31
+
}
+11
-4
packages/emitter/test/integration/atproto/input/app/bsky/feed/getRepostedBy.tsp
+11
-4
packages/emitter/test/integration/atproto/input/app/bsky/feed/getRepostedBy.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace app.bsky.feed.getRepostedBy {
4
-
@doc("Get a list of reposts for a given post.")
4
+
/** Get a list of reposts for a given post. */
5
5
@query
6
6
op main(
7
-
@doc("Reference (AT-URI) of post record")
8
-
uri: atUri,
7
+
/** Reference (AT-URI) of post record */
8
+
@required uri: atUri,
9
9
10
-
@doc("If supplied, filters to reposts of specific version (by CID) of the post record.")
10
+
/** If supplied, filters to reposts of specific version (by CID) of the post record. */
11
11
cid?: cid,
12
12
13
13
@minValue(1)
···
22
22
@required repostedBy: app.bsky.actor.defs.ProfileView[];
23
23
};
24
24
}
25
+
26
+
// --- Externals ---
27
+
28
+
@external
29
+
namespace app.bsky.actor.defs {
30
+
model ProfileView { }
31
+
}
+8
-1
packages/emitter/test/integration/atproto/input/app/bsky/feed/getSuggestedFeeds.tsp
+8
-1
packages/emitter/test/integration/atproto/input/app/bsky/feed/getSuggestedFeeds.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace app.bsky.feed.getSuggestedFeeds {
4
-
@doc("Get a list of suggested feeds (feed generators) for the requesting account.")
4
+
/** Get a list of suggested feeds (feed generators) for the requesting account. */
5
5
@query
6
6
op main(
7
7
@minValue(1)
···
14
14
@required feeds: app.bsky.feed.defs.GeneratorView[];
15
15
};
16
16
}
17
+
18
+
// --- Externals ---
19
+
20
+
@external
21
+
namespace app.bsky.feed.defs {
22
+
model GeneratorView { }
23
+
}
+9
-2
packages/emitter/test/integration/atproto/input/app/bsky/feed/getTimeline.tsp
+9
-2
packages/emitter/test/integration/atproto/input/app/bsky/feed/getTimeline.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace app.bsky.feed.getTimeline {
4
-
@doc("Get a view of the requesting account's home timeline. This is expected to be some form of reverse-chronological feed.")
4
+
/** Get a view of the requesting account's home timeline. This is expected to be some form of reverse-chronological feed. */
5
5
@query
6
6
op main(
7
-
@doc("Variant 'algorithm' for timeline. Implementation-specific. NOTE: most feed flexibility has been moved to feed generator mechanism.")
7
+
/** Variant 'algorithm' for timeline. Implementation-specific. NOTE: most feed flexibility has been moved to feed generator mechanism. */
8
8
algorithm?: string,
9
9
10
10
@minValue(1)
···
17
17
@required feed: app.bsky.feed.defs.FeedViewPost[];
18
18
};
19
19
}
20
+
21
+
// --- Externals ---
22
+
23
+
@external
24
+
namespace app.bsky.feed.defs {
25
+
model FeedViewPost { }
26
+
}
+8
-1
packages/emitter/test/integration/atproto/input/app/bsky/feed/like.tsp
+8
-1
packages/emitter/test/integration/atproto/input/app/bsky/feed/like.tsp
···
2
2
3
3
namespace app.bsky.feed.like {
4
4
@rec("tid")
5
-
@doc("Record declaring a 'like' of a piece of subject content.")
5
+
/** Record declaring a 'like' of a piece of subject content. */
6
6
model Main {
7
7
@required
8
8
subject: com.atproto.repo.strongRef.Main;
···
13
13
via?: com.atproto.repo.strongRef.Main;
14
14
}
15
15
}
16
+
17
+
// --- Externals ---
18
+
19
+
@external
20
+
namespace com.atproto.repo.strongRef {
21
+
model Main { }
22
+
}
+53
-11
packages/emitter/test/integration/atproto/input/app/bsky/feed/post.tsp
+53
-11
packages/emitter/test/integration/atproto/input/app/bsky/feed/post.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace app.bsky.feed.post {
4
-
@doc("Record containing a Bluesky post.")
4
+
/** Record containing a Bluesky post. */
5
5
@rec("tid")
6
6
model Main {
7
-
@doc("The primary post content. May be an empty string, if there are embeds.")
7
+
/** The primary post content. May be an empty string, if there are embeds. */
8
8
@maxGraphemes(300)
9
9
@maxLength(3000)
10
10
@required
11
11
text: string;
12
12
13
-
@doc("DEPRECATED: replaced by app.bsky.richtext.facet.")
13
+
/** DEPRECATED: replaced by app.bsky.richtext.facet. */
14
14
entities?: Entity[];
15
15
16
-
@doc("Annotations of text (mentions, URLs, hashtags, etc)")
16
+
/** Annotations of text (mentions, URLs, hashtags, etc) */
17
17
facets?: app.bsky.richtext.facet.Main[];
18
18
19
19
reply?: ReplyRef;
···
27
27
| unknown
28
28
);
29
29
30
-
@doc("Indicates human language of post primary text content.")
30
+
/** Indicates human language of post primary text content. */
31
31
@maxItems(3)
32
32
langs?: language[];
33
33
34
-
@doc("Self-label values for this post. Effectively content warnings.")
34
+
/** Self-label values for this post. Effectively content warnings. */
35
35
labels?: (com.atproto.label.defs.SelfLabels | unknown);
36
36
37
-
@doc("Additional hashtags, in addition to any included in post text and facets.")
37
+
/** Additional hashtags, in addition to any included in post text and facets. */
38
38
@maxItems(8)
39
39
tags?: PostTag[];
40
40
41
-
@doc("Client-declared timestamp when this post was originally created.")
41
+
/** Client-declared timestamp when this post was originally created. */
42
42
@required
43
43
createdAt: datetime;
44
44
}
···
48
48
@required parent: com.atproto.repo.strongRef.Main;
49
49
}
50
50
51
-
@doc("Deprecated: use facets instead.")
51
+
/** Deprecated: use facets instead. */
52
52
model Entity {
53
53
@required index: TextSlice;
54
54
55
-
@doc("Expected values are 'mention' and 'link'.")
55
+
/** Expected values are 'mention' and 'link'. */
56
56
@required
57
57
type: string;
58
58
59
59
@required value: string;
60
60
}
61
61
62
-
@doc("Deprecated. Use app.bsky.richtext instead -- A text segment. Start is inclusive, end is exclusive. Indices are for utf16-encoded strings.")
62
+
/** Deprecated. Use app.bsky.richtext instead -- A text segment. Start is inclusive, end is exclusive. Indices are for utf16-encoded strings. */
63
63
model TextSlice {
64
64
@minValue(0)
65
65
@required
···
74
74
@maxGraphemes(64)
75
75
@maxLength(640)
76
76
scalar PostTag extends string;
77
+
78
+
// --- Externals ---
79
+
80
+
@external
81
+
namespace app.bsky.richtext.facet {
82
+
model Main { }
83
+
}
84
+
85
+
@external
86
+
namespace app.bsky.embed.images {
87
+
model Main { }
88
+
}
89
+
90
+
@external
91
+
namespace app.bsky.embed.video {
92
+
model Main { }
93
+
}
94
+
95
+
@external
96
+
namespace app.bsky.embed.external {
97
+
model Main { }
98
+
}
99
+
100
+
@external
101
+
namespace app.bsky.embed.`record` {
102
+
model Main { }
103
+
}
104
+
105
+
@external
106
+
namespace app.bsky.embed.recordWithMedia {
107
+
model Main { }
108
+
}
109
+
110
+
@external
111
+
namespace com.atproto.label.defs {
112
+
model SelfLabels { }
113
+
}
114
+
115
+
@external
116
+
namespace com.atproto.repo.strongRef {
117
+
model Main { }
118
+
}
+5
-5
packages/emitter/test/integration/atproto/input/app/bsky/feed/postgate.tsp
+5
-5
packages/emitter/test/integration/atproto/input/app/bsky/feed/postgate.tsp
···
2
2
3
3
namespace app.bsky.feed.postgate {
4
4
@rec("tid")
5
-
@doc("Record defining interaction rules for a post. The record key (rkey) of the postgate record must match the record key of the post, and that record must be in the same repository.")
5
+
/** Record defining interaction rules for a post. The record key (rkey) of the postgate record must match the record key of the post, and that record must be in the same repository. */
6
6
model Main {
7
-
@doc("Reference (AT-URI) to the post record.")
7
+
/** Reference (AT-URI) to the post record. */
8
8
@required
9
9
post: atUri;
10
10
11
11
@required createdAt: datetime;
12
12
13
-
@doc("List of AT-URIs embedding this post that the author has detached from.")
13
+
/** List of AT-URIs embedding this post that the author has detached from. */
14
14
@maxItems(50)
15
15
detachedEmbeddingUris?: atUri[];
16
16
17
-
@doc("List of rules defining who can embed this post. If value is an empty array or is undefined, no particular rules apply and anyone can embed.")
17
+
/** List of rules defining who can embed this post. If value is an empty array or is undefined, no particular rules apply and anyone can embed. */
18
18
@maxItems(5)
19
19
embeddingRules?: (DisableRule | unknown)[];
20
20
}
21
21
22
-
@doc("Disables embedding of this post.")
22
+
/** Disables embedding of this post. */
23
23
model DisableRule {}
24
24
}
+8
-1
packages/emitter/test/integration/atproto/input/app/bsky/feed/repost.tsp
+8
-1
packages/emitter/test/integration/atproto/input/app/bsky/feed/repost.tsp
···
2
2
3
3
namespace app.bsky.feed.repost {
4
4
@rec("tid")
5
-
@doc("Record representing a 'repost' of an existing Bluesky post.")
5
+
/** Record representing a 'repost' of an existing Bluesky post. */
6
6
model Main {
7
7
@required subject: com.atproto.repo.strongRef.Main;
8
8
@required createdAt: datetime;
9
9
via?: com.atproto.repo.strongRef.Main;
10
10
}
11
11
}
12
+
13
+
// --- Externals ---
14
+
15
+
@external
16
+
namespace com.atproto.repo.strongRef {
17
+
model Main { }
18
+
}
+21
-14
packages/emitter/test/integration/atproto/input/app/bsky/feed/searchPosts.tsp
+21
-14
packages/emitter/test/integration/atproto/input/app/bsky/feed/searchPosts.tsp
···
7
7
namespace app.bsky.feed.searchPosts {
8
8
model BadQueryString {}
9
9
10
-
@doc("Find posts matching search criteria, returning views of those posts. Note that this API endpoint may require authentication (eg, not public) for some service providers and implementations.")
10
+
/** Find posts matching search criteria, returning views of those posts. Note that this API endpoint may require authentication (eg, not public) for some service providers and implementations. */
11
11
@query
12
12
@errors(BadQueryString)
13
13
op main(
14
-
@doc("Search query string; syntax, phrase, boolean, and faceting is unspecified, but Lucene query syntax is recommended.")
15
-
q: string,
14
+
/** Search query string; syntax, phrase, boolean, and faceting is unspecified, but Lucene query syntax is recommended. */
15
+
@required q: string,
16
16
17
-
@doc("Specifies the ranking order of results.")
17
+
/** Specifies the ranking order of results. */
18
18
sort?: "top" | "latest" | string = "latest",
19
19
20
-
@doc("Filter results for posts after the indicated datetime (inclusive). Expected to use 'sortAt' timestamp, which may not match 'createdAt'. Can be a datetime, or just an ISO date (YYYY-MM-DD).")
20
+
/** Filter results for posts after the indicated datetime (inclusive). Expected to use 'sortAt' timestamp, which may not match 'createdAt'. Can be a datetime, or just an ISO date (YYYY-MM-DD). */
21
21
since?: string,
22
22
23
-
@doc("Filter results for posts before the indicated datetime (not inclusive). Expected to use 'sortAt' timestamp, which may not match 'createdAt'. Can be a datetime, or just an ISO date (YYY-MM-DD).")
23
+
/** Filter results for posts before the indicated datetime (not inclusive). Expected to use 'sortAt' timestamp, which may not match 'createdAt'. Can be a datetime, or just an ISO date (YYY-MM-DD). */
24
24
until?: string,
25
25
26
-
@doc("Filter to posts which mention the given account. Handles are resolved to DID before query-time. Only matches rich-text facet mentions.")
26
+
/** Filter to posts which mention the given account. Handles are resolved to DID before query-time. Only matches rich-text facet mentions. */
27
27
mentions?: atIdentifier,
28
28
29
-
@doc("Filter to posts by the given account. Handles are resolved to DID before query-time.")
29
+
/** Filter to posts by the given account. Handles are resolved to DID before query-time. */
30
30
author?: atIdentifier,
31
31
32
-
@doc("Filter to posts in the given language. Expected to be based on post language field, though server may override language detection.")
32
+
/** Filter to posts in the given language. Expected to be based on post language field, though server may override language detection. */
33
33
lang?: language,
34
34
35
-
@doc("Filter to posts with URLs (facet links or embeds) linking to the given domain (hostname). Server may apply hostname normalization.")
35
+
/** Filter to posts with URLs (facet links or embeds) linking to the given domain (hostname). Server may apply hostname normalization. */
36
36
domain?: string,
37
37
38
-
@doc("Filter to posts with links (facet links or embeds) pointing to this URL. Server may apply URL normalization or fuzzy matching.")
38
+
/** Filter to posts with links (facet links or embeds) pointing to this URL. Server may apply URL normalization or fuzzy matching. */
39
39
url?: uri,
40
40
41
-
@doc("Filter to posts with the given tag (hashtag), based on rich-text facet or tag field. Do not include the hash (#) prefix. Multiple tags can be specified, with 'AND' matching.")
41
+
/** Filter to posts with the given tag (hashtag), based on rich-text facet or tag field. Do not include the hash (#) prefix. Multiple tags can be specified, with 'AND' matching. */
42
42
tag?: TagString[],
43
43
44
44
@minValue(1)
45
45
@maxValue(100)
46
46
limit?: int32 = 25,
47
47
48
-
@doc("Optional pagination mechanism; may not necessarily allow scrolling through entire result set.")
48
+
/** Optional pagination mechanism; may not necessarily allow scrolling through entire result set. */
49
49
cursor?: string
50
50
): {
51
51
cursor?: string;
52
52
53
-
@doc("Count of search hits. Optional, may be rounded/truncated, and may not be possible to paginate through all hits.")
53
+
/** Count of search hits. Optional, may be rounded/truncated, and may not be possible to paginate through all hits. */
54
54
hitsTotal?: int32;
55
55
56
56
@required posts: app.bsky.feed.defs.PostView[];
57
57
};
58
58
}
59
+
60
+
// --- Externals ---
61
+
62
+
@external
63
+
namespace app.bsky.feed.defs {
64
+
model PostView { }
65
+
}
+8
-1
packages/emitter/test/integration/atproto/input/app/bsky/feed/sendInteractions.tsp
+8
-1
packages/emitter/test/integration/atproto/input/app/bsky/feed/sendInteractions.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace app.bsky.feed.sendInteractions {
4
-
@doc("Send information about interactions with feed items back to the feed generator that served them.")
4
+
/** Send information about interactions with feed items back to the feed generator that served them. */
5
5
@procedure
6
6
op main(input: {
7
7
@required interactions: app.bsky.feed.defs.Interaction[];
8
8
}): {};
9
9
}
10
+
11
+
// --- Externals ---
12
+
13
+
@external
14
+
namespace app.bsky.feed.defs {
15
+
model Interaction { }
16
+
}
+8
-8
packages/emitter/test/integration/atproto/input/app/bsky/feed/threadgate.tsp
+8
-8
packages/emitter/test/integration/atproto/input/app/bsky/feed/threadgate.tsp
···
2
2
3
3
namespace app.bsky.feed.threadgate {
4
4
@rec("tid")
5
-
@doc("Record defining interaction gating rules for a thread (aka, reply controls). The record key (rkey) of the threadgate record must match the record key of the thread's root post, and that record must be in the same repository.")
5
+
/** Record defining interaction gating rules for a thread (aka, reply controls). The record key (rkey) of the threadgate record must match the record key of the thread's root post, and that record must be in the same repository. */
6
6
model Main {
7
-
@doc("Reference (AT-URI) to the post record.")
7
+
/** Reference (AT-URI) to the post record. */
8
8
@required
9
9
post: atUri;
10
10
11
-
@doc("List of rules defining who can reply to this post. If value is an empty array, no one can reply. If value is undefined, anyone can reply.")
11
+
/** List of rules defining who can reply to this post. If value is an empty array, no one can reply. If value is undefined, anyone can reply. */
12
12
@maxItems(5)
13
13
allow?: (MentionRule | FollowerRule | FollowingRule | ListRule | unknown)[];
14
14
15
15
@required createdAt: datetime;
16
16
17
-
@doc("List of hidden reply URIs.")
17
+
/** List of hidden reply URIs. */
18
18
@maxItems(50)
19
19
hiddenReplies?: atUri[];
20
20
}
21
21
22
-
@doc("Allow replies from actors mentioned in your post.")
22
+
/** Allow replies from actors mentioned in your post. */
23
23
model MentionRule {}
24
24
25
-
@doc("Allow replies from actors who follow you.")
25
+
/** Allow replies from actors who follow you. */
26
26
model FollowerRule {}
27
27
28
-
@doc("Allow replies from actors you follow.")
28
+
/** Allow replies from actors you follow. */
29
29
model FollowingRule {}
30
30
31
-
@doc("Allow replies from actors on a list.")
31
+
/** Allow replies from actors on a list. */
32
32
model ListRule {
33
33
@required list: atUri;
34
34
}
+2
-2
packages/emitter/test/integration/atproto/input/app/bsky/graph/block.tsp
+2
-2
packages/emitter/test/integration/atproto/input/app/bsky/graph/block.tsp
···
2
2
3
3
namespace app.bsky.graph.block {
4
4
@rec("tid")
5
-
@doc("Record declaring a 'block' relationship against another account. NOTE: blocks are public in Bluesky; see blog posts for details.")
5
+
/** Record declaring a 'block' relationship against another account. NOTE: blocks are public in Bluesky; see blog posts for details. */
6
6
model Main {
7
-
@doc("DID of the account to be blocked.")
7
+
/** DID of the account to be blocked. */
8
8
@required
9
9
subject: did;
10
10
+33
-11
packages/emitter/test/integration/atproto/input/app/bsky/graph/defs.tsp
+33
-11
packages/emitter/test/integration/atproto/input/app/bsky/graph/defs.tsp
···
97
97
98
98
union ListPurpose {
99
99
string,
100
-
101
-
Modlist: "app.bsky.graph.defs#modlist",
102
-
Curatelist: "app.bsky.graph.defs#curatelist",
103
-
Referencelist: "app.bsky.graph.defs#referencelist",
100
+
Modlist,
101
+
Curatelist,
102
+
Referencelist,
104
103
}
105
104
106
-
@doc("A list of actors to apply an aggregate moderation action (mute/block) on.")
105
+
/** A list of actors to apply an aggregate moderation action (mute/block) on. */
107
106
@token
108
107
model Modlist {}
109
108
110
-
@doc("A list of actors used for curation purposes such as list feeds or interaction gating.")
109
+
/** A list of actors used for curation purposes such as list feeds or interaction gating. */
111
110
@token
112
111
model Curatelist {}
113
112
114
-
@doc("A list of actors used for only for reference purposes such as within a starter pack.")
113
+
/** A list of actors used for only for reference purposes such as within a starter pack. */
115
114
@token
116
115
model Referencelist {}
117
116
···
120
119
blocked?: atUri;
121
120
}
122
121
123
-
@doc("indicates that a handle or DID could not be resolved")
122
+
/** indicates that a handle or DID could not be resolved */
124
123
model NotFoundActor {
125
124
@required actor: atIdentifier;
126
125
···
129
128
notFound: boolean = true;
130
129
}
131
130
132
-
@doc("lists the bi-directional graph relationships between one actor (not indicated in the object), and the target actors (the DID included in the object)")
131
+
/** lists the bi-directional graph relationships between one actor (not indicated in the object), and the target actors (the DID included in the object) */
133
132
model Relationship {
134
133
@required did: did;
135
134
136
-
@doc("if the actor follows this DID, this is the AT-URI of the follow record")
135
+
/** if the actor follows this DID, this is the AT-URI of the follow record */
137
136
following?: atUri;
138
137
139
-
@doc("if the actor is followed by this DID, contains the AT-URI of the follow record")
138
+
/** if the actor is followed by this DID, contains the AT-URI of the follow record */
140
139
followedBy?: atUri;
141
140
}
142
141
}
142
+
143
+
// --- Externals ---
144
+
145
+
@external
146
+
namespace com.atproto.label.defs {
147
+
model Label { }
148
+
}
149
+
150
+
@external
151
+
namespace app.bsky.actor.defs {
152
+
model ProfileView { }
153
+
model ProfileViewBasic { }
154
+
}
155
+
156
+
@external
157
+
namespace app.bsky.richtext.facet {
158
+
model Main { }
159
+
}
160
+
161
+
@external
162
+
namespace app.bsky.feed.defs {
163
+
model GeneratorView { }
164
+
}
+1
-1
packages/emitter/test/integration/atproto/input/app/bsky/graph/follow.tsp
+1
-1
packages/emitter/test/integration/atproto/input/app/bsky/graph/follow.tsp
···
2
2
3
3
namespace app.bsky.graph.follow {
4
4
@rec("tid")
5
-
@doc("Record declaring a social 'follow' relationship of another account. Duplicate follows will be ignored by the AppView.")
5
+
/** Record declaring a social 'follow' relationship of another account. Duplicate follows will be ignored by the AppView. */
6
6
model Main {
7
7
@required subject: did;
8
8
@required createdAt: datetime;
+8
-1
packages/emitter/test/integration/atproto/input/app/bsky/graph/getActorStarterPacks.tsp
+8
-1
packages/emitter/test/integration/atproto/input/app/bsky/graph/getActorStarterPacks.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace app.bsky.graph.getActorStarterPacks {
4
-
@doc("Get a list of starter packs created by the actor.")
4
+
/** Get a list of starter packs created by the actor. */
5
5
@query
6
6
op main(
7
7
@required actor: atIdentifier,
···
16
16
@required starterPacks: app.bsky.graph.defs.StarterPackViewBasic[];
17
17
};
18
18
}
19
+
20
+
// --- Externals ---
21
+
22
+
@external
23
+
namespace app.bsky.graph.defs {
24
+
model StarterPackViewBasic { }
25
+
}
+8
-1
packages/emitter/test/integration/atproto/input/app/bsky/graph/getBlocks.tsp
+8
-1
packages/emitter/test/integration/atproto/input/app/bsky/graph/getBlocks.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace app.bsky.graph.getBlocks {
4
-
@doc("Enumerates which accounts the requesting account is currently blocking. Requires auth.")
4
+
/** Enumerates which accounts the requesting account is currently blocking. Requires auth. */
5
5
@query
6
6
op main(
7
7
@minValue(1)
···
14
14
@required blocks: app.bsky.actor.defs.ProfileView[];
15
15
};
16
16
}
17
+
18
+
// --- Externals ---
19
+
20
+
@external
21
+
namespace app.bsky.actor.defs {
22
+
model ProfileView { }
23
+
}
+9
-2
packages/emitter/test/integration/atproto/input/app/bsky/graph/getFollowers.tsp
+9
-2
packages/emitter/test/integration/atproto/input/app/bsky/graph/getFollowers.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace app.bsky.graph.getFollowers {
4
-
@doc("Enumerates accounts which follow a specified account (actor).")
4
+
/** Enumerates accounts which follow a specified account (actor). */
5
5
@query
6
6
op main(
7
-
actor: atIdentifier,
7
+
@required actor: atIdentifier,
8
8
9
9
@minValue(1)
10
10
@maxValue(100)
···
17
17
@required followers: app.bsky.actor.defs.ProfileView[];
18
18
};
19
19
}
20
+
21
+
// --- Externals ---
22
+
23
+
@external
24
+
namespace app.bsky.actor.defs {
25
+
model ProfileView { }
26
+
}
+9
-2
packages/emitter/test/integration/atproto/input/app/bsky/graph/getFollows.tsp
+9
-2
packages/emitter/test/integration/atproto/input/app/bsky/graph/getFollows.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace app.bsky.graph.getFollows {
4
-
@doc("Enumerates accounts which a specified account (actor) follows.")
4
+
/** Enumerates accounts which a specified account (actor) follows. */
5
5
@query
6
6
op main(
7
-
actor: atIdentifier,
7
+
@required actor: atIdentifier,
8
8
9
9
@minValue(1)
10
10
@maxValue(100)
···
17
17
@required follows: app.bsky.actor.defs.ProfileView[];
18
18
};
19
19
}
20
+
21
+
// --- Externals ---
22
+
23
+
@external
24
+
namespace app.bsky.actor.defs {
25
+
model ProfileView { }
26
+
}
+9
-2
packages/emitter/test/integration/atproto/input/app/bsky/graph/getKnownFollowers.tsp
+9
-2
packages/emitter/test/integration/atproto/input/app/bsky/graph/getKnownFollowers.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace app.bsky.graph.getKnownFollowers {
4
-
@doc("Enumerates accounts which follow a specified account (actor) and are followed by the viewer.")
4
+
/** Enumerates accounts which follow a specified account (actor) and are followed by the viewer. */
5
5
@query
6
6
op main(
7
-
actor: atIdentifier,
7
+
@required actor: atIdentifier,
8
8
9
9
@minValue(1)
10
10
@maxValue(100)
···
17
17
@required followers: app.bsky.actor.defs.ProfileView[];
18
18
};
19
19
}
20
+
21
+
// --- Externals ---
22
+
23
+
@external
24
+
namespace app.bsky.actor.defs {
25
+
model ProfileView { }
26
+
}
+11
-3
packages/emitter/test/integration/atproto/input/app/bsky/graph/getList.tsp
+11
-3
packages/emitter/test/integration/atproto/input/app/bsky/graph/getList.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace app.bsky.graph.getList {
4
-
@doc("Gets a 'view' (with additional context) of a specified list.")
4
+
/** Gets a 'view' (with additional context) of a specified list. */
5
5
@query
6
6
op main(
7
-
@doc("Reference (AT-URI) of the list record to hydrate.")
8
-
list: atUri,
7
+
/** Reference (AT-URI) of the list record to hydrate. */
8
+
@required list: atUri,
9
9
10
10
@minValue(1)
11
11
@maxValue(100)
···
18
18
@required items: app.bsky.graph.defs.ListItemView[];
19
19
};
20
20
}
21
+
22
+
// --- Externals ---
23
+
24
+
@external
25
+
namespace app.bsky.graph.defs {
26
+
model ListView { }
27
+
model ListItemView { }
28
+
}
+8
-1
packages/emitter/test/integration/atproto/input/app/bsky/graph/getListBlocks.tsp
+8
-1
packages/emitter/test/integration/atproto/input/app/bsky/graph/getListBlocks.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace app.bsky.graph.getListBlocks {
4
-
@doc("Get mod lists that the requesting account (actor) is blocking. Requires auth.")
4
+
/** Get mod lists that the requesting account (actor) is blocking. Requires auth. */
5
5
@query
6
6
op main(
7
7
@minValue(1)
···
14
14
@required lists: app.bsky.graph.defs.ListView[];
15
15
};
16
16
}
17
+
18
+
// --- Externals ---
19
+
20
+
@external
21
+
namespace app.bsky.graph.defs {
22
+
model ListView { }
23
+
}
+8
-1
packages/emitter/test/integration/atproto/input/app/bsky/graph/getListMutes.tsp
+8
-1
packages/emitter/test/integration/atproto/input/app/bsky/graph/getListMutes.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace app.bsky.graph.getListMutes {
4
-
@doc("Enumerates mod lists that the requesting account (actor) currently has muted. Requires auth.")
4
+
/** Enumerates mod lists that the requesting account (actor) currently has muted. Requires auth. */
5
5
@query
6
6
op main(
7
7
@minValue(1)
···
14
14
@required lists: app.bsky.graph.defs.ListView[];
15
15
};
16
16
}
17
+
18
+
// --- Externals ---
19
+
20
+
@external
21
+
namespace app.bsky.graph.defs {
22
+
model ListView { }
23
+
}
+11
-4
packages/emitter/test/integration/atproto/input/app/bsky/graph/getLists.tsp
+11
-4
packages/emitter/test/integration/atproto/input/app/bsky/graph/getLists.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace app.bsky.graph.getLists {
4
-
@doc("Enumerates the lists created by a specified account (actor).")
4
+
/** Enumerates the lists created by a specified account (actor). */
5
5
@query
6
6
op main(
7
-
@doc("The account (actor) to enumerate lists from.")
8
-
actor: atIdentifier,
7
+
/** The account (actor) to enumerate lists from. */
8
+
@required actor: atIdentifier,
9
9
10
10
@minValue(1)
11
11
@maxValue(100)
···
13
13
14
14
cursor?: string,
15
15
16
-
@doc("Optional filter by list purpose. If not specified, all supported types are returned.")
16
+
/** Optional filter by list purpose. If not specified, all supported types are returned. */
17
17
purposes?: ("modlist" | "curatelist" | string)[]
18
18
): {
19
19
cursor?: string;
20
20
@required lists: app.bsky.graph.defs.ListView[];
21
21
};
22
22
}
23
+
24
+
// --- Externals ---
25
+
26
+
@external
27
+
namespace app.bsky.graph.defs {
28
+
model ListView { }
29
+
}
+12
-4
packages/emitter/test/integration/atproto/input/app/bsky/graph/getListsWithMembership.tsp
+12
-4
packages/emitter/test/integration/atproto/input/app/bsky/graph/getListsWithMembership.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace app.bsky.graph.getListsWithMembership {
4
-
@doc("Enumerates the lists created by the session user, and includes membership information about `actor` in those lists. Only supports curation and moderation lists (no reference lists, used in starter packs). Requires auth.")
4
+
/** Enumerates the lists created by the session user, and includes membership information about `actor` in those lists. Only supports curation and moderation lists (no reference lists, used in starter packs). Requires auth. */
5
5
@query
6
6
op main(
7
-
@doc("The account (actor) to check for membership.")
7
+
/** The account (actor) to check for membership. */
8
8
@required
9
9
actor: atIdentifier,
10
10
···
14
14
15
15
cursor?: string,
16
16
17
-
@doc("Optional filter by list purpose. If not specified, all supported types are returned.")
17
+
/** Optional filter by list purpose. If not specified, all supported types are returned. */
18
18
purposes?: ("modlist" | "curatelist" | string)[]
19
19
): {
20
20
cursor?: string;
21
21
@required listsWithMembership: ListWithMembership[];
22
22
};
23
23
24
-
@doc("A list and an optional list item indicating membership of a target user to that list.")
24
+
/** A list and an optional list item indicating membership of a target user to that list. */
25
25
model ListWithMembership {
26
26
@required list: app.bsky.graph.defs.ListView;
27
27
listItem?: app.bsky.graph.defs.ListItemView;
28
28
}
29
29
}
30
+
31
+
// --- Externals ---
32
+
33
+
@external
34
+
namespace app.bsky.graph.defs {
35
+
model ListView { }
36
+
model ListItemView { }
37
+
}
+8
-1
packages/emitter/test/integration/atproto/input/app/bsky/graph/getMutes.tsp
+8
-1
packages/emitter/test/integration/atproto/input/app/bsky/graph/getMutes.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace app.bsky.graph.getMutes {
4
-
@doc("Enumerates accounts that the requesting account (actor) currently has muted. Requires auth.")
4
+
/** Enumerates accounts that the requesting account (actor) currently has muted. Requires auth. */
5
5
@query
6
6
op main(
7
7
@minValue(1)
···
14
14
@required mutes: app.bsky.actor.defs.ProfileView[];
15
15
};
16
16
}
17
+
18
+
// --- Externals ---
19
+
20
+
@external
21
+
namespace app.bsky.actor.defs {
22
+
model ProfileView { }
23
+
}
+12
-4
packages/emitter/test/integration/atproto/input/app/bsky/graph/getRelationships.tsp
+12
-4
packages/emitter/test/integration/atproto/input/app/bsky/graph/getRelationships.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace app.bsky.graph.getRelationships {
4
-
@doc("Enumerates public relationships between one account, and a list of other accounts. Does not require auth.")
4
+
/** Enumerates public relationships between one account, and a list of other accounts. Does not require auth. */
5
5
@query
6
6
@errors(ActorNotFound)
7
7
op main(
8
-
@doc("Primary account requesting relationships for.")
8
+
/** Primary account requesting relationships for. */
9
9
@required
10
10
actor: atIdentifier,
11
11
12
-
@doc("List of 'other' accounts to be related back to the primary.")
12
+
/** List of 'other' accounts to be related back to the primary. */
13
13
@maxItems(30)
14
14
others?: atIdentifier[]
15
15
): {
···
23
23
)[];
24
24
};
25
25
26
-
@doc("the primary actor at-identifier could not be resolved")
26
+
/** the primary actor at-identifier could not be resolved */
27
27
model ActorNotFound {}
28
28
}
29
+
30
+
// --- Externals ---
31
+
32
+
@external
33
+
namespace app.bsky.graph.defs {
34
+
model Relationship { }
35
+
model NotFoundActor { }
36
+
}
+9
-2
packages/emitter/test/integration/atproto/input/app/bsky/graph/getStarterPack.tsp
+9
-2
packages/emitter/test/integration/atproto/input/app/bsky/graph/getStarterPack.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace app.bsky.graph.getStarterPack {
4
-
@doc("Gets a view of a starter pack.")
4
+
/** Gets a view of a starter pack. */
5
5
@query
6
6
op main(
7
-
@doc("Reference (AT-URI) of the starter pack record.")
7
+
/** Reference (AT-URI) of the starter pack record. */
8
8
@required
9
9
starterPack: atUri
10
10
): {
11
11
@required starterPack: app.bsky.graph.defs.StarterPackView;
12
12
};
13
13
}
14
+
15
+
// --- Externals ---
16
+
17
+
@external
18
+
namespace app.bsky.graph.defs {
19
+
model StarterPackView { }
20
+
}
+8
-1
packages/emitter/test/integration/atproto/input/app/bsky/graph/getStarterPacks.tsp
+8
-1
packages/emitter/test/integration/atproto/input/app/bsky/graph/getStarterPacks.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace app.bsky.graph.getStarterPacks {
4
-
@doc("Get views for a list of starter packs.")
4
+
/** Get views for a list of starter packs. */
5
5
@query
6
6
op main(
7
7
@maxItems(25)
···
11
11
@required starterPacks: app.bsky.graph.defs.StarterPackViewBasic[];
12
12
};
13
13
}
14
+
15
+
// --- Externals ---
16
+
17
+
@external
18
+
namespace app.bsky.graph.defs {
19
+
model StarterPackViewBasic { }
20
+
}
+11
-3
packages/emitter/test/integration/atproto/input/app/bsky/graph/getStarterPacksWithMembership.tsp
+11
-3
packages/emitter/test/integration/atproto/input/app/bsky/graph/getStarterPacksWithMembership.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace app.bsky.graph.getStarterPacksWithMembership {
4
-
@doc("Enumerates the starter packs created by the session user, and includes membership information about `actor` in those starter packs. Requires auth.")
4
+
/** Enumerates the starter packs created by the session user, and includes membership information about `actor` in those starter packs. Requires auth. */
5
5
@query
6
6
op main(
7
-
@doc("The account (actor) to check for membership.")
7
+
/** The account (actor) to check for membership. */
8
8
@required
9
9
actor: atIdentifier,
10
10
···
18
18
@required starterPacksWithMembership: StarterPackWithMembership[];
19
19
};
20
20
21
-
@doc("A starter pack and an optional list item indicating membership of a target user to that starter pack.")
21
+
/** A starter pack and an optional list item indicating membership of a target user to that starter pack. */
22
22
model StarterPackWithMembership {
23
23
@required starterPack: app.bsky.graph.defs.StarterPackView;
24
24
listItem?: app.bsky.graph.defs.ListItemView;
25
25
}
26
26
}
27
+
28
+
// --- Externals ---
29
+
30
+
@external
31
+
namespace app.bsky.graph.defs {
32
+
model StarterPackView { }
33
+
model ListItemView { }
34
+
}
+11
-4
packages/emitter/test/integration/atproto/input/app/bsky/graph/getSuggestedFollowsByActor.tsp
+11
-4
packages/emitter/test/integration/atproto/input/app/bsky/graph/getSuggestedFollowsByActor.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace app.bsky.graph.getSuggestedFollowsByActor {
4
-
@doc("Enumerates follows similar to a given account (actor). Expected use is to recommend additional accounts immediately after following one account.")
4
+
/** Enumerates follows similar to a given account (actor). Expected use is to recommend additional accounts immediately after following one account. */
5
5
@query
6
6
op main(
7
-
actor: atIdentifier
7
+
@required actor: atIdentifier
8
8
): {
9
9
@required
10
10
suggestions: app.bsky.actor.defs.ProfileView[];
11
11
12
-
@doc("If true, response has fallen-back to generic results, and is not scoped using relativeToDid")
12
+
/** If true, response has fallen-back to generic results, and is not scoped using relativeToDid */
13
13
isFallback?: boolean = false;
14
14
15
-
@doc("Snowflake for this recommendation, use when submitting recommendation events.")
15
+
/** Snowflake for this recommendation, use when submitting recommendation events. */
16
16
recId?: int32;
17
17
};
18
18
}
19
+
20
+
// --- Externals ---
21
+
22
+
@external
23
+
namespace app.bsky.actor.defs {
24
+
model ProfileView { }
25
+
}
+20
-3
packages/emitter/test/integration/atproto/input/app/bsky/graph/list.tsp
+20
-3
packages/emitter/test/integration/atproto/input/app/bsky/graph/list.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace app.bsky.graph.list {
4
-
@doc("Record representing a list of accounts (actors). Scope includes both moderation-oriented lists and curration-oriented lists.")
4
+
/** Record representing a list of accounts (actors). Scope includes both moderation-oriented lists and curration-oriented lists. */
5
5
@rec("tid")
6
6
model Main {
7
-
@doc("Display name for list; can not be empty.")
7
+
/** Display name for list; can not be empty. */
8
8
@minLength(1)
9
9
@maxLength(64)
10
10
@required
11
11
name: string;
12
12
13
-
@doc("Defines the purpose of the list (aka, moderation-oriented or curration-oriented)")
13
+
/** Defines the purpose of the list (aka, moderation-oriented or curration-oriented) */
14
14
@required
15
15
purpose: app.bsky.graph.defs.ListPurpose;
16
16
···
27
27
@required createdAt: datetime;
28
28
}
29
29
}
30
+
31
+
// --- Externals ---
32
+
33
+
@external
34
+
namespace app.bsky.graph.defs {
35
+
model ListPurpose { }
36
+
}
37
+
38
+
@external
39
+
namespace app.bsky.richtext.facet {
40
+
model Main { }
41
+
}
42
+
43
+
@external
44
+
namespace com.atproto.label.defs {
45
+
model SelfLabels { }
46
+
}
+2
-2
packages/emitter/test/integration/atproto/input/app/bsky/graph/listblock.tsp
+2
-2
packages/emitter/test/integration/atproto/input/app/bsky/graph/listblock.tsp
···
2
2
3
3
namespace app.bsky.graph.listblock {
4
4
@rec("tid")
5
-
@doc("Record representing a block relationship against an entire an entire list of accounts (actors).")
5
+
/** Record representing a block relationship against an entire an entire list of accounts (actors). */
6
6
model Main {
7
-
@doc("Reference (AT-URI) to the mod list record.")
7
+
/** Reference (AT-URI) to the mod list record. */
8
8
@required
9
9
subject: atUri;
10
10
+3
-3
packages/emitter/test/integration/atproto/input/app/bsky/graph/listitem.tsp
+3
-3
packages/emitter/test/integration/atproto/input/app/bsky/graph/listitem.tsp
···
2
2
3
3
namespace app.bsky.graph.listitem {
4
4
@rec("tid")
5
-
@doc("Record representing an account's inclusion on a specific list. The AppView will ignore duplicate listitem records.")
5
+
/** Record representing an account's inclusion on a specific list. The AppView will ignore duplicate listitem records. */
6
6
model Main {
7
-
@doc("The account which is included on the list.")
7
+
/** The account which is included on the list. */
8
8
@required
9
9
subject: did;
10
10
11
-
@doc("Reference (AT-URI) to the list record (app.bsky.graph.list).")
11
+
/** Reference (AT-URI) to the list record (app.bsky.graph.list). */
12
12
@required
13
13
list: atUri;
14
14
+1
-1
packages/emitter/test/integration/atproto/input/app/bsky/graph/muteActor.tsp
+1
-1
packages/emitter/test/integration/atproto/input/app/bsky/graph/muteActor.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace app.bsky.graph.muteActor {
4
-
@doc("Creates a mute relationship for the specified account. Mutes are private in Bluesky. Requires auth.")
4
+
/** Creates a mute relationship for the specified account. Mutes are private in Bluesky. Requires auth. */
5
5
@procedure
6
6
op main(input: {
7
7
@required actor: atIdentifier;
+1
-1
packages/emitter/test/integration/atproto/input/app/bsky/graph/muteActorList.tsp
+1
-1
packages/emitter/test/integration/atproto/input/app/bsky/graph/muteActorList.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace app.bsky.graph.muteActorList {
4
-
@doc("Creates a mute relationship for the specified list of accounts. Mutes are private in Bluesky. Requires auth.")
4
+
/** Creates a mute relationship for the specified list of accounts. Mutes are private in Bluesky. Requires auth. */
5
5
@procedure
6
6
op main(input: {
7
7
@required list: atUri;
+1
-1
packages/emitter/test/integration/atproto/input/app/bsky/graph/muteThread.tsp
+1
-1
packages/emitter/test/integration/atproto/input/app/bsky/graph/muteThread.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace app.bsky.graph.muteThread {
4
-
@doc("Mutes a thread preventing notifications from the thread and any of its children. Mutes are private in Bluesky. Requires auth.")
4
+
/** Mutes a thread preventing notifications from the thread and any of its children. Mutes are private in Bluesky. Requires auth. */
5
5
@procedure
6
6
op main(input: {
7
7
@required root: atUri;
+9
-2
packages/emitter/test/integration/atproto/input/app/bsky/graph/searchStarterPacks.tsp
+9
-2
packages/emitter/test/integration/atproto/input/app/bsky/graph/searchStarterPacks.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace app.bsky.graph.searchStarterPacks {
4
-
@doc("Find starter packs matching search criteria. Does not require auth.")
4
+
/** Find starter packs matching search criteria. Does not require auth. */
5
5
@query
6
6
op main(
7
-
@doc("Search query string. Syntax, phrase, boolean, and faceting is unspecified, but Lucene query syntax is recommended.")
7
+
/** Search query string. Syntax, phrase, boolean, and faceting is unspecified, but Lucene query syntax is recommended. */
8
8
@required
9
9
q: string,
10
10
···
18
18
@required starterPacks: app.bsky.graph.defs.StarterPackViewBasic[];
19
19
};
20
20
}
21
+
22
+
// --- Externals ---
23
+
24
+
@external
25
+
namespace app.bsky.graph.defs {
26
+
model StarterPackViewBasic { }
27
+
}
+10
-3
packages/emitter/test/integration/atproto/input/app/bsky/graph/starterpack.tsp
+10
-3
packages/emitter/test/integration/atproto/input/app/bsky/graph/starterpack.tsp
···
2
2
3
3
namespace app.bsky.graph.starterpack {
4
4
@rec("tid")
5
-
@doc("Record defining a starter pack of actors and feeds for new users.")
5
+
/** Record defining a starter pack of actors and feeds for new users. */
6
6
model Main {
7
-
@doc("Display name for starter pack; can not be empty.")
7
+
/** Display name for starter pack; can not be empty. */
8
8
@minLength(1)
9
9
@maxLength(500)
10
10
@maxGraphemes(50)
···
17
17
18
18
descriptionFacets?: app.bsky.richtext.facet.Main[];
19
19
20
-
@doc("Reference (AT-URI) to the list record.")
20
+
/** Reference (AT-URI) to the list record. */
21
21
@required
22
22
list: atUri;
23
23
···
33
33
uri: atUri;
34
34
}
35
35
}
36
+
37
+
// --- Externals ---
38
+
39
+
@external
40
+
namespace app.bsky.richtext.facet {
41
+
model Main { }
42
+
}
+1
-1
packages/emitter/test/integration/atproto/input/app/bsky/graph/unmuteActor.tsp
+1
-1
packages/emitter/test/integration/atproto/input/app/bsky/graph/unmuteActor.tsp
+1
-1
packages/emitter/test/integration/atproto/input/app/bsky/graph/unmuteActorList.tsp
+1
-1
packages/emitter/test/integration/atproto/input/app/bsky/graph/unmuteActorList.tsp
+1
-1
packages/emitter/test/integration/atproto/input/app/bsky/graph/unmuteThread.tsp
+1
-1
packages/emitter/test/integration/atproto/input/app/bsky/graph/unmuteThread.tsp
+5
-5
packages/emitter/test/integration/atproto/input/app/bsky/graph/verification.tsp
+5
-5
packages/emitter/test/integration/atproto/input/app/bsky/graph/verification.tsp
···
2
2
3
3
namespace app.bsky.graph.verification {
4
4
@rec("tid")
5
-
@doc("Record declaring a verification relationship between two accounts. Verifications are only considered valid by an app if issued by an account the app considers trusted.")
5
+
/** Record declaring a verification relationship between two accounts. Verifications are only considered valid by an app if issued by an account the app considers trusted. */
6
6
model Main {
7
-
@doc("DID of the subject the verification applies to.")
7
+
/** DID of the subject the verification applies to. */
8
8
@required
9
9
subject: did;
10
10
11
-
@doc("Handle of the subject the verification applies to at the moment of verifying, which might not be the same at the time of viewing. The verification is only valid if the current handle matches the one at the time of verifying.")
11
+
/** Handle of the subject the verification applies to at the moment of verifying, which might not be the same at the time of viewing. The verification is only valid if the current handle matches the one at the time of verifying. */
12
12
@required
13
13
handle: handle;
14
14
15
-
@doc("Display name of the subject the verification applies to at the moment of verifying, which might not be the same at the time of viewing. The verification is only valid if the current displayName matches the one at the time of verifying.")
15
+
/** Display name of the subject the verification applies to at the moment of verifying, which might not be the same at the time of viewing. The verification is only valid if the current displayName matches the one at the time of verifying. */
16
16
@required
17
17
displayName: string;
18
18
19
-
@doc("Date of when the verification was created.")
19
+
/** Date of when the verification was created. */
20
20
@required
21
21
createdAt: datetime;
22
22
}
+25
-5
packages/emitter/test/integration/atproto/input/app/bsky/labeler/defs.tsp
+25
-5
packages/emitter/test/integration/atproto/input/app/bsky/labeler/defs.tsp
···
31
31
32
32
labels?: com.atproto.label.defs.Label[];
33
33
34
-
@doc("The set of report reason 'codes' which are in-scope for this service to review and action. These usually align to policy categories. If not defined (distinct from empty array), all reason types are allowed.")
34
+
/** The set of report reason 'codes' which are in-scope for this service to review and action. These usually align to policy categories. If not defined (distinct from empty array), all reason types are allowed. */
35
35
reasonTypes?: com.atproto.moderation.defs.ReasonType[];
36
36
37
-
@doc("The set of subject types (account, record, etc) this service accepts reports on.")
37
+
/** The set of subject types (account, record, etc) this service accepts reports on. */
38
38
subjectTypes?: com.atproto.moderation.defs.SubjectType[];
39
39
40
-
@doc("Set of record types (collection NSIDs) which can be reported to this service. If not defined (distinct from empty array), default is any record type.")
40
+
/** Set of record types (collection NSIDs) which can be reported to this service. If not defined (distinct from empty array), default is any record type. */
41
41
subjectCollections?: nsid[];
42
42
}
43
43
···
46
46
}
47
47
48
48
model LabelerPolicies {
49
-
@doc("The label values which this labeler publishes. May include global or custom labels.")
49
+
/** The label values which this labeler publishes. May include global or custom labels. */
50
50
@required
51
51
labelValues: com.atproto.label.defs.LabelValue[];
52
52
53
-
@doc("Label values created by this labeler and scoped exclusively to it. Labels defined here will override global label definitions for this labeler.")
53
+
/** Label values created by this labeler and scoped exclusively to it. Labels defined here will override global label definitions for this labeler. */
54
54
labelValueDefinitions?: com.atproto.label.defs.LabelValueDefinition[];
55
55
}
56
56
}
57
+
58
+
// --- Externals ---
59
+
60
+
@external
61
+
namespace app.bsky.actor.defs {
62
+
model ProfileView { }
63
+
}
64
+
65
+
@external
66
+
namespace com.atproto.label.defs {
67
+
model Label { }
68
+
model LabelValue { }
69
+
model LabelValueDefinition { }
70
+
}
71
+
72
+
@external
73
+
namespace com.atproto.moderation.defs {
74
+
model ReasonType { }
75
+
model SubjectType { }
76
+
}
+9
-1
packages/emitter/test/integration/atproto/input/app/bsky/labeler/getServices.tsp
+9
-1
packages/emitter/test/integration/atproto/input/app/bsky/labeler/getServices.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace app.bsky.labeler.getServices {
4
-
@doc("Get information about a list of labeler services.")
4
+
/** Get information about a list of labeler services. */
5
5
@query
6
6
op main(
7
7
@required dids: did[],
···
15
15
)[];
16
16
};
17
17
}
18
+
19
+
// --- Externals ---
20
+
21
+
@external
22
+
namespace app.bsky.labeler.defs {
23
+
model LabelerView { }
24
+
model LabelerViewDetailed { }
25
+
}
+22
-4
packages/emitter/test/integration/atproto/input/app/bsky/labeler/service.tsp
+22
-4
packages/emitter/test/integration/atproto/input/app/bsky/labeler/service.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace app.bsky.labeler.service {
4
-
@doc("A declaration of the existence of labeler service.")
4
+
/** A declaration of the existence of labeler service. */
5
5
@rec("literal:self")
6
6
model Main {
7
7
@required policies: app.bsky.labeler.defs.LabelerPolicies;
···
10
10
11
11
@required createdAt: datetime;
12
12
13
-
@doc("The set of report reason 'codes' which are in-scope for this service to review and action. These usually align to policy categories. If not defined (distinct from empty array), all reason types are allowed.")
13
+
/** The set of report reason 'codes' which are in-scope for this service to review and action. These usually align to policy categories. If not defined (distinct from empty array), all reason types are allowed. */
14
14
reasonTypes?: com.atproto.moderation.defs.ReasonType[];
15
15
16
-
@doc("The set of subject types (account, record, etc) this service accepts reports on.")
16
+
/** The set of subject types (account, record, etc) this service accepts reports on. */
17
17
subjectTypes?: com.atproto.moderation.defs.SubjectType[];
18
18
19
-
@doc("Set of record types (collection NSIDs) which can be reported to this service. If not defined (distinct from empty array), default is any record type.")
19
+
/** Set of record types (collection NSIDs) which can be reported to this service. If not defined (distinct from empty array), default is any record type. */
20
20
subjectCollections?: nsid[];
21
21
}
22
22
}
23
+
24
+
// --- Externals ---
25
+
26
+
@external
27
+
namespace app.bsky.labeler.defs {
28
+
model LabelerPolicies { }
29
+
}
30
+
31
+
@external
32
+
namespace com.atproto.label.defs {
33
+
model SelfLabels { }
34
+
}
35
+
36
+
@external
37
+
namespace com.atproto.moderation.defs {
38
+
model ReasonType { }
39
+
model SubjectType { }
40
+
}
+2
-2
packages/emitter/test/integration/atproto/input/app/bsky/notification/declaration.tsp
+2
-2
packages/emitter/test/integration/atproto/input/app/bsky/notification/declaration.tsp
···
2
2
3
3
namespace app.bsky.notification.declaration {
4
4
@rec("literal:self")
5
-
@doc("A declaration of the user's choices related to notifications that can be produced by them.")
5
+
/** A declaration of the user's choices related to notifications that can be produced by them. */
6
6
model Main {
7
-
@doc("A declaration of the user's preference for allowing activity subscriptions from other users. Absence of a record implies 'followers'.")
7
+
/** A declaration of the user's preference for allowing activity subscriptions from other users. Absence of a record implies 'followers'. */
8
8
@required
9
9
allowSubscriptions: "followers" | "mutuals" | "none" | string;
10
10
}
+1
-1
packages/emitter/test/integration/atproto/input/app/bsky/notification/defs.tsp
+1
-1
packages/emitter/test/integration/atproto/input/app/bsky/notification/defs.tsp
···
40
40
@required reply: boolean;
41
41
}
42
42
43
-
@doc("Object used to store activity subscription data in stash.")
43
+
/** Object used to store activity subscription data in stash. */
44
44
model SubjectActivitySubscription {
45
45
@required subject: did;
46
46
@required activitySubscription: ActivitySubscription;
+8
-1
packages/emitter/test/integration/atproto/input/app/bsky/notification/getPreferences.tsp
+8
-1
packages/emitter/test/integration/atproto/input/app/bsky/notification/getPreferences.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace app.bsky.notification.getPreferences {
4
-
@doc("Get notification-related preferences for an account. Requires auth.")
4
+
/** Get notification-related preferences for an account. Requires auth. */
5
5
@query
6
6
op main(): {
7
7
@required preferences: app.bsky.notification.defs.Preferences;
8
8
};
9
9
}
10
+
11
+
// --- Externals ---
12
+
13
+
@external
14
+
namespace app.bsky.notification.defs {
15
+
model Preferences { }
16
+
}
+1
-1
packages/emitter/test/integration/atproto/input/app/bsky/notification/getUnreadCount.tsp
+1
-1
packages/emitter/test/integration/atproto/input/app/bsky/notification/getUnreadCount.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace app.bsky.notification.getUnreadCount {
4
-
@doc("Count the number of unread notifications for the requesting account. Requires auth.")
4
+
/** Count the number of unread notifications for the requesting account. Requires auth. */
5
5
@query
6
6
op main(
7
7
priority?: boolean,
+8
-1
packages/emitter/test/integration/atproto/input/app/bsky/notification/listActivitySubscriptions.tsp
+8
-1
packages/emitter/test/integration/atproto/input/app/bsky/notification/listActivitySubscriptions.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace app.bsky.notification.listActivitySubscriptions {
4
-
@doc("Enumerate all accounts to which the requesting account is subscribed to receive notifications for. Requires auth.")
4
+
/** Enumerate all accounts to which the requesting account is subscribed to receive notifications for. Requires auth. */
5
5
@query
6
6
op main(
7
7
@minValue(1)
···
14
14
@required subscriptions: app.bsky.actor.defs.ProfileView[];
15
15
};
16
16
}
17
+
18
+
// --- Externals ---
19
+
20
+
@external
21
+
namespace app.bsky.actor.defs {
22
+
model ProfileView { }
23
+
}
+16
-4
packages/emitter/test/integration/atproto/input/app/bsky/notification/listNotifications.tsp
+16
-4
packages/emitter/test/integration/atproto/input/app/bsky/notification/listNotifications.tsp
···
1
1
import "@typelex/emitter";
2
2
3
-
@doc("A reason that matches the reason property of #notification.")
3
+
/** A reason that matches the reason property of #notification. */
4
4
scalar ReasonString extends string;
5
5
6
6
namespace app.bsky.notification.listNotifications {
7
-
@doc("Enumerate notifications for the requesting account. Requires auth.")
7
+
/** Enumerate notifications for the requesting account. Requires auth. */
8
8
@query
9
9
op main(
10
-
@doc("Notification reasons to include in response.")
10
+
/** Notification reasons to include in response. */
11
11
reasons?: ReasonString[],
12
12
13
13
@minValue(1)
···
29
29
@required cid: cid;
30
30
@required author: app.bsky.actor.defs.ProfileView;
31
31
32
-
@doc("The reason why this notification was delivered - e.g. your post was liked, or you received a new follower.")
32
+
/** The reason why this notification was delivered - e.g. your post was liked, or you received a new follower. */
33
33
@required
34
34
reason: "like" | "repost" | "follow" | "mention" | "reply" | "quote" | "starterpack-joined" | "verified" | "unverified" | "like-via-repost" | "repost-via-repost" | "subscribed-post" | string;
35
35
···
40
40
labels?: com.atproto.label.defs.Label[];
41
41
};
42
42
}
43
+
44
+
// --- Externals ---
45
+
46
+
@external
47
+
namespace app.bsky.actor.defs {
48
+
model ProfileView { }
49
+
}
50
+
51
+
@external
52
+
namespace com.atproto.label.defs {
53
+
model Label { }
54
+
}
+8
-1
packages/emitter/test/integration/atproto/input/app/bsky/notification/putActivitySubscription.tsp
+8
-1
packages/emitter/test/integration/atproto/input/app/bsky/notification/putActivitySubscription.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace app.bsky.notification.putActivitySubscription {
4
-
@doc("Puts an activity subscription entry. The key should be omitted for creation and provided for updates. Requires auth.")
4
+
/** Puts an activity subscription entry. The key should be omitted for creation and provided for updates. Requires auth. */
5
5
@procedure
6
6
op main(input: {
7
7
@required subject: did;
···
13
13
activitySubscription?: app.bsky.notification.defs.ActivitySubscription;
14
14
};
15
15
}
16
+
17
+
// --- Externals ---
18
+
19
+
@external
20
+
namespace app.bsky.notification.defs {
21
+
model ActivitySubscription { }
22
+
}
+1
-1
packages/emitter/test/integration/atproto/input/app/bsky/notification/putPreferences.tsp
+1
-1
packages/emitter/test/integration/atproto/input/app/bsky/notification/putPreferences.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace app.bsky.notification.putPreferences {
4
-
@doc("Set notification-related preferences for an account. Requires auth.")
4
+
/** Set notification-related preferences for an account. Requires auth. */
5
5
@procedure
6
6
op main(input: {
7
7
@required priority: boolean;
+11
-1
packages/emitter/test/integration/atproto/input/app/bsky/notification/putPreferencesV2.tsp
+11
-1
packages/emitter/test/integration/atproto/input/app/bsky/notification/putPreferencesV2.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace app.bsky.notification.putPreferencesV2 {
4
-
@doc("Set notification-related preferences for an account. Requires auth.")
4
+
/** Set notification-related preferences for an account. Requires auth. */
5
5
@procedure
6
6
op main(input: {
7
7
chat?: app.bsky.notification.defs.ChatPreference;
···
21
21
@required preferences: app.bsky.notification.defs.Preferences;
22
22
};
23
23
}
24
+
25
+
// --- Externals ---
26
+
27
+
@external
28
+
namespace app.bsky.notification.defs {
29
+
model ChatPreference { }
30
+
model FilterablePreference { }
31
+
model Preference { }
32
+
model Preferences { }
33
+
}
+2
-2
packages/emitter/test/integration/atproto/input/app/bsky/notification/registerPush.tsp
+2
-2
packages/emitter/test/integration/atproto/input/app/bsky/notification/registerPush.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace app.bsky.notification.registerPush {
4
-
@doc("Register to receive push notifications, via a specified service, for the requesting account. Requires auth.")
4
+
/** Register to receive push notifications, via a specified service, for the requesting account. Requires auth. */
5
5
@procedure
6
6
op main(input: {
7
7
@required serviceDid: did;
···
9
9
@required platform: "ios" | "android" | "web" | string;
10
10
@required appId: string;
11
11
12
-
@doc("Set to true when the actor is age restricted")
12
+
/** Set to true when the actor is age restricted */
13
13
ageRestricted?: boolean;
14
14
}): void;
15
15
}
+1
-1
packages/emitter/test/integration/atproto/input/app/bsky/notification/unregisterPush.tsp
+1
-1
packages/emitter/test/integration/atproto/input/app/bsky/notification/unregisterPush.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace app.bsky.notification.unregisterPush {
4
-
@doc("The inverse of registerPush - inform a specified service that push notifications should no longer be sent to the given token for the requesting account. Requires auth.")
4
+
/** The inverse of registerPush - inform a specified service that push notifications should no longer be sent to the given token for the requesting account. Requires auth. */
5
5
@procedure
6
6
op main(input: {
7
7
@required serviceDid: did;
+1
-1
packages/emitter/test/integration/atproto/input/app/bsky/notification/updateSeen.tsp
+1
-1
packages/emitter/test/integration/atproto/input/app/bsky/notification/updateSeen.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace app.bsky.notification.updateSeen {
4
-
@doc("Notify server that the requesting account has seen notifications. Requires auth.")
4
+
/** Notify server that the requesting account has seen notifications. Requires auth. */
5
5
@procedure
6
6
op main(input: {
7
7
@required seenAt: datetime;
+5
-5
packages/emitter/test/integration/atproto/input/app/bsky/richtext/facet.tsp
+5
-5
packages/emitter/test/integration/atproto/input/app/bsky/richtext/facet.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace app.bsky.richtext.facet {
4
-
@doc("Annotation of a sub-string within rich text.")
4
+
/** Annotation of a sub-string within rich text. */
5
5
model Main {
6
6
@required index: ByteSlice;
7
7
8
8
@required features: (Mention | Link | Tag | unknown)[];
9
9
}
10
10
11
-
@doc("Facet feature for mention of another account. The text is usually a handle, including a '@' prefix, but the facet reference is a DID.")
11
+
/** Facet feature for mention of another account. The text is usually a handle, including a `@` prefix, but the facet reference is a DID. */
12
12
model Mention {
13
13
@required did: did;
14
14
}
15
15
16
-
@doc("Facet feature for a URL. The text URL may have been simplified or truncated, but the facet reference should be a complete URL.")
16
+
/** Facet feature for a URL. The text URL may have been simplified or truncated, but the facet reference should be a complete URL. */
17
17
model Link {
18
18
@required uri: uri;
19
19
}
20
20
21
-
@doc("Facet feature for a hashtag. The text usually includes a '#' prefix, but the facet reference should not (except in the case of 'double hash tags').")
21
+
/** Facet feature for a hashtag. The text usually includes a `#` prefix, but the facet reference should not (except in the case of 'double hash tags'). */
22
22
model Tag {
23
23
@maxLength(640)
24
24
@maxGraphemes(64)
···
26
26
tag: string;
27
27
}
28
28
29
-
@doc("Specifies the sub-string range a facet feature applies to. Start index is inclusive, end index is exclusive. Indices are zero-indexed, counting bytes of the UTF-8 encoded text. NOTE: some languages, like Javascript, use UTF-16 or Unicode codepoints for string slice indexing; in these languages, convert to byte arrays before working with facets.")
29
+
/** Specifies the sub-string range a facet feature applies to. Start index is inclusive, end index is exclusive. Indices are zero-indexed, counting bytes of the UTF-8 encoded text. NOTE: some languages, like Javascript, use UTF-16 or Unicode codepoints for string slice indexing; in these languages, convert to byte arrays before working with facets. */
30
30
model ByteSlice {
31
31
@minValue(0)
32
32
@required
+30
-17
packages/emitter/test/integration/atproto/input/app/bsky/unspecced/defs.tsp
+30
-17
packages/emitter/test/integration/atproto/input/app/bsky/unspecced/defs.tsp
···
45
45
model ThreadItemPost {
46
46
@required post: app.bsky.feed.defs.PostView;
47
47
48
-
@doc("This post has more parents that were not present in the response. This is just a boolean, without the number of parents.")
48
+
/** This post has more parents that were not present in the response. This is just a boolean, without the number of parents. */
49
49
@required
50
50
moreParents: boolean;
51
51
52
-
@doc("This post has more replies that were not present in the response. This is a numeric value, which is best-effort and might not be accurate.")
52
+
/** This post has more replies that were not present in the response. This is a numeric value, which is best-effort and might not be accurate. */
53
53
@required
54
54
moreReplies: integer;
55
55
56
-
@doc("This post is part of a contiguous thread by the OP from the thread root. Many different OP threads can happen in the same thread.")
56
+
/** This post is part of a contiguous thread by the OP from the thread root. Many different OP threads can happen in the same thread. */
57
57
@required
58
58
opThread: boolean;
59
59
60
-
@doc("The threadgate created by the author indicates this post as a reply to be hidden for everyone consuming the thread.")
60
+
/** The threadgate created by the author indicates this post as a reply to be hidden for everyone consuming the thread. */
61
61
@required
62
62
hiddenByThreadgate: boolean;
63
63
64
-
@doc("This is by an account muted by the viewer requesting it.")
64
+
/** This is by an account muted by the viewer requesting it. */
65
65
@required
66
66
mutedByViewer: boolean;
67
67
}
···
74
74
@required author: app.bsky.feed.defs.BlockedAuthor;
75
75
}
76
76
77
-
@doc("The computed state of the age assurance process, returned to the user in question on certain authenticated requests.")
77
+
/** The computed state of the age assurance process, returned to the user in question on certain authenticated requests. */
78
78
model AgeAssuranceState {
79
-
@doc("The timestamp when this state was last updated.")
79
+
/** The timestamp when this state was last updated. */
80
80
lastInitiatedAt?: datetime;
81
81
82
-
@doc("The status of the age assurance process.")
82
+
/** The status of the age assurance process. */
83
83
@required
84
84
status: "unknown" | "pending" | "assured" | "blocked" | string;
85
85
}
86
86
87
-
@doc("Object used to store age assurance data in stash.")
87
+
/** Object used to store age assurance data in stash. */
88
88
model AgeAssuranceEvent {
89
-
@doc("The date and time of this write operation.")
89
+
/** The date and time of this write operation. */
90
90
@required
91
91
createdAt: datetime;
92
92
93
-
@doc("The status of the age assurance process.")
93
+
/** The status of the age assurance process. */
94
94
@required
95
95
status: "unknown" | "pending" | "assured" | string;
96
96
97
-
@doc("The unique identifier for this instance of the age assurance flow, in UUID format.")
97
+
/** The unique identifier for this instance of the age assurance flow, in UUID format. */
98
98
@required
99
99
attemptId: string;
100
100
101
-
@doc("The email used for AA.")
101
+
/** The email used for AA. */
102
102
email?: string;
103
103
104
-
@doc("The IP address used when initiating the AA flow.")
104
+
/** The IP address used when initiating the AA flow. */
105
105
initIp?: string;
106
106
107
-
@doc("The user agent used when initiating the AA flow.")
107
+
/** The user agent used when initiating the AA flow. */
108
108
initUa?: string;
109
109
110
-
@doc("The IP address used when completing the AA flow.")
110
+
/** The IP address used when completing the AA flow. */
111
111
completeIp?: string;
112
112
113
-
@doc("The user agent used when completing the AA flow.")
113
+
/** The user agent used when completing the AA flow. */
114
114
completeUa?: string;
115
115
}
116
116
}
117
+
118
+
// --- Externals ---
119
+
120
+
@external
121
+
namespace app.bsky.actor.defs {
122
+
model ProfileViewBasic { }
123
+
}
124
+
125
+
@external
126
+
namespace app.bsky.feed.defs {
127
+
model PostView { }
128
+
model BlockedAuthor { }
129
+
}
+8
-1
packages/emitter/test/integration/atproto/input/app/bsky/unspecced/getAgeAssuranceState.tsp
+8
-1
packages/emitter/test/integration/atproto/input/app/bsky/unspecced/getAgeAssuranceState.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace app.bsky.unspecced.getAgeAssuranceState {
4
-
@doc("Returns the current state of the age assurance process for an account. This is used to check if the user has completed age assurance or if further action is required.")
4
+
/** Returns the current state of the age assurance process for an account. This is used to check if the user has completed age assurance or if further action is required. */
5
5
@query
6
6
op main(): app.bsky.unspecced.defs.AgeAssuranceState;
7
7
}
8
+
9
+
// --- Externals ---
10
+
11
+
@external
12
+
namespace app.bsky.unspecced.defs {
13
+
model AgeAssuranceState { }
14
+
}
+1
-1
packages/emitter/test/integration/atproto/input/app/bsky/unspecced/getConfig.tsp
+1
-1
packages/emitter/test/integration/atproto/input/app/bsky/unspecced/getConfig.tsp
+8
-1
packages/emitter/test/integration/atproto/input/app/bsky/unspecced/getOnboardingSuggestedStarterPacks.tsp
+8
-1
packages/emitter/test/integration/atproto/input/app/bsky/unspecced/getOnboardingSuggestedStarterPacks.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace app.bsky.unspecced.getOnboardingSuggestedStarterPacks {
4
-
@doc("Get a list of suggested starterpacks for onboarding")
4
+
/** Get a list of suggested starterpacks for onboarding */
5
5
@query
6
6
op main(
7
7
@minValue(1)
···
11
11
@required starterPacks: app.bsky.graph.defs.StarterPackView[];
12
12
};
13
13
}
14
+
15
+
// --- Externals ---
16
+
17
+
@external
18
+
namespace app.bsky.graph.defs {
19
+
model StarterPackView { }
20
+
}
+2
-2
packages/emitter/test/integration/atproto/input/app/bsky/unspecced/getOnboardingSuggestedStarterPacksSkeleton.tsp
+2
-2
packages/emitter/test/integration/atproto/input/app/bsky/unspecced/getOnboardingSuggestedStarterPacksSkeleton.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace app.bsky.unspecced.getOnboardingSuggestedStarterPacksSkeleton {
4
-
@doc("Get a skeleton of suggested starterpacks for onboarding. Intended to be called and hydrated by app.bsky.unspecced.getOnboardingSuggestedStarterPacks")
4
+
/** Get a skeleton of suggested starterpacks for onboarding. Intended to be called and hydrated by app.bsky.unspecced.getOnboardingSuggestedStarterPacks */
5
5
@query
6
6
op main(
7
-
@doc("DID of the account making the request (not included for public/unauthenticated queries).")
7
+
/** DID of the account making the request (not included for public/unauthenticated queries). */
8
8
viewer?: did,
9
9
10
10
@minValue(1)
+8
-1
packages/emitter/test/integration/atproto/input/app/bsky/unspecced/getPopularFeedGenerators.tsp
+8
-1
packages/emitter/test/integration/atproto/input/app/bsky/unspecced/getPopularFeedGenerators.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace app.bsky.unspecced.getPopularFeedGenerators {
4
-
@doc("An unspecced view of globally popular feed generators.")
4
+
/** An unspecced view of globally popular feed generators. */
5
5
@query
6
6
op main(
7
7
@minValue(1)
···
15
15
@required feeds: app.bsky.feed.defs.GeneratorView[];
16
16
};
17
17
}
18
+
19
+
// --- Externals ---
20
+
21
+
@external
22
+
namespace app.bsky.feed.defs {
23
+
model GeneratorView { }
24
+
}
+12
-5
packages/emitter/test/integration/atproto/input/app/bsky/unspecced/getPostThreadOtherV2.tsp
+12
-5
packages/emitter/test/integration/atproto/input/app/bsky/unspecced/getPostThreadOtherV2.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace app.bsky.unspecced.getPostThreadOtherV2 {
4
-
@doc("(NOTE: this endpoint is under development and WILL change without notice. Don't use it until it is moved out of `unspecced` or your application WILL break) Get additional posts under a thread e.g. replies hidden by threadgate. Based on an anchor post at any depth of the tree, returns top-level replies below that anchor. It does not include ancestors nor the anchor itself. This should be called after exhausting `app.bsky.unspecced.getPostThreadV2`. Does not require auth, but additional metadata and filtering will be applied for authed requests.")
4
+
/** (NOTE: this endpoint is under development and WILL change without notice. Don't use it until it is moved out of `unspecced` or your application WILL break) Get additional posts under a thread e.g. replies hidden by threadgate. Based on an anchor post at any depth of the tree, returns top-level replies below that anchor. It does not include ancestors nor the anchor itself. This should be called after exhausting `app.bsky.unspecced.getPostThreadV2`. Does not require auth, but additional metadata and filtering will be applied for authed requests. */
5
5
@query
6
6
op main(
7
-
@doc("Reference (AT-URI) to post record. This is the anchor post.")
7
+
/** Reference (AT-URI) to post record. This is the anchor post. */
8
8
@required
9
9
anchor: atUri,
10
10
11
-
@doc("Whether to prioritize posts from followed users. It only has effect when the user is authenticated.")
11
+
/** Whether to prioritize posts from followed users. It only has effect when the user is authenticated. */
12
12
prioritizeFollowedUsers?: boolean = false
13
13
): {
14
-
@doc("A flat list of other thread items. The depth of each item is indicated by the depth property inside the item.")
14
+
/** A flat list of other thread items. The depth of each item is indicated by the depth property inside the item. */
15
15
@required
16
16
thread: ThreadItem[];
17
17
};
···
19
19
model ThreadItem {
20
20
@required uri: atUri;
21
21
22
-
@doc("The nesting level of this item in the thread. Depth 0 means the anchor item. Items above have negative depths, items below have positive depths.")
22
+
/** The nesting level of this item in the thread. Depth 0 means the anchor item. Items above have negative depths, items below have positive depths. */
23
23
@required
24
24
depth: integer;
25
25
26
26
@required value: (app.bsky.unspecced.defs.ThreadItemPost | unknown);
27
27
}
28
28
}
29
+
30
+
// --- Externals ---
31
+
32
+
@external
33
+
namespace app.bsky.unspecced.defs {
34
+
model ThreadItemPost { }
35
+
}
+25
-10
packages/emitter/test/integration/atproto/input/app/bsky/unspecced/getPostThreadV2.tsp
+25
-10
packages/emitter/test/integration/atproto/input/app/bsky/unspecced/getPostThreadV2.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace app.bsky.unspecced.getPostThreadV2 {
4
-
@doc("(NOTE: this endpoint is under development and WILL change without notice. Don't use it until it is moved out of `unspecced` or your application WILL break) Get posts in a thread. It is based in an anchor post at any depth of the tree, and returns posts above it (recursively resolving the parent, without further branching to their replies) and below it (recursive replies, with branching to their replies). Does not require auth, but additional metadata and filtering will be applied for authed requests.")
4
+
/** (NOTE: this endpoint is under development and WILL change without notice. Don't use it until it is moved out of `unspecced` or your application WILL break) Get posts in a thread. It is based in an anchor post at any depth of the tree, and returns posts above it (recursively resolving the parent, without further branching to their replies) and below it (recursive replies, with branching to their replies). Does not require auth, but additional metadata and filtering will be applied for authed requests. */
5
5
@query
6
6
op main(
7
-
@doc("Reference (AT-URI) to post record. This is the anchor post, and the thread will be built around it. It can be any post in the tree, not necessarily a root post.")
7
+
/** Reference (AT-URI) to post record. This is the anchor post, and the thread will be built around it. It can be any post in the tree, not necessarily a root post. */
8
8
@required
9
9
anchor: atUri,
10
10
11
-
@doc("Whether to include parents above the anchor.")
11
+
/** Whether to include parents above the anchor. */
12
12
above?: boolean = true,
13
13
14
-
@doc("How many levels of replies to include below the anchor.")
14
+
/** How many levels of replies to include below the anchor. */
15
15
@minValue(0)
16
16
@maxValue(20)
17
17
below?: int32 = 6,
18
18
19
-
@doc("Maximum of replies to include at each level of the thread, except for the direct replies to the anchor, which are (NOTE: currently, during unspecced phase) all returned (NOTE: later they might be paginated).")
19
+
/** Maximum of replies to include at each level of the thread, except for the direct replies to the anchor, which are (NOTE: currently, during unspecced phase) all returned (NOTE: later they might be paginated). */
20
20
@minValue(0)
21
21
@maxValue(100)
22
22
branchingFactor?: int32 = 10,
23
23
24
-
@doc("Whether to prioritize posts from followed users. It only has effect when the user is authenticated.")
24
+
/** Whether to prioritize posts from followed users. It only has effect when the user is authenticated. */
25
25
prioritizeFollowedUsers?: boolean = false,
26
26
27
-
@doc("Sorting for the thread replies.")
27
+
/** Sorting for the thread replies. */
28
28
sort?: "newest" | "oldest" | "top" | string = "oldest"
29
29
): {
30
-
@doc("A flat list of thread items. The depth of each item is indicated by the depth property inside the item.")
30
+
/** A flat list of thread items. The depth of each item is indicated by the depth property inside the item. */
31
31
@required
32
32
thread: ThreadItem[];
33
33
34
34
threadgate?: app.bsky.feed.defs.ThreadgateView;
35
35
36
-
@doc("Whether this thread has additional replies. If true, a call can be made to the `getPostThreadOtherV2` endpoint to retrieve them.")
36
+
/** Whether this thread has additional replies. If true, a call can be made to the `getPostThreadOtherV2` endpoint to retrieve them. */
37
37
@required
38
38
hasOtherReplies: boolean;
39
39
};
···
41
41
model ThreadItem {
42
42
@required uri: atUri;
43
43
44
-
@doc("The nesting level of this item in the thread. Depth 0 means the anchor item. Items above have negative depths, items below have positive depths.")
44
+
/** The nesting level of this item in the thread. Depth 0 means the anchor item. Items above have negative depths, items below have positive depths. */
45
45
@required
46
46
depth: integer;
47
47
···
55
55
);
56
56
}
57
57
}
58
+
59
+
// --- Externals ---
60
+
61
+
@external
62
+
namespace app.bsky.feed.defs {
63
+
model ThreadgateView { }
64
+
}
65
+
66
+
@external
67
+
namespace app.bsky.unspecced.defs {
68
+
model ThreadItemPost { }
69
+
model ThreadItemNoUnauthenticated { }
70
+
model ThreadItemNotFound { }
71
+
model ThreadItemBlocked { }
72
+
}
+8
-1
packages/emitter/test/integration/atproto/input/app/bsky/unspecced/getSuggestedFeeds.tsp
+8
-1
packages/emitter/test/integration/atproto/input/app/bsky/unspecced/getSuggestedFeeds.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace app.bsky.unspecced.getSuggestedFeeds {
4
-
@doc("Get a list of suggested feeds")
4
+
/** Get a list of suggested feeds */
5
5
@query
6
6
op main(
7
7
@minValue(1)
···
11
11
@required feeds: app.bsky.feed.defs.GeneratorView[];
12
12
};
13
13
}
14
+
15
+
// --- Externals ---
16
+
17
+
@external
18
+
namespace app.bsky.feed.defs {
19
+
model GeneratorView { }
20
+
}
+2
-2
packages/emitter/test/integration/atproto/input/app/bsky/unspecced/getSuggestedFeedsSkeleton.tsp
+2
-2
packages/emitter/test/integration/atproto/input/app/bsky/unspecced/getSuggestedFeedsSkeleton.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace app.bsky.unspecced.getSuggestedFeedsSkeleton {
4
-
@doc("Get a skeleton of suggested feeds. Intended to be called and hydrated by app.bsky.unspecced.getSuggestedFeeds")
4
+
/** Get a skeleton of suggested feeds. Intended to be called and hydrated by app.bsky.unspecced.getSuggestedFeeds */
5
5
@query
6
6
op main(
7
-
@doc("DID of the account making the request (not included for public/unauthenticated queries).")
7
+
/** DID of the account making the request (not included for public/unauthenticated queries). */
8
8
viewer?: did,
9
9
10
10
@minValue(1)
+8
-1
packages/emitter/test/integration/atproto/input/app/bsky/unspecced/getSuggestedStarterPacks.tsp
+8
-1
packages/emitter/test/integration/atproto/input/app/bsky/unspecced/getSuggestedStarterPacks.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace app.bsky.unspecced.getSuggestedStarterPacks {
4
-
@doc("Get a list of suggested starterpacks")
4
+
/** Get a list of suggested starterpacks */
5
5
@query
6
6
op main(
7
7
@minValue(1)
···
11
11
@required starterPacks: app.bsky.graph.defs.StarterPackView[];
12
12
};
13
13
}
14
+
15
+
// --- Externals ---
16
+
17
+
@external
18
+
namespace app.bsky.graph.defs {
19
+
model StarterPackView { }
20
+
}
+2
-2
packages/emitter/test/integration/atproto/input/app/bsky/unspecced/getSuggestedStarterPacksSkeleton.tsp
+2
-2
packages/emitter/test/integration/atproto/input/app/bsky/unspecced/getSuggestedStarterPacksSkeleton.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace app.bsky.unspecced.getSuggestedStarterPacksSkeleton {
4
-
@doc("Get a skeleton of suggested starterpacks. Intended to be called and hydrated by app.bsky.unspecced.getSuggestedStarterpacks")
4
+
/** Get a skeleton of suggested starterpacks. Intended to be called and hydrated by app.bsky.unspecced.getSuggestedStarterpacks */
5
5
@query
6
6
op main(
7
-
@doc("DID of the account making the request (not included for public/unauthenticated queries).")
7
+
/** DID of the account making the request (not included for public/unauthenticated queries). */
8
8
viewer?: did,
9
9
10
10
@minValue(1)
+9
-2
packages/emitter/test/integration/atproto/input/app/bsky/unspecced/getSuggestedUsers.tsp
+9
-2
packages/emitter/test/integration/atproto/input/app/bsky/unspecced/getSuggestedUsers.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace app.bsky.unspecced.getSuggestedUsers {
4
-
@doc("Get a list of suggested users")
4
+
/** Get a list of suggested users */
5
5
@query
6
6
op main(
7
-
@doc("Category of users to get suggestions for.")
7
+
/** Category of users to get suggestions for. */
8
8
category?: string,
9
9
10
10
@minValue(1)
···
14
14
@required actors: app.bsky.actor.defs.ProfileView[];
15
15
};
16
16
}
17
+
18
+
// --- Externals ---
19
+
20
+
@external
21
+
namespace app.bsky.actor.defs {
22
+
model ProfileView { }
23
+
}
+3
-3
packages/emitter/test/integration/atproto/input/app/bsky/unspecced/getSuggestedUsersSkeleton.tsp
+3
-3
packages/emitter/test/integration/atproto/input/app/bsky/unspecced/getSuggestedUsersSkeleton.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace app.bsky.unspecced.getSuggestedUsersSkeleton {
4
-
@doc("Get a skeleton of suggested users. Intended to be called and hydrated by app.bsky.unspecced.getSuggestedUsers")
4
+
/** Get a skeleton of suggested users. Intended to be called and hydrated by app.bsky.unspecced.getSuggestedUsers */
5
5
@query
6
6
op main(
7
-
@doc("DID of the account making the request (not included for public/unauthenticated queries).")
7
+
/** DID of the account making the request (not included for public/unauthenticated queries). */
8
8
viewer?: did,
9
9
10
-
@doc("Category of users to get suggestions for.")
10
+
/** Category of users to get suggestions for. */
11
11
category?: string,
12
12
13
13
@minValue(1)
+12
-5
packages/emitter/test/integration/atproto/input/app/bsky/unspecced/getSuggestionsSkeleton.tsp
+12
-5
packages/emitter/test/integration/atproto/input/app/bsky/unspecced/getSuggestionsSkeleton.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace app.bsky.unspecced.getSuggestionsSkeleton {
4
-
@doc("Get a skeleton of suggested actors. Intended to be called and then hydrated through app.bsky.actor.getSuggestions")
4
+
/** Get a skeleton of suggested actors. Intended to be called and then hydrated through app.bsky.actor.getSuggestions */
5
5
@query
6
6
op main(
7
-
@doc("DID of the account making the request (not included for public/unauthenticated queries). Used to boost followed accounts in ranking.")
7
+
/** DID of the account making the request (not included for public/unauthenticated queries). Used to boost followed accounts in ranking. */
8
8
viewer?: did,
9
9
10
10
@minValue(1)
···
13
13
14
14
cursor?: string,
15
15
16
-
@doc("DID of the account to get suggestions relative to. If not provided, suggestions will be based on the viewer.")
16
+
/** DID of the account to get suggestions relative to. If not provided, suggestions will be based on the viewer. */
17
17
relativeToDid?: did
18
18
): {
19
19
cursor?: string;
20
20
@required actors: app.bsky.unspecced.defs.SkeletonSearchActor[];
21
21
22
-
@doc("DID of the account these suggestions are relative to. If this is returned undefined, suggestions are based on the viewer.")
22
+
/** DID of the account these suggestions are relative to. If this is returned undefined, suggestions are based on the viewer. */
23
23
relativeToDid?: did;
24
24
25
-
@doc("Snowflake for this recommendation, use when submitting recommendation events.")
25
+
/** Snowflake for this recommendation, use when submitting recommendation events. */
26
26
recId?: integer;
27
27
};
28
28
}
29
+
30
+
// --- Externals ---
31
+
32
+
@external
33
+
namespace app.bsky.unspecced.defs {
34
+
model SkeletonSearchActor { }
35
+
}
+1
-1
packages/emitter/test/integration/atproto/input/app/bsky/unspecced/getTaggedSuggestions.tsp
+1
-1
packages/emitter/test/integration/atproto/input/app/bsky/unspecced/getTaggedSuggestions.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace app.bsky.unspecced.getTaggedSuggestions {
4
-
@doc("Get a list of suggestions (feeds and users) tagged with categories")
4
+
/** Get a list of suggestions (feeds and users) tagged with categories */
5
5
@query
6
6
op main(): {
7
7
@required suggestions: Suggestion[];
+9
-2
packages/emitter/test/integration/atproto/input/app/bsky/unspecced/getTrendingTopics.tsp
+9
-2
packages/emitter/test/integration/atproto/input/app/bsky/unspecced/getTrendingTopics.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace app.bsky.unspecced.getTrendingTopics {
4
-
@doc("Get a list of trending topics")
4
+
/** Get a list of trending topics */
5
5
@query
6
6
op main(
7
-
@doc("DID of the account making the request (not included for public/unauthenticated queries). Used to boost followed accounts in ranking.")
7
+
/** DID of the account making the request (not included for public/unauthenticated queries). Used to boost followed accounts in ranking. */
8
8
viewer?: did,
9
9
10
10
@minValue(1)
···
15
15
@required suggested: app.bsky.unspecced.defs.TrendingTopic[];
16
16
};
17
17
}
18
+
19
+
// --- Externals ---
20
+
21
+
@external
22
+
namespace app.bsky.unspecced.defs {
23
+
model TrendingTopic { }
24
+
}
+8
-1
packages/emitter/test/integration/atproto/input/app/bsky/unspecced/getTrends.tsp
+8
-1
packages/emitter/test/integration/atproto/input/app/bsky/unspecced/getTrends.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace app.bsky.unspecced.getTrends {
4
-
@doc("Get the current trends on the network")
4
+
/** Get the current trends on the network */
5
5
@query
6
6
op main(
7
7
@minValue(1)
···
11
11
@required trends: app.bsky.unspecced.defs.TrendView[];
12
12
};
13
13
}
14
+
15
+
// --- Externals ---
16
+
17
+
@external
18
+
namespace app.bsky.unspecced.defs {
19
+
model TrendView { }
20
+
}
+9
-2
packages/emitter/test/integration/atproto/input/app/bsky/unspecced/getTrendsSkeleton.tsp
+9
-2
packages/emitter/test/integration/atproto/input/app/bsky/unspecced/getTrendsSkeleton.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace app.bsky.unspecced.getTrendsSkeleton {
4
-
@doc("Get the skeleton of trends on the network. Intended to be called and then hydrated through app.bsky.unspecced.getTrends")
4
+
/** Get the skeleton of trends on the network. Intended to be called and then hydrated through app.bsky.unspecced.getTrends */
5
5
@query
6
6
op main(
7
-
@doc("DID of the account making the request (not included for public/unauthenticated queries).")
7
+
/** DID of the account making the request (not included for public/unauthenticated queries). */
8
8
viewer?: did,
9
9
10
10
@minValue(1)
···
14
14
@required trends: app.bsky.unspecced.defs.SkeletonTrend[];
15
15
};
16
16
}
17
+
18
+
// --- Externals ---
19
+
20
+
@external
21
+
namespace app.bsky.unspecced.defs {
22
+
model SkeletonTrend { }
23
+
}
+11
-4
packages/emitter/test/integration/atproto/input/app/bsky/unspecced/initAgeAssurance.tsp
+11
-4
packages/emitter/test/integration/atproto/input/app/bsky/unspecced/initAgeAssurance.tsp
···
5
5
model DidTooLong {}
6
6
model InvalidInitiation {}
7
7
8
-
@doc("Initiate age assurance for an account. This is a one-time action that will start the process of verifying the user's age.")
8
+
/** Initiate age assurance for an account. This is a one-time action that will start the process of verifying the user's age. */
9
9
@procedure
10
10
@errors(InvalidEmail, DidTooLong, InvalidInitiation)
11
11
op main(input: {
12
-
@doc("The user's email address to receive assurance instructions.")
12
+
/** The user's email address to receive assurance instructions. */
13
13
@required
14
14
email: string;
15
15
16
-
@doc("The user's preferred language for communication during the assurance process.")
16
+
/** The user's preferred language for communication during the assurance process. */
17
17
@required
18
18
language: string;
19
19
20
-
@doc("An ISO 3166-1 alpha-2 code of the user's location.")
20
+
/** An ISO 3166-1 alpha-2 code of the user's location. */
21
21
@required
22
22
countryCode: string;
23
23
}): app.bsky.unspecced.defs.AgeAssuranceState;
24
24
}
25
+
26
+
// --- Externals ---
27
+
28
+
@external
29
+
namespace app.bsky.unspecced.defs {
30
+
model AgeAssuranceState { }
31
+
}
+14
-7
packages/emitter/test/integration/atproto/input/app/bsky/unspecced/searchActorsSkeleton.tsp
+14
-7
packages/emitter/test/integration/atproto/input/app/bsky/unspecced/searchActorsSkeleton.tsp
···
3
3
namespace app.bsky.unspecced.searchActorsSkeleton {
4
4
model BadQueryString {}
5
5
6
-
@doc("Backend Actors (profile) search, returns only skeleton.")
6
+
/** Backend Actors (profile) search, returns only skeleton. */
7
7
@query
8
8
@errors(BadQueryString)
9
9
op main(
10
-
@doc("Search query string; syntax, phrase, boolean, and faceting is unspecified, but Lucene query syntax is recommended. For typeahead search, only simple term match is supported, not full syntax.")
11
-
q: string,
10
+
/** Search query string; syntax, phrase, boolean, and faceting is unspecified, but Lucene query syntax is recommended. For typeahead search, only simple term match is supported, not full syntax. */
11
+
@required q: string,
12
12
13
-
@doc("DID of the account making the request (not included for public/unauthenticated queries). Used to boost followed accounts in ranking.")
13
+
/** DID of the account making the request (not included for public/unauthenticated queries). Used to boost followed accounts in ranking. */
14
14
viewer?: did,
15
15
16
-
@doc("If true, acts as fast/simple 'typeahead' query.")
16
+
/** If true, acts as fast/simple 'typeahead' query. */
17
17
typeahead?: boolean,
18
18
19
19
@minValue(1)
20
20
@maxValue(100)
21
21
limit?: integer = 25,
22
22
23
-
@doc("Optional pagination mechanism; may not necessarily allow scrolling through entire result set.")
23
+
/** Optional pagination mechanism; may not necessarily allow scrolling through entire result set. */
24
24
cursor?: string
25
25
): {
26
26
cursor?: string;
27
27
28
-
@doc("Count of search hits. Optional, may be rounded/truncated, and may not be possible to paginate through all hits.")
28
+
/** Count of search hits. Optional, may be rounded/truncated, and may not be possible to paginate through all hits. */
29
29
hitsTotal?: integer;
30
30
31
31
@required actors: app.bsky.unspecced.defs.SkeletonSearchActor[];
32
32
};
33
33
}
34
+
35
+
// --- Externals ---
36
+
37
+
@external
38
+
namespace app.bsky.unspecced.defs {
39
+
model SkeletonSearchActor { }
40
+
}
+22
-15
packages/emitter/test/integration/atproto/input/app/bsky/unspecced/searchPostsSkeleton.tsp
+22
-15
packages/emitter/test/integration/atproto/input/app/bsky/unspecced/searchPostsSkeleton.tsp
···
7
7
namespace app.bsky.unspecced.searchPostsSkeleton {
8
8
model BadQueryString {}
9
9
10
-
@doc("Backend Posts search, returns only skeleton")
10
+
/** Backend Posts search, returns only skeleton */
11
11
@query
12
12
@errors(BadQueryString)
13
13
op main(
14
-
@doc("Search query string; syntax, phrase, boolean, and faceting is unspecified, but Lucene query syntax is recommended.")
15
-
q: string,
14
+
/** Search query string; syntax, phrase, boolean, and faceting is unspecified, but Lucene query syntax is recommended. */
15
+
@required q: string,
16
16
17
-
@doc("Specifies the ranking order of results.")
17
+
/** Specifies the ranking order of results. */
18
18
sort?: "top" | "latest" | string = "latest",
19
19
20
-
@doc("Filter results for posts after the indicated datetime (inclusive). Expected to use 'sortAt' timestamp, which may not match 'createdAt'. Can be a datetime, or just an ISO date (YYYY-MM-DD).")
20
+
/** Filter results for posts after the indicated datetime (inclusive). Expected to use 'sortAt' timestamp, which may not match 'createdAt'. Can be a datetime, or just an ISO date (YYYY-MM-DD). */
21
21
since?: string,
22
22
23
-
@doc("Filter results for posts before the indicated datetime (not inclusive). Expected to use 'sortAt' timestamp, which may not match 'createdAt'. Can be a datetime, or just an ISO date (YYY-MM-DD).")
23
+
/** Filter results for posts before the indicated datetime (not inclusive). Expected to use 'sortAt' timestamp, which may not match 'createdAt'. Can be a datetime, or just an ISO date (YYY-MM-DD). */
24
24
until?: string,
25
25
26
-
@doc("Filter to posts which mention the given account. Handles are resolved to DID before query-time. Only matches rich-text facet mentions.")
26
+
/** Filter to posts which mention the given account. Handles are resolved to DID before query-time. Only matches rich-text facet mentions. */
27
27
mentions?: atIdentifier,
28
28
29
-
@doc("Filter to posts by the given account. Handles are resolved to DID before query-time.")
29
+
/** Filter to posts by the given account. Handles are resolved to DID before query-time. */
30
30
author?: atIdentifier,
31
31
32
-
@doc("Filter to posts in the given language. Expected to be based on post language field, though server may override language detection.")
32
+
/** Filter to posts in the given language. Expected to be based on post language field, though server may override language detection. */
33
33
lang?: language,
34
34
35
-
@doc("Filter to posts with URLs (facet links or embeds) linking to the given domain (hostname). Server may apply hostname normalization.")
35
+
/** Filter to posts with URLs (facet links or embeds) linking to the given domain (hostname). Server may apply hostname normalization. */
36
36
domain?: string,
37
37
38
-
@doc("Filter to posts with links (facet links or embeds) pointing to this URL. Server may apply URL normalization or fuzzy matching.")
38
+
/** Filter to posts with links (facet links or embeds) pointing to this URL. Server may apply URL normalization or fuzzy matching. */
39
39
url?: uri,
40
40
41
-
@doc("Filter to posts with the given tag (hashtag), based on rich-text facet or tag field. Do not include the hash (#) prefix. Multiple tags can be specified, with 'AND' matching.")
41
+
/** Filter to posts with the given tag (hashtag), based on rich-text facet or tag field. Do not include the hash (#) prefix. Multiple tags can be specified, with 'AND' matching. */
42
42
tag?: SkeletonSearchTagString[],
43
43
44
-
@doc("DID of the account making the request (not included for public/unauthenticated queries). Used for 'from:me' queries.")
44
+
/** DID of the account making the request (not included for public/unauthenticated queries). Used for 'from:me' queries. */
45
45
viewer?: did,
46
46
47
47
@minValue(1)
48
48
@maxValue(100)
49
49
limit?: integer = 25,
50
50
51
-
@doc("Optional pagination mechanism; may not necessarily allow scrolling through entire result set.")
51
+
/** Optional pagination mechanism; may not necessarily allow scrolling through entire result set. */
52
52
cursor?: string
53
53
): {
54
54
cursor?: string;
55
55
56
-
@doc("Count of search hits. Optional, may be rounded/truncated, and may not be possible to paginate through all hits.")
56
+
/** Count of search hits. Optional, may be rounded/truncated, and may not be possible to paginate through all hits. */
57
57
hitsTotal?: integer;
58
58
59
59
@required posts: app.bsky.unspecced.defs.SkeletonSearchPost[];
60
60
};
61
61
}
62
+
63
+
// --- Externals ---
64
+
65
+
@external
66
+
namespace app.bsky.unspecced.defs {
67
+
model SkeletonSearchPost { }
68
+
}
+13
-6
packages/emitter/test/integration/atproto/input/app/bsky/unspecced/searchStarterPacksSkeleton.tsp
+13
-6
packages/emitter/test/integration/atproto/input/app/bsky/unspecced/searchStarterPacksSkeleton.tsp
···
3
3
namespace app.bsky.unspecced.searchStarterPacksSkeleton {
4
4
model BadQueryString {}
5
5
6
-
@doc("Backend Starter Pack search, returns only skeleton.")
6
+
/** Backend Starter Pack search, returns only skeleton. */
7
7
@query
8
8
@errors(BadQueryString)
9
9
op main(
10
-
@doc("Search query string; syntax, phrase, boolean, and faceting is unspecified, but Lucene query syntax is recommended.")
11
-
q: string,
10
+
/** Search query string; syntax, phrase, boolean, and faceting is unspecified, but Lucene query syntax is recommended. */
11
+
@required q: string,
12
12
13
-
@doc("DID of the account making the request (not included for public/unauthenticated queries).")
13
+
/** DID of the account making the request (not included for public/unauthenticated queries). */
14
14
viewer?: did,
15
15
16
16
@minValue(1)
17
17
@maxValue(100)
18
18
limit?: integer = 25,
19
19
20
-
@doc("Optional pagination mechanism; may not necessarily allow scrolling through entire result set.")
20
+
/** Optional pagination mechanism; may not necessarily allow scrolling through entire result set. */
21
21
cursor?: string
22
22
): {
23
23
cursor?: string;
24
24
25
-
@doc("Count of search hits. Optional, may be rounded/truncated, and may not be possible to paginate through all hits.")
25
+
/** Count of search hits. Optional, may be rounded/truncated, and may not be possible to paginate through all hits. */
26
26
hitsTotal?: integer;
27
27
28
28
@required starterPacks: app.bsky.unspecced.defs.SkeletonSearchStarterPack[];
29
29
};
30
30
}
31
+
32
+
// --- Externals ---
33
+
34
+
@external
35
+
namespace app.bsky.unspecced.defs {
36
+
model SkeletonSearchStarterPack { }
37
+
}
+2
-2
packages/emitter/test/integration/atproto/input/app/bsky/video/defs.tsp
+2
-2
packages/emitter/test/integration/atproto/input/app/bsky/video/defs.tsp
···
5
5
@required jobId: string;
6
6
@required did: did;
7
7
8
-
@doc("The state of the video processing job. All values not listed as a known value indicate that the job is in process.")
8
+
/** The state of the video processing job. All values not listed as a known value indicate that the job is in process. */
9
9
@required
10
10
state: "JOB_STATE_COMPLETED" | "JOB_STATE_FAILED" | string;
11
11
12
-
@doc("Progress within the current processing state.")
12
+
/** Progress within the current processing state. */
13
13
@minValue(0)
14
14
@maxValue(100)
15
15
progress?: integer;
+8
-1
packages/emitter/test/integration/atproto/input/app/bsky/video/getJobStatus.tsp
+8
-1
packages/emitter/test/integration/atproto/input/app/bsky/video/getJobStatus.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace app.bsky.video.getJobStatus {
4
-
@doc("Get status details for a video processing job.")
4
+
/** Get status details for a video processing job. */
5
5
@query
6
6
op main(
7
7
@required jobId: string
···
9
9
@required jobStatus: app.bsky.video.defs.JobStatus;
10
10
};
11
11
}
12
+
13
+
// --- Externals ---
14
+
15
+
@external
16
+
namespace app.bsky.video.defs {
17
+
model JobStatus { }
18
+
}
+1
-1
packages/emitter/test/integration/atproto/input/app/bsky/video/getUploadLimits.tsp
+1
-1
packages/emitter/test/integration/atproto/input/app/bsky/video/getUploadLimits.tsp
+8
-1
packages/emitter/test/integration/atproto/input/app/bsky/video/uploadVideo.tsp
+8
-1
packages/emitter/test/integration/atproto/input/app/bsky/video/uploadVideo.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace app.bsky.video.uploadVideo {
4
-
@doc("Upload a video to be processed then stored on the PDS.")
4
+
/** Upload a video to be processed then stored on the PDS. */
5
5
@procedure
6
6
op main(
7
7
@encoding("video/mp4")
···
10
10
@required jobStatus: app.bsky.video.defs.JobStatus;
11
11
};
12
12
}
13
+
14
+
// --- Externals ---
15
+
16
+
@external
17
+
namespace app.bsky.video.defs {
18
+
model JobStatus { }
19
+
}
+1
-1
packages/emitter/test/integration/atproto/input/chat/bsky/actor/declaration.tsp
+1
-1
packages/emitter/test/integration/atproto/input/chat/bsky/actor/declaration.tsp
+15
-1
packages/emitter/test/integration/atproto/input/chat/bsky/actor/defs.tsp
+15
-1
packages/emitter/test/integration/atproto/input/chat/bsky/actor/defs.tsp
···
14
14
viewer?: app.bsky.actor.defs.ViewerState;
15
15
labels?: com.atproto.label.defs.Label[];
16
16
17
-
@doc("Set to true when the actor cannot actively participate in conversations")
17
+
/** Set to true when the actor cannot actively participate in conversations */
18
18
chatDisabled?: boolean;
19
19
20
20
verification?: app.bsky.actor.defs.VerificationState;
21
21
}
22
22
}
23
+
24
+
// --- Externals ---
25
+
26
+
@external
27
+
namespace app.bsky.actor.defs {
28
+
model ProfileAssociated { }
29
+
model ViewerState { }
30
+
model VerificationState { }
31
+
}
32
+
33
+
@external
34
+
namespace com.atproto.label.defs {
35
+
model Label { }
36
+
}
+1
-1
packages/emitter/test/integration/atproto/input/chat/bsky/convo/acceptConvo.tsp
+1
-1
packages/emitter/test/integration/atproto/input/chat/bsky/convo/acceptConvo.tsp
+11
-4
packages/emitter/test/integration/atproto/input/chat/bsky/convo/addReaction.tsp
+11
-4
packages/emitter/test/integration/atproto/input/chat/bsky/convo/addReaction.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace chat.bsky.convo.addReaction {
4
-
@doc("Indicates that the message has been deleted and reactions can no longer be added/removed.")
4
+
/** Indicates that the message has been deleted and reactions can no longer be added/removed. */
5
5
model ReactionMessageDeleted {}
6
6
7
-
@doc("Indicates that the message has the maximum number of reactions allowed for a single user, and the requested reaction wasn't yet present. If it was already present, the request will not fail since it is idempotent.")
7
+
/** Indicates that the message has the maximum number of reactions allowed for a single user, and the requested reaction wasn't yet present. If it was already present, the request will not fail since it is idempotent. */
8
8
model ReactionLimitReached {}
9
9
10
-
@doc("Indicates the value for the reaction is not acceptable. In general, this means it is not an emoji.")
10
+
/** Indicates the value for the reaction is not acceptable. In general, this means it is not an emoji. */
11
11
model ReactionInvalidValue {}
12
12
13
-
@doc("Adds an emoji reaction to a message. Requires authentication. It is idempotent, so multiple calls from the same user with the same emoji result in a single reaction.")
13
+
/** Adds an emoji reaction to a message. Requires authentication. It is idempotent, so multiple calls from the same user with the same emoji result in a single reaction. */
14
14
@procedure
15
15
@errors(ReactionMessageDeleted, ReactionLimitReached, ReactionInvalidValue)
16
16
op main(input: {
···
27
27
@required message: chat.bsky.convo.defs.MessageView;
28
28
};
29
29
}
30
+
31
+
// --- Externals ---
32
+
33
+
@external
34
+
namespace chat.bsky.convo.defs {
35
+
model MessageView { }
36
+
}
+21
-3
packages/emitter/test/integration/atproto/input/chat/bsky/convo/defs.tsp
+21
-3
packages/emitter/test/integration/atproto/input/chat/bsky/convo/defs.tsp
···
13
13
@required
14
14
text: string;
15
15
16
-
@doc("Annotations of text (mentions, URLs, hashtags, etc)")
16
+
/** Annotations of text (mentions, URLs, hashtags, etc) */
17
17
facets?: app.bsky.richtext.facet.Main[];
18
18
19
19
embed?: (app.bsky.embed.record.Main | unknown);
···
28
28
@required
29
29
text: string;
30
30
31
-
@doc("Annotations of text (mentions, URLs, hashtags, etc)")
31
+
/** Annotations of text (mentions, URLs, hashtags, etc) */
32
32
facets?: app.bsky.richtext.facet.Main[];
33
33
34
34
embed?: (app.bsky.embed.record.View | unknown);
35
35
36
-
@doc("Reactions to this message, in ascending order of creation time.")
36
+
/** Reactions to this message, in ascending order of creation time. */
37
37
reactions?: ReactionView[];
38
38
39
39
@required sender: MessageViewSender;
···
139
139
@required reaction: ReactionView;
140
140
}
141
141
}
142
+
143
+
// --- Externals ---
144
+
145
+
@external
146
+
namespace app.bsky.richtext.facet {
147
+
model Main { }
148
+
}
149
+
150
+
@external
151
+
namespace app.bsky.embed.`record` {
152
+
model Main { }
153
+
model View { }
154
+
}
155
+
156
+
@external
157
+
namespace chat.bsky.actor.defs {
158
+
model ProfileViewBasic { }
159
+
}
+7
packages/emitter/test/integration/atproto/input/chat/bsky/convo/deleteMessageForSelf.tsp
+7
packages/emitter/test/integration/atproto/input/chat/bsky/convo/deleteMessageForSelf.tsp
+7
packages/emitter/test/integration/atproto/input/chat/bsky/convo/getConvo.tsp
+7
packages/emitter/test/integration/atproto/input/chat/bsky/convo/getConvo.tsp
+8
-1
packages/emitter/test/integration/atproto/input/chat/bsky/convo/getConvoAvailability.tsp
+8
-1
packages/emitter/test/integration/atproto/input/chat/bsky/convo/getConvoAvailability.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace chat.bsky.convo.getConvoAvailability {
4
-
@doc("Get whether the requester and the other members can chat. If an existing convo is found for these members, it is returned.")
4
+
/** Get whether the requester and the other members can chat. If an existing convo is found for these members, it is returned. */
5
5
@query
6
6
op main(
7
7
@minItems(1)
···
13
13
convo?: chat.bsky.convo.defs.ConvoView;
14
14
};
15
15
}
16
+
17
+
// --- Externals ---
18
+
19
+
@external
20
+
namespace chat.bsky.convo.defs {
21
+
model ConvoView { }
22
+
}
+7
packages/emitter/test/integration/atproto/input/chat/bsky/convo/getConvoForMembers.tsp
+7
packages/emitter/test/integration/atproto/input/chat/bsky/convo/getConvoForMembers.tsp
+16
packages/emitter/test/integration/atproto/input/chat/bsky/convo/getLog.tsp
+16
packages/emitter/test/integration/atproto/input/chat/bsky/convo/getLog.tsp
···
21
21
)[];
22
22
};
23
23
}
24
+
25
+
// --- Externals ---
26
+
27
+
@external
28
+
namespace chat.bsky.convo.defs {
29
+
model LogBeginConvo { }
30
+
model LogAcceptConvo { }
31
+
model LogLeaveConvo { }
32
+
model LogMuteConvo { }
33
+
model LogUnmuteConvo { }
34
+
model LogCreateMessage { }
35
+
model LogDeleteMessage { }
36
+
model LogReadMessage { }
37
+
model LogAddReaction { }
38
+
model LogRemoveReaction { }
39
+
}
+8
packages/emitter/test/integration/atproto/input/chat/bsky/convo/getMessages.tsp
+8
packages/emitter/test/integration/atproto/input/chat/bsky/convo/getMessages.tsp
+7
packages/emitter/test/integration/atproto/input/chat/bsky/convo/listConvos.tsp
+7
packages/emitter/test/integration/atproto/input/chat/bsky/convo/listConvos.tsp
+7
packages/emitter/test/integration/atproto/input/chat/bsky/convo/muteConvo.tsp
+7
packages/emitter/test/integration/atproto/input/chat/bsky/convo/muteConvo.tsp
+10
-3
packages/emitter/test/integration/atproto/input/chat/bsky/convo/removeReaction.tsp
+10
-3
packages/emitter/test/integration/atproto/input/chat/bsky/convo/removeReaction.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace chat.bsky.convo.removeReaction {
4
-
@doc("Indicates that the message has been deleted and reactions can no longer be added/removed.")
4
+
/** Indicates that the message has been deleted and reactions can no longer be added/removed. */
5
5
model ReactionMessageDeleted {}
6
6
7
-
@doc("Indicates the value for the reaction is not acceptable. In general, this means it is not an emoji.")
7
+
/** Indicates the value for the reaction is not acceptable. In general, this means it is not an emoji. */
8
8
model ReactionInvalidValue {}
9
9
10
-
@doc("Removes an emoji reaction from a message. Requires authentication. It is idempotent, so multiple calls from the same user with the same emoji result in that reaction not being present, even if it already wasn't.")
10
+
/** Removes an emoji reaction from a message. Requires authentication. It is idempotent, so multiple calls from the same user with the same emoji result in that reaction not being present, even if it already wasn't. */
11
11
@procedure
12
12
@errors(ReactionMessageDeleted, ReactionInvalidValue)
13
13
op main(input: {
···
24
24
@required message: chat.bsky.convo.defs.MessageView;
25
25
};
26
26
}
27
+
28
+
// --- Externals ---
29
+
30
+
@external
31
+
namespace chat.bsky.convo.defs {
32
+
model MessageView { }
33
+
}
+8
packages/emitter/test/integration/atproto/input/chat/bsky/convo/sendMessage.tsp
+8
packages/emitter/test/integration/atproto/input/chat/bsky/convo/sendMessage.tsp
+8
packages/emitter/test/integration/atproto/input/chat/bsky/convo/sendMessageBatch.tsp
+8
packages/emitter/test/integration/atproto/input/chat/bsky/convo/sendMessageBatch.tsp
+7
packages/emitter/test/integration/atproto/input/chat/bsky/convo/unmuteConvo.tsp
+7
packages/emitter/test/integration/atproto/input/chat/bsky/convo/unmuteConvo.tsp
+1
-1
packages/emitter/test/integration/atproto/input/chat/bsky/convo/updateAllRead.tsp
+1
-1
packages/emitter/test/integration/atproto/input/chat/bsky/convo/updateAllRead.tsp
+7
packages/emitter/test/integration/atproto/input/chat/bsky/convo/updateRead.tsp
+7
packages/emitter/test/integration/atproto/input/chat/bsky/convo/updateRead.tsp
+9
-1
packages/emitter/test/integration/atproto/input/chat/bsky/moderation/getMessageContext.tsp
+9
-1
packages/emitter/test/integration/atproto/input/chat/bsky/moderation/getMessageContext.tsp
···
3
3
namespace chat.bsky.moderation.getMessageContext {
4
4
@query
5
5
op main(
6
-
@doc("Conversation that the message is from. NOTE: this field will eventually be required.")
6
+
/** Conversation that the message is from. NOTE: this field will eventually be required. */
7
7
convoId?: string,
8
8
9
9
@required messageId: string,
···
20
20
)[];
21
21
};
22
22
}
23
+
24
+
// --- Externals ---
25
+
26
+
@external
27
+
namespace chat.bsky.convo.defs {
28
+
model MessageView { }
29
+
model DeletedMessageView { }
30
+
}
+8
packages/emitter/test/integration/atproto/input/com/atproto/admin/defs.tsp
+8
packages/emitter/test/integration/atproto/input/com/atproto/admin/defs.tsp
+1
-1
packages/emitter/test/integration/atproto/input/com/atproto/admin/deleteAccount.tsp
+1
-1
packages/emitter/test/integration/atproto/input/com/atproto/admin/deleteAccount.tsp
+2
-2
packages/emitter/test/integration/atproto/input/com/atproto/admin/disableAccountInvites.tsp
+2
-2
packages/emitter/test/integration/atproto/input/com/atproto/admin/disableAccountInvites.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace com.atproto.admin.disableAccountInvites {
4
-
@doc("Disable an account from receiving new invite codes, but does not invalidate existing codes.")
4
+
/** Disable an account from receiving new invite codes, but does not invalidate existing codes. */
5
5
@procedure
6
6
op main(input: {
7
7
@required account: did;
8
8
9
-
@doc("Optional reason for disabled invites.")
9
+
/** Optional reason for disabled invites. */
10
10
note?: string;
11
11
}): void;
12
12
}
+1
-1
packages/emitter/test/integration/atproto/input/com/atproto/admin/disableInviteCodes.tsp
+1
-1
packages/emitter/test/integration/atproto/input/com/atproto/admin/disableInviteCodes.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace com.atproto.admin.disableInviteCodes {
4
-
@doc("Disable some set of codes and/or all codes associated with a set of users.")
4
+
/** Disable some set of codes and/or all codes associated with a set of users. */
5
5
@procedure
6
6
op main(input: {
7
7
codes?: string[];
+2
-2
packages/emitter/test/integration/atproto/input/com/atproto/admin/enableAccountInvites.tsp
+2
-2
packages/emitter/test/integration/atproto/input/com/atproto/admin/enableAccountInvites.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace com.atproto.admin.enableAccountInvites {
4
-
@doc("Re-enable an account's ability to receive invite codes.")
4
+
/** Re-enable an account's ability to receive invite codes. */
5
5
@procedure
6
6
op main(input: {
7
7
@required account: did;
8
8
9
-
@doc("Optional reason for enabled invites.")
9
+
/** Optional reason for enabled invites. */
10
10
note?: string;
11
11
}): void;
12
12
}
+8
-1
packages/emitter/test/integration/atproto/input/com/atproto/admin/getAccountInfo.tsp
+8
-1
packages/emitter/test/integration/atproto/input/com/atproto/admin/getAccountInfo.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace com.atproto.admin.getAccountInfo {
4
-
@doc("Get details about an account.")
4
+
/** Get details about an account. */
5
5
@query
6
6
op main(
7
7
@required did: did
8
8
): com.atproto.admin.defs.AccountView;
9
9
}
10
+
11
+
// --- Externals ---
12
+
13
+
@external
14
+
namespace com.atproto.admin.defs {
15
+
model AccountView { }
16
+
}
+8
-1
packages/emitter/test/integration/atproto/input/com/atproto/admin/getAccountInfos.tsp
+8
-1
packages/emitter/test/integration/atproto/input/com/atproto/admin/getAccountInfos.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace com.atproto.admin.getAccountInfos {
4
-
@doc("Get details about some accounts.")
4
+
/** Get details about some accounts. */
5
5
@query
6
6
op main(
7
7
@required dids: did[]
···
9
9
@required infos: com.atproto.admin.defs.AccountView[];
10
10
};
11
11
}
12
+
13
+
// --- Externals ---
14
+
15
+
@external
16
+
namespace com.atproto.admin.defs {
17
+
model AccountView { }
18
+
}
+8
-1
packages/emitter/test/integration/atproto/input/com/atproto/admin/getInviteCodes.tsp
+8
-1
packages/emitter/test/integration/atproto/input/com/atproto/admin/getInviteCodes.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace com.atproto.admin.getInviteCodes {
4
-
@doc("Get an admin view of invite codes.")
4
+
/** Get an admin view of invite codes. */
5
5
@query
6
6
op main(
7
7
sort?: "recent" | "usage" | string = "recent",
···
16
16
@required codes: com.atproto.server.defs.InviteCode[];
17
17
};
18
18
}
19
+
20
+
// --- Externals ---
21
+
22
+
@external
23
+
namespace com.atproto.server.defs {
24
+
model InviteCode { }
25
+
}
+15
-1
packages/emitter/test/integration/atproto/input/com/atproto/admin/getSubjectStatus.tsp
+15
-1
packages/emitter/test/integration/atproto/input/com/atproto/admin/getSubjectStatus.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace com.atproto.admin.getSubjectStatus {
4
-
@doc("Get the service-specific admin status of a subject (account, record, or blob).")
4
+
/** Get the service-specific admin status of a subject (account, record, or blob). */
5
5
@query
6
6
op main(
7
7
did?: did,
···
20
20
deactivated?: com.atproto.admin.defs.StatusAttr;
21
21
};
22
22
}
23
+
24
+
// --- Externals ---
25
+
26
+
@external
27
+
namespace com.atproto.admin.defs {
28
+
model RepoRef { }
29
+
model RepoBlobRef { }
30
+
model StatusAttr { }
31
+
}
32
+
33
+
@external
34
+
namespace com.atproto.repo.strongRef {
35
+
model Main { }
36
+
}
+8
-1
packages/emitter/test/integration/atproto/input/com/atproto/admin/searchAccounts.tsp
+8
-1
packages/emitter/test/integration/atproto/input/com/atproto/admin/searchAccounts.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace com.atproto.admin.searchAccounts {
4
-
@doc("Get list of accounts that matches your search query.")
4
+
/** Get list of accounts that matches your search query. */
5
5
@query
6
6
op main(
7
7
email?: string,
···
15
15
@required accounts: com.atproto.admin.defs.AccountView[];
16
16
};
17
17
}
18
+
19
+
// --- Externals ---
20
+
21
+
@external
22
+
namespace com.atproto.admin.defs {
23
+
model AccountView { }
24
+
}
+2
-2
packages/emitter/test/integration/atproto/input/com/atproto/admin/sendEmail.tsp
+2
-2
packages/emitter/test/integration/atproto/input/com/atproto/admin/sendEmail.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace com.atproto.admin.sendEmail {
4
-
@doc("Send email to a user's account email address.")
4
+
/** Send email to a user's account email address. */
5
5
@procedure
6
6
op main(input: {
7
7
@required recipientDid: did;
···
9
9
subject?: string;
10
10
@required senderDid: did;
11
11
12
-
@doc("Additional comment by the sender that won't be used in the email itself but helpful to provide more context for moderators/reviewers")
12
+
/** Additional comment by the sender that won't be used in the email itself but helpful to provide more context for moderators/reviewers */
13
13
comment?: string;
14
14
}): {
15
15
@required sent: boolean;
+2
-2
packages/emitter/test/integration/atproto/input/com/atproto/admin/updateAccountEmail.tsp
+2
-2
packages/emitter/test/integration/atproto/input/com/atproto/admin/updateAccountEmail.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace com.atproto.admin.updateAccountEmail {
4
-
@doc("Administrative action to update an account's email.")
4
+
/** Administrative action to update an account's email. */
5
5
@procedure
6
6
op main(input: {
7
-
@doc("The handle or DID of the repo.")
7
+
/** The handle or DID of the repo. */
8
8
@required
9
9
account: atIdentifier;
10
10
+1
-1
packages/emitter/test/integration/atproto/input/com/atproto/admin/updateAccountHandle.tsp
+1
-1
packages/emitter/test/integration/atproto/input/com/atproto/admin/updateAccountHandle.tsp
+1
-1
packages/emitter/test/integration/atproto/input/com/atproto/admin/updateAccountPassword.tsp
+1
-1
packages/emitter/test/integration/atproto/input/com/atproto/admin/updateAccountPassword.tsp
+2
-2
packages/emitter/test/integration/atproto/input/com/atproto/admin/updateAccountSigningKey.tsp
+2
-2
packages/emitter/test/integration/atproto/input/com/atproto/admin/updateAccountSigningKey.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace com.atproto.admin.updateAccountSigningKey {
4
-
@doc("Administrative action to update an account's signing key in their Did document.")
4
+
/** Administrative action to update an account's signing key in their Did document. */
5
5
@procedure
6
6
op main(input: {
7
7
@required did: did;
8
8
9
-
@doc("Did-key formatted public key")
9
+
/** Did-key formatted public key */
10
10
@required
11
11
signingKey: did;
12
12
}): void;
+15
-1
packages/emitter/test/integration/atproto/input/com/atproto/admin/updateSubjectStatus.tsp
+15
-1
packages/emitter/test/integration/atproto/input/com/atproto/admin/updateSubjectStatus.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace com.atproto.admin.updateSubjectStatus {
4
-
@doc("Update the service-specific admin status of a subject (account, record, or blob).")
4
+
/** Update the service-specific admin status of a subject (account, record, or blob). */
5
5
@procedure
6
6
op main(input: {
7
7
@required
···
26
26
takedown?: com.atproto.admin.defs.StatusAttr;
27
27
};
28
28
}
29
+
30
+
// --- Externals ---
31
+
32
+
@external
33
+
namespace com.atproto.admin.defs {
34
+
model RepoRef { }
35
+
model RepoBlobRef { }
36
+
model StatusAttr { }
37
+
}
38
+
39
+
@external
40
+
namespace com.atproto.repo.strongRef {
41
+
model Main { }
42
+
}
+2
-2
packages/emitter/test/integration/atproto/input/com/atproto/identity/defs.tsp
+2
-2
packages/emitter/test/integration/atproto/input/com/atproto/identity/defs.tsp
···
4
4
model IdentityInfo {
5
5
@required did: did;
6
6
7
-
@doc("The validated handle of the account; or 'handle.invalid' if the handle did not bi-directionally match the DID document.")
7
+
/** The validated handle of the account; or 'handle.invalid' if the handle did not bi-directionally match the DID document. */
8
8
@required
9
9
handle: handle;
10
10
11
-
@doc("The complete DID document for the identity.")
11
+
/** The complete DID document for the identity. */
12
12
@required
13
13
didDoc: unknown;
14
14
}
+2
-2
packages/emitter/test/integration/atproto/input/com/atproto/identity/getRecommendedDidCredentials.tsp
+2
-2
packages/emitter/test/integration/atproto/input/com/atproto/identity/getRecommendedDidCredentials.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace com.atproto.identity.getRecommendedDidCredentials {
4
-
@doc("Describe the credentials that should be included in the DID doc of an account that is migrating to this service.")
4
+
/** Describe the credentials that should be included in the DID doc of an account that is migrating to this service. */
5
5
@query
6
6
op main(): {
7
-
@doc("Recommended rotation keys for PLC dids. Should be undefined (or ignored) for did:webs.")
7
+
/** Recommended rotation keys for PLC dids. Should be undefined (or ignored) for did:webs. */
8
8
rotationKeys?: string[];
9
9
10
10
alsoKnownAs?: string[];
+11
-4
packages/emitter/test/integration/atproto/input/com/atproto/identity/refreshIdentity.tsp
+11
-4
packages/emitter/test/integration/atproto/input/com/atproto/identity/refreshIdentity.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace com.atproto.identity.refreshIdentity {
4
-
@doc("The resolution process confirmed that the handle does not resolve to any DID.")
4
+
/** The resolution process confirmed that the handle does not resolve to any DID. */
5
5
model HandleNotFound {}
6
6
7
-
@doc("The DID resolution process confirmed that there is no current DID.")
7
+
/** The DID resolution process confirmed that there is no current DID. */
8
8
model DidNotFound {}
9
9
10
-
@doc("The DID previously existed, but has been deactivated.")
10
+
/** The DID previously existed, but has been deactivated. */
11
11
model DidDeactivated {}
12
12
13
-
@doc("Request that the server re-resolve an identity (DID and handle). The server may ignore this request, or require authentication, depending on the role, implementation, and policy of the server.")
13
+
/** Request that the server re-resolve an identity (DID and handle). The server may ignore this request, or require authentication, depending on the role, implementation, and policy of the server. */
14
14
@procedure
15
15
@errors(HandleNotFound, DidNotFound, DidDeactivated)
16
16
op main(input: {
17
17
@required identifier: atIdentifier;
18
18
}): com.atproto.identity.defs.IdentityInfo;
19
19
}
20
+
21
+
// --- Externals ---
22
+
23
+
@external
24
+
namespace com.atproto.identity.defs {
25
+
model IdentityInfo { }
26
+
}
+1
-1
packages/emitter/test/integration/atproto/input/com/atproto/identity/requestPlcOperationSignature.tsp
+1
-1
packages/emitter/test/integration/atproto/input/com/atproto/identity/requestPlcOperationSignature.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace com.atproto.identity.requestPlcOperationSignature {
4
-
@doc("Request an email with a code to in order to request a signed PLC operation. Requires Auth.")
4
+
/** Request an email with a code to in order to request a signed PLC operation. Requires Auth. */
5
5
@procedure
6
6
op main(): void;
7
7
}
+5
-5
packages/emitter/test/integration/atproto/input/com/atproto/identity/resolveDid.tsp
+5
-5
packages/emitter/test/integration/atproto/input/com/atproto/identity/resolveDid.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace com.atproto.identity.resolveDid {
4
-
@doc("Resolves DID to DID document. Does not bi-directionally verify handle.")
4
+
/** Resolves DID to DID document. Does not bi-directionally verify handle. */
5
5
@query
6
6
@errors(DidNotFound, DidDeactivated)
7
7
op main(
8
-
@doc("DID to resolve.")
8
+
/** DID to resolve. */
9
9
@required
10
10
did: did
11
11
): {
12
-
@doc("The complete DID document for the identity.")
12
+
/** The complete DID document for the identity. */
13
13
@required
14
14
didDoc: unknown;
15
15
};
16
16
17
-
@doc("The DID resolution process confirmed that there is no current DID.")
17
+
/** The DID resolution process confirmed that there is no current DID. */
18
18
model DidNotFound {}
19
19
20
-
@doc("The DID previously existed, but has been deactivated.")
20
+
/** The DID previously existed, but has been deactivated. */
21
21
model DidDeactivated {}
22
22
}
+3
-3
packages/emitter/test/integration/atproto/input/com/atproto/identity/resolveHandle.tsp
+3
-3
packages/emitter/test/integration/atproto/input/com/atproto/identity/resolveHandle.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace com.atproto.identity.resolveHandle {
4
-
@doc("Resolves an atproto handle (hostname) to a DID. Does not necessarily bi-directionally verify against the the DID document.")
4
+
/** Resolves an atproto handle (hostname) to a DID. Does not necessarily bi-directionally verify against the the DID document. */
5
5
@query
6
6
@errors(HandleNotFound)
7
7
op main(
8
-
@doc("The handle to resolve.")
8
+
/** The handle to resolve. */
9
9
@required
10
10
handle: handle
11
11
): {
12
12
@required did: did;
13
13
};
14
14
15
-
@doc("The resolution process confirmed that the handle does not resolve to any DID.")
15
+
/** The resolution process confirmed that the handle does not resolve to any DID. */
16
16
model HandleNotFound {}
17
17
}
+12
-5
packages/emitter/test/integration/atproto/input/com/atproto/identity/resolveIdentity.tsp
+12
-5
packages/emitter/test/integration/atproto/input/com/atproto/identity/resolveIdentity.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace com.atproto.identity.resolveIdentity {
4
-
@doc("The resolution process confirmed that the handle does not resolve to any DID.")
4
+
/** The resolution process confirmed that the handle does not resolve to any DID. */
5
5
model HandleNotFound {}
6
6
7
-
@doc("The DID resolution process confirmed that there is no current DID.")
7
+
/** The DID resolution process confirmed that there is no current DID. */
8
8
model DidNotFound {}
9
9
10
-
@doc("The DID previously existed, but has been deactivated.")
10
+
/** The DID previously existed, but has been deactivated. */
11
11
model DidDeactivated {}
12
12
13
-
@doc("Resolves an identity (DID or Handle) to a full identity (DID document and verified handle).")
13
+
/** Resolves an identity (DID or Handle) to a full identity (DID document and verified handle). */
14
14
@query
15
15
@errors(HandleNotFound, DidNotFound, DidDeactivated)
16
16
op main(
17
-
@doc("Handle or DID to resolve.")
17
+
/** Handle or DID to resolve. */
18
18
@required
19
19
identifier: atIdentifier
20
20
): com.atproto.identity.defs.IdentityInfo;
21
21
}
22
+
23
+
// --- Externals ---
24
+
25
+
@external
26
+
namespace com.atproto.identity.defs {
27
+
model IdentityInfo { }
28
+
}
+3
-3
packages/emitter/test/integration/atproto/input/com/atproto/identity/signPlcOperation.tsp
+3
-3
packages/emitter/test/integration/atproto/input/com/atproto/identity/signPlcOperation.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace com.atproto.identity.signPlcOperation {
4
-
@doc("Signs a PLC operation to update some value(s) in the requesting DID's document.")
4
+
/** Signs a PLC operation to update some value(s) in the requesting DID's document. */
5
5
@procedure
6
6
op main(input: {
7
-
@doc("A token received through com.atproto.identity.requestPlcOperationSignature")
7
+
/** A token received through com.atproto.identity.requestPlcOperationSignature */
8
8
token?: string;
9
9
10
10
rotationKeys?: string[];
···
15
15
16
16
services?: unknown;
17
17
}): {
18
-
@doc("A signed DID PLC operation.")
18
+
/** A signed DID PLC operation. */
19
19
@required
20
20
operation: unknown;
21
21
};
+1
-1
packages/emitter/test/integration/atproto/input/com/atproto/identity/submitPlcOperation.tsp
+1
-1
packages/emitter/test/integration/atproto/input/com/atproto/identity/submitPlcOperation.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace com.atproto.identity.submitPlcOperation {
4
-
@doc("Validates a PLC operation to ensure that it doesn't violate a service's constraints or get the identity into a bad state, then submits it to the PLC registry")
4
+
/** Validates a PLC operation to ensure that it doesn't violate a service's constraints or get the identity into a bad state, then submits it to the PLC registry */
5
5
@procedure
6
6
op main(input: {
7
7
@required operation: unknown;
+2
-2
packages/emitter/test/integration/atproto/input/com/atproto/identity/updateHandle.tsp
+2
-2
packages/emitter/test/integration/atproto/input/com/atproto/identity/updateHandle.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace com.atproto.identity.updateHandle {
4
-
@doc("Updates the current account's handle. Verifies handle validity, and updates did:plc document if necessary. Implemented by PDS, and requires auth.")
4
+
/** Updates the current account's handle. Verifies handle validity, and updates did:plc document if necessary. Implemented by PDS, and requires auth. */
5
5
@procedure
6
6
op main(input: {
7
-
@doc("The new handle.")
7
+
/** The new handle. */
8
8
@required
9
9
handle: handle;
10
10
}): void;
+23
-23
packages/emitter/test/integration/atproto/input/com/atproto/label/defs.tsp
+23
-23
packages/emitter/test/integration/atproto/input/com/atproto/label/defs.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace com.atproto.label.defs {
4
-
@doc("Metadata tag on an atproto resource (eg, repo or record).")
4
+
/** Metadata tag on an atproto resource (eg, repo or record). */
5
5
model Label {
6
-
@doc("The AT Protocol version of the label object.")
6
+
/** The AT Protocol version of the label object. */
7
7
ver?: integer;
8
8
9
-
@doc("DID of the actor who created this label.")
9
+
/** DID of the actor who created this label. */
10
10
@required
11
11
src: did;
12
12
13
-
@doc("AT URI of the record, repository (account), or other resource that this label applies to.")
13
+
/** AT URI of the record, repository (account), or other resource that this label applies to. */
14
14
@required
15
15
uri: uri;
16
16
17
-
@doc("Optionally, CID specifying the specific version of 'uri' resource this label applies to.")
17
+
/** Optionally, CID specifying the specific version of 'uri' resource this label applies to. */
18
18
cid?: cid;
19
19
20
-
@doc("The short string name of the value or type of this label.")
20
+
/** The short string name of the value or type of this label. */
21
21
@maxLength(128)
22
22
@required
23
23
val: string;
24
24
25
-
@doc("If true, this is a negation label, overwriting a previous label.")
25
+
/** If true, this is a negation label, overwriting a previous label. */
26
26
neg?: boolean;
27
27
28
-
@doc("Timestamp when this label was created.")
28
+
/** Timestamp when this label was created. */
29
29
@required
30
30
cts: datetime;
31
31
32
-
@doc("Timestamp at which this label expires (no longer applies).")
32
+
/** Timestamp at which this label expires (no longer applies). */
33
33
exp?: datetime;
34
34
35
-
@doc("Signature of dag-cbor encoded label.")
35
+
/** Signature of dag-cbor encoded label. */
36
36
sig?: bytes;
37
37
}
38
38
39
-
@doc("Metadata tags on an atproto record, published by the author within the record.")
39
+
/** Metadata tags on an atproto record, published by the author within the record. */
40
40
model SelfLabels {
41
41
@maxItems(10)
42
42
@required
43
43
values: SelfLabel[];
44
44
}
45
45
46
-
@doc("Metadata tag on an atproto record, published by the author within the record. Note that schemas should use #selfLabels, not #selfLabel.")
46
+
/** Metadata tag on an atproto record, published by the author within the record. Note that schemas should use #selfLabels, not #selfLabel. */
47
47
model SelfLabel {
48
-
@doc("The short string name of the value or type of this label.")
48
+
/** The short string name of the value or type of this label. */
49
49
@maxLength(128)
50
50
@required
51
51
val: string;
52
52
}
53
53
54
-
@doc("Declares a label value and its expected interpretations and behaviors.")
54
+
/** Declares a label value and its expected interpretations and behaviors. */
55
55
model LabelValueDefinition {
56
-
@doc("The value of the label being defined. Must only include lowercase ascii and the '-' character ([a-z-]+).")
56
+
/** The value of the label being defined. Must only include lowercase ascii and the '-' character ([a-z-]+). */
57
57
@maxLength(100)
58
58
@maxGraphemes(100)
59
59
@required
60
60
identifier: string;
61
61
62
-
@doc("How should a client visually convey this label? 'inform' means neutral and informational; 'alert' means negative and warning; 'none' means show nothing.")
62
+
/** How should a client visually convey this label? 'inform' means neutral and informational; 'alert' means negative and warning; 'none' means show nothing. */
63
63
@required
64
64
severity: "inform" | "alert" | "none" | string;
65
65
66
-
@doc("What should this label hide in the UI, if applied? 'content' hides all of the target; 'media' hides the images/video/audio; 'none' hides nothing.")
66
+
/** What should this label hide in the UI, if applied? 'content' hides all of the target; 'media' hides the images/video/audio; 'none' hides nothing. */
67
67
@required
68
68
blurs: "content" | "media" | "none" | string;
69
69
70
-
@doc("The default setting for this label.")
70
+
/** The default setting for this label. */
71
71
defaultSetting?: "ignore" | "warn" | "hide" | string = "warn";
72
72
73
-
@doc("Does the user need to have adult content enabled in order to configure this label?")
73
+
/** Does the user need to have adult content enabled in order to configure this label? */
74
74
adultOnly?: boolean;
75
75
76
76
@required
77
77
locales: LabelValueDefinitionStrings[];
78
78
}
79
79
80
-
@doc("Strings which describe the label in the UI, localized into a specific language.")
80
+
/** Strings which describe the label in the UI, localized into a specific language. */
81
81
model LabelValueDefinitionStrings {
82
-
@doc("The code of the language these strings are written in.")
82
+
/** The code of the language these strings are written in. */
83
83
@required
84
84
lang: language;
85
85
86
-
@doc("A short human-readable name for the label.")
86
+
/** A short human-readable name for the label. */
87
87
@maxGraphemes(64)
88
88
@maxLength(640)
89
89
@required
90
90
name: string;
91
91
92
-
@doc("A longer description of what the label means and why it might be applied.")
92
+
/** A longer description of what the label means and why it might be applied. */
93
93
@maxGraphemes(10000)
94
94
@maxLength(100000)
95
95
@required
+10
-3
packages/emitter/test/integration/atproto/input/com/atproto/label/queryLabels.tsp
+10
-3
packages/emitter/test/integration/atproto/input/com/atproto/label/queryLabels.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace com.atproto.label.queryLabels {
4
-
@doc("Find labels relevant to the provided AT-URI patterns. Public endpoint for moderation services, though may return different or additional results with auth.")
4
+
/** Find labels relevant to the provided AT-URI patterns. Public endpoint for moderation services, though may return different or additional results with auth. */
5
5
@query
6
6
op main(
7
-
@doc("List of AT URI patterns to match (boolean 'OR'). Each may be a prefix (ending with '*'; will match inclusive of the string leading to '*'), or a full URI.")
7
+
/** List of AT URI patterns to match (boolean 'OR'). Each may be a prefix (ending with '*'; will match inclusive of the string leading to '*'), or a full URI. */
8
8
@required
9
9
uriPatterns: string[],
10
10
11
-
@doc("Optional list of label sources (DIDs) to filter on.")
11
+
/** Optional list of label sources (DIDs) to filter on. */
12
12
sources?: did[],
13
13
14
14
@minValue(1)
···
21
21
@required labels: com.atproto.label.defs.Label[];
22
22
};
23
23
}
24
+
25
+
// --- Externals ---
26
+
27
+
@external
28
+
namespace com.atproto.label.defs {
29
+
model Label { }
30
+
}
+10
-2
packages/emitter/test/integration/atproto/input/com/atproto/label/subscribeLabels.tsp
+10
-2
packages/emitter/test/integration/atproto/input/com/atproto/label/subscribeLabels.tsp
···
13
13
message?: string;
14
14
}
15
15
16
-
@doc("Subscribe to stream of labels (and negations). Public endpoint implemented by mod services. Uses same sequencing scheme as repo event stream.")
16
+
/** Subscribe to stream of labels (and negations). Public endpoint implemented by mod services. Uses same sequencing scheme as repo event stream. */
17
17
@subscription
18
18
@errors(FutureCursor)
19
19
op main(
20
-
@doc("The last known event seq number to backfill from.")
20
+
/** The last known event seq number to backfill from. */
21
21
cursor?: integer
22
22
): (Labels | Info);
23
23
}
24
+
25
+
// --- Externals ---
26
+
27
+
@external
28
+
namespace com.atproto.label.defs {
29
+
model Label { }
30
+
model Info { }
31
+
}
+2
-2
packages/emitter/test/integration/atproto/input/com/atproto/lexicon/schema.tsp
+2
-2
packages/emitter/test/integration/atproto/input/com/atproto/lexicon/schema.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace com.atproto.lexicon.schema {
4
-
@doc("Representation of Lexicon schemas themselves, when published as atproto records. Note that the schema language is not defined in Lexicon; this meta schema currently only includes a single version field ('lexicon'). See the atproto specifications for description of the other expected top-level fields ('id', 'defs', etc).")
4
+
/** Representation of Lexicon schemas themselves, when published as atproto records. Note that the schema language is not defined in Lexicon; this meta schema currently only includes a single version field ('lexicon'). See the atproto specifications for description of the other expected top-level fields ('id', 'defs', etc). */
5
5
@rec("nsid")
6
6
model Main {
7
-
@doc("Indicates the 'version' of the Lexicon language. Must be '1' for the current atproto/Lexicon schema system.")
7
+
/** Indicates the 'version' of the Lexicon language. Must be '1' for the current atproto/Lexicon schema system. */
8
8
@required
9
9
lexicon: integer;
10
10
}
+23
-6
packages/emitter/test/integration/atproto/input/com/atproto/moderation/createReport.tsp
+23
-6
packages/emitter/test/integration/atproto/input/com/atproto/moderation/createReport.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace com.atproto.moderation.createReport {
4
-
@doc("Submit a moderation report regarding an atproto account or record. Implemented by moderation services (with PDS proxying), and requires auth.")
4
+
/** Submit a moderation report regarding an atproto account or record. Implemented by moderation services (with PDS proxying), and requires auth. */
5
5
@procedure
6
6
op main(input: {
7
-
@doc("Indicates the broad category of violation the report is for.")
7
+
/** Indicates the broad category of violation the report is for. */
8
8
@required
9
9
reasonType: com.atproto.moderation.defs.ReasonType;
10
10
11
11
@maxGraphemes(2000)
12
12
@maxLength(20000)
13
-
@doc("Additional context about the content and violation.")
13
+
/** Additional context about the content and violation. */
14
14
reason?: string;
15
15
16
16
@required
···
40
40
@required createdAt: datetime;
41
41
};
42
42
43
-
@doc("Moderation tool information for tracing the source of the action")
43
+
/** Moderation tool information for tracing the source of the action */
44
44
model ModTool {
45
-
@doc("Name/identifier of the source (e.g., 'bsky-app/android', 'bsky-web/chrome')")
45
+
/** Name/identifier of the source (e.g., 'bsky-app/android', 'bsky-web/chrome') */
46
46
@required
47
47
name: string;
48
48
49
-
@doc("Additional arbitrary metadata about the source")
49
+
/** Additional arbitrary metadata about the source */
50
50
meta?: unknown;
51
51
}
52
52
}
53
+
54
+
// --- Externals ---
55
+
56
+
@external
57
+
namespace com.atproto.moderation.defs {
58
+
model ReasonType { }
59
+
}
60
+
61
+
@external
62
+
namespace com.atproto.admin.defs {
63
+
model RepoRef { }
64
+
}
65
+
66
+
@external
67
+
namespace com.atproto.repo.strongRef {
68
+
model Main { }
69
+
}
+111
-69
packages/emitter/test/integration/atproto/input/com/atproto/moderation/defs.tsp
+111
-69
packages/emitter/test/integration/atproto/input/com/atproto/moderation/defs.tsp
···
3
3
namespace com.atproto.moderation.defs {
4
4
union ReasonType {
5
5
string,
6
-
7
-
ReasonSpam: "com.atproto.moderation.defs#reasonSpam",
8
-
ReasonViolation: "com.atproto.moderation.defs#reasonViolation",
9
-
ReasonMisleading: "com.atproto.moderation.defs#reasonMisleading",
10
-
ReasonSexual: "com.atproto.moderation.defs#reasonSexual",
11
-
ReasonRude: "com.atproto.moderation.defs#reasonRude",
12
-
ReasonOther: "com.atproto.moderation.defs#reasonOther",
13
-
ReasonAppeal: "com.atproto.moderation.defs#reasonAppeal",
14
-
15
-
ToolsOzoneReportReasonAppeal: "tools.ozone.report.defs#reasonAppeal",
16
-
17
-
ToolsOzoneReportReasonViolenceAnimalWelfare: "tools.ozone.report.defs#reasonViolenceAnimalWelfare",
18
-
ToolsOzoneReportReasonViolenceThreats: "tools.ozone.report.defs#reasonViolenceThreats",
19
-
ToolsOzoneReportReasonViolenceGraphicContent: "tools.ozone.report.defs#reasonViolenceGraphicContent",
20
-
ToolsOzoneReportReasonViolenceSelfHarm: "tools.ozone.report.defs#reasonViolenceSelfHarm",
21
-
ToolsOzoneReportReasonViolenceGlorification: "tools.ozone.report.defs#reasonViolenceGlorification",
22
-
ToolsOzoneReportReasonViolenceExtremistContent: "tools.ozone.report.defs#reasonViolenceExtremistContent",
23
-
ToolsOzoneReportReasonViolenceTrafficking: "tools.ozone.report.defs#reasonViolenceTrafficking",
24
-
ToolsOzoneReportReasonViolenceOther: "tools.ozone.report.defs#reasonViolenceOther",
25
-
26
-
ToolsOzoneReportReasonSexualAbuseContent: "tools.ozone.report.defs#reasonSexualAbuseContent",
27
-
ToolsOzoneReportReasonSexualNCII: "tools.ozone.report.defs#reasonSexualNCII",
28
-
ToolsOzoneReportReasonSexualSextortion: "tools.ozone.report.defs#reasonSexualSextortion",
29
-
ToolsOzoneReportReasonSexualDeepfake: "tools.ozone.report.defs#reasonSexualDeepfake",
30
-
ToolsOzoneReportReasonSexualAnimal: "tools.ozone.report.defs#reasonSexualAnimal",
31
-
ToolsOzoneReportReasonSexualUnlabeled: "tools.ozone.report.defs#reasonSexualUnlabeled",
32
-
ToolsOzoneReportReasonSexualOther: "tools.ozone.report.defs#reasonSexualOther",
33
-
34
-
ToolsOzoneReportReasonChildSafetyCSAM: "tools.ozone.report.defs#reasonChildSafetyCSAM",
35
-
ToolsOzoneReportReasonChildSafetyGroom: "tools.ozone.report.defs#reasonChildSafetyGroom",
36
-
ToolsOzoneReportReasonChildSafetyMinorPrivacy: "tools.ozone.report.defs#reasonChildSafetyMinorPrivacy",
37
-
ToolsOzoneReportReasonChildSafetyEndangerment: "tools.ozone.report.defs#reasonChildSafetyEndangerment",
38
-
ToolsOzoneReportReasonChildSafetyHarassment: "tools.ozone.report.defs#reasonChildSafetyHarassment",
39
-
ToolsOzoneReportReasonChildSafetyPromotion: "tools.ozone.report.defs#reasonChildSafetyPromotion",
40
-
ToolsOzoneReportReasonChildSafetyOther: "tools.ozone.report.defs#reasonChildSafetyOther",
41
-
42
-
ToolsOzoneReportReasonHarassmentTroll: "tools.ozone.report.defs#reasonHarassmentTroll",
43
-
ToolsOzoneReportReasonHarassmentTargeted: "tools.ozone.report.defs#reasonHarassmentTargeted",
44
-
ToolsOzoneReportReasonHarassmentHateSpeech: "tools.ozone.report.defs#reasonHarassmentHateSpeech",
45
-
ToolsOzoneReportReasonHarassmentDoxxing: "tools.ozone.report.defs#reasonHarassmentDoxxing",
46
-
ToolsOzoneReportReasonHarassmentOther: "tools.ozone.report.defs#reasonHarassmentOther",
47
-
48
-
ToolsOzoneReportReasonMisleadingBot: "tools.ozone.report.defs#reasonMisleadingBot",
49
-
ToolsOzoneReportReasonMisleadingImpersonation: "tools.ozone.report.defs#reasonMisleadingImpersonation",
50
-
ToolsOzoneReportReasonMisleadingSpam: "tools.ozone.report.defs#reasonMisleadingSpam",
51
-
ToolsOzoneReportReasonMisleadingScam: "tools.ozone.report.defs#reasonMisleadingScam",
52
-
ToolsOzoneReportReasonMisleadingSyntheticContent: "tools.ozone.report.defs#reasonMisleadingSyntheticContent",
53
-
ToolsOzoneReportReasonMisleadingMisinformation: "tools.ozone.report.defs#reasonMisleadingMisinformation",
54
-
ToolsOzoneReportReasonMisleadingOther: "tools.ozone.report.defs#reasonMisleadingOther",
55
-
56
-
ToolsOzoneReportReasonRuleSiteSecurity: "tools.ozone.report.defs#reasonRuleSiteSecurity",
57
-
ToolsOzoneReportReasonRuleStolenContent: "tools.ozone.report.defs#reasonRuleStolenContent",
58
-
ToolsOzoneReportReasonRuleProhibitedSales: "tools.ozone.report.defs#reasonRuleProhibitedSales",
59
-
ToolsOzoneReportReasonRuleBanEvasion: "tools.ozone.report.defs#reasonRuleBanEvasion",
60
-
ToolsOzoneReportReasonRuleOther: "tools.ozone.report.defs#reasonRuleOther",
61
-
62
-
ToolsOzoneReportReasonCivicElectoralProcess: "tools.ozone.report.defs#reasonCivicElectoralProcess",
63
-
ToolsOzoneReportReasonCivicDisclosure: "tools.ozone.report.defs#reasonCivicDisclosure",
64
-
ToolsOzoneReportReasonCivicInterference: "tools.ozone.report.defs#reasonCivicInterference",
65
-
ToolsOzoneReportReasonCivicMisinformation: "tools.ozone.report.defs#reasonCivicMisinformation",
66
-
ToolsOzoneReportReasonCivicImpersonation: "tools.ozone.report.defs#reasonCivicImpersonation",
6
+
ReasonSpam,
7
+
ReasonViolation,
8
+
ReasonMisleading,
9
+
ReasonSexual,
10
+
ReasonRude,
11
+
ReasonOther,
12
+
ReasonAppeal,
13
+
tools.ozone.report.defs.ReasonAppeal,
14
+
tools.ozone.report.defs.ReasonViolenceAnimalWelfare,
15
+
tools.ozone.report.defs.ReasonViolenceThreats,
16
+
tools.ozone.report.defs.ReasonViolenceGraphicContent,
17
+
tools.ozone.report.defs.ReasonViolenceSelfHarm,
18
+
tools.ozone.report.defs.ReasonViolenceGlorification,
19
+
tools.ozone.report.defs.ReasonViolenceExtremistContent,
20
+
tools.ozone.report.defs.ReasonViolenceTrafficking,
21
+
tools.ozone.report.defs.ReasonViolenceOther,
22
+
tools.ozone.report.defs.ReasonSexualAbuseContent,
23
+
tools.ozone.report.defs.ReasonSexualNCII,
24
+
tools.ozone.report.defs.ReasonSexualSextortion,
25
+
tools.ozone.report.defs.ReasonSexualDeepfake,
26
+
tools.ozone.report.defs.ReasonSexualAnimal,
27
+
tools.ozone.report.defs.ReasonSexualUnlabeled,
28
+
tools.ozone.report.defs.ReasonSexualOther,
29
+
tools.ozone.report.defs.ReasonChildSafetyCSAM,
30
+
tools.ozone.report.defs.ReasonChildSafetyGroom,
31
+
tools.ozone.report.defs.ReasonChildSafetyMinorPrivacy,
32
+
tools.ozone.report.defs.ReasonChildSafetyEndangerment,
33
+
tools.ozone.report.defs.ReasonChildSafetyHarassment,
34
+
tools.ozone.report.defs.ReasonChildSafetyPromotion,
35
+
tools.ozone.report.defs.ReasonChildSafetyOther,
36
+
tools.ozone.report.defs.ReasonHarassmentTroll,
37
+
tools.ozone.report.defs.ReasonHarassmentTargeted,
38
+
tools.ozone.report.defs.ReasonHarassmentHateSpeech,
39
+
tools.ozone.report.defs.ReasonHarassmentDoxxing,
40
+
tools.ozone.report.defs.ReasonHarassmentOther,
41
+
tools.ozone.report.defs.ReasonMisleadingBot,
42
+
tools.ozone.report.defs.ReasonMisleadingImpersonation,
43
+
tools.ozone.report.defs.ReasonMisleadingSpam,
44
+
tools.ozone.report.defs.ReasonMisleadingScam,
45
+
tools.ozone.report.defs.ReasonMisleadingSyntheticContent,
46
+
tools.ozone.report.defs.ReasonMisleadingMisinformation,
47
+
tools.ozone.report.defs.ReasonMisleadingOther,
48
+
tools.ozone.report.defs.ReasonRuleSiteSecurity,
49
+
tools.ozone.report.defs.ReasonRuleStolenContent,
50
+
tools.ozone.report.defs.ReasonRuleProhibitedSales,
51
+
tools.ozone.report.defs.ReasonRuleBanEvasion,
52
+
tools.ozone.report.defs.ReasonRuleOther,
53
+
tools.ozone.report.defs.ReasonCivicElectoralProcess,
54
+
tools.ozone.report.defs.ReasonCivicDisclosure,
55
+
tools.ozone.report.defs.ReasonCivicInterference,
56
+
tools.ozone.report.defs.ReasonCivicMisinformation,
57
+
tools.ozone.report.defs.ReasonCivicImpersonation,
67
58
}
68
59
69
-
@doc("Spam: frequent unwanted promotion, replies, mentions. Prefer new lexicon definition `tools.ozone.report.defs#reasonMisleadingSpam`.")
60
+
/** Spam: frequent unwanted promotion, replies, mentions. Prefer new lexicon definition `tools.ozone.report.defs#reasonMisleadingSpam`. */
70
61
@token
71
62
model ReasonSpam {}
72
63
73
-
@doc("Direct violation of server rules, laws, terms of service. Prefer new lexicon definition `tools.ozone.report.defs#reasonRuleOther`.")
64
+
/** Direct violation of server rules, laws, terms of service. Prefer new lexicon definition `tools.ozone.report.defs#reasonRuleOther`. */
74
65
@token
75
66
model ReasonViolation {}
76
67
77
-
@doc("Misleading identity, affiliation, or content. Prefer new lexicon definition `tools.ozone.report.defs#reasonMisleadingOther`.")
68
+
/** Misleading identity, affiliation, or content. Prefer new lexicon definition `tools.ozone.report.defs#reasonMisleadingOther`. */
78
69
@token
79
70
model ReasonMisleading {}
80
71
81
-
@doc("Unwanted or mislabeled sexual content. Prefer new lexicon definition `tools.ozone.report.defs#reasonSexualUnlabeled`.")
72
+
/** Unwanted or mislabeled sexual content. Prefer new lexicon definition `tools.ozone.report.defs#reasonSexualUnlabeled`. */
82
73
@token
83
74
model ReasonSexual {}
84
75
85
-
@doc("Rude, harassing, explicit, or otherwise unwelcoming behavior. Prefer new lexicon definition `tools.ozone.report.defs#reasonHarassmentOther`.")
76
+
/** Rude, harassing, explicit, or otherwise unwelcoming behavior. Prefer new lexicon definition `tools.ozone.report.defs#reasonHarassmentOther`. */
86
77
@token
87
78
model ReasonRude {}
88
79
89
-
@doc("Reports not falling under another report category. Prefer new lexicon definition `tools.ozone.report.defs#reasonRuleOther`.")
80
+
/** Reports not falling under another report category. Prefer new lexicon definition `tools.ozone.report.defs#reasonRuleOther`. */
90
81
@token
91
82
model ReasonOther {}
92
83
93
-
@doc("Appeal a previously taken moderation action")
84
+
/** Appeal a previously taken moderation action */
94
85
@token
95
86
model ReasonAppeal {}
96
87
97
-
@doc("Tag describing a type of subject that might be reported.")
88
+
/** Tag describing a type of subject that might be reported. */
98
89
union SubjectType {
99
90
"account",
100
91
"record",
···
102
93
string,
103
94
}
104
95
}
96
+
97
+
// --- Externals ---
98
+
99
+
@external
100
+
namespace tools.ozone.report.defs {
101
+
@token model ReasonAppeal { }
102
+
@token model ReasonChildSafetyCSAM { }
103
+
@token model ReasonChildSafetyEndangerment { }
104
+
@token model ReasonChildSafetyGroom { }
105
+
@token model ReasonChildSafetyHarassment { }
106
+
@token model ReasonChildSafetyMinorPrivacy { }
107
+
@token model ReasonChildSafetyOther { }
108
+
@token model ReasonChildSafetyPromotion { }
109
+
@token model ReasonCivicDisclosure { }
110
+
@token model ReasonCivicElectoralProcess { }
111
+
@token model ReasonCivicImpersonation { }
112
+
@token model ReasonCivicInterference { }
113
+
@token model ReasonCivicMisinformation { }
114
+
@token model ReasonHarassmentDoxxing { }
115
+
@token model ReasonHarassmentHateSpeech { }
116
+
@token model ReasonHarassmentOther { }
117
+
@token model ReasonHarassmentTargeted { }
118
+
@token model ReasonHarassmentTroll { }
119
+
@token model ReasonMisleadingBot { }
120
+
@token model ReasonMisleadingImpersonation { }
121
+
@token model ReasonMisleadingMisinformation { }
122
+
@token model ReasonMisleadingOther { }
123
+
@token model ReasonMisleadingScam { }
124
+
@token model ReasonMisleadingSpam { }
125
+
@token model ReasonMisleadingSyntheticContent { }
126
+
@token model ReasonRuleBanEvasion { }
127
+
@token model ReasonRuleOther { }
128
+
@token model ReasonRuleProhibitedSales { }
129
+
@token model ReasonRuleSiteSecurity { }
130
+
@token model ReasonRuleStolenContent { }
131
+
@token model ReasonSexualAbuseContent { }
132
+
@token model ReasonSexualAnimal { }
133
+
@token model ReasonSexualDeepfake { }
134
+
@token model ReasonSexualNCII { }
135
+
@token model ReasonSexualOther { }
136
+
@token model ReasonSexualSextortion { }
137
+
@token model ReasonSexualUnlabeled { }
138
+
@token model ReasonViolenceAnimalWelfare { }
139
+
@token model ReasonViolenceExtremistContent { }
140
+
@token model ReasonViolenceGlorification { }
141
+
@token model ReasonViolenceGraphicContent { }
142
+
@token model ReasonViolenceOther { }
143
+
@token model ReasonViolenceSelfHarm { }
144
+
@token model ReasonViolenceThreats { }
145
+
@token model ReasonViolenceTrafficking { }
146
+
}
+16
-9
packages/emitter/test/integration/atproto/input/com/atproto/repo/applyWrites.tsp
+16
-9
packages/emitter/test/integration/atproto/input/com/atproto/repo/applyWrites.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace com.atproto.repo.applyWrites {
4
-
@doc("Indicates that the 'swapCommit' parameter did not match current commit.")
4
+
/** Indicates that the 'swapCommit' parameter did not match current commit. */
5
5
model InvalidSwap {}
6
6
7
7
@closed
···
20
20
DeleteResult,
21
21
}
22
22
23
-
@doc("Apply a batch transaction of repository creates, updates, and deletes. Requires auth, implemented by PDS.")
23
+
/** Apply a batch transaction of repository creates, updates, and deletes. Requires auth, implemented by PDS. */
24
24
@procedure
25
25
@errors(InvalidSwap)
26
26
op main(input: {
27
-
@doc("The handle or DID of the repo (aka, current account).")
27
+
/** The handle or DID of the repo (aka, current account). */
28
28
@required
29
29
repo: atIdentifier;
30
30
31
-
@doc("Can be set to 'false' to skip Lexicon schema validation of record data across all operations, 'true' to require it, or leave unset to validate only for known Lexicons.")
31
+
/** Can be set to 'false' to skip Lexicon schema validation of record data across all operations, 'true' to require it, or leave unset to validate only for known Lexicons. */
32
32
validate?: boolean;
33
33
34
34
@required
35
35
writes: WriteAction[];
36
36
37
-
@doc("If provided, the entire operation will fail if the current repo commit CID does not match this value. Used to prevent conflicting repo mutations.")
37
+
/** If provided, the entire operation will fail if the current repo commit CID does not match this value. Used to prevent conflicting repo mutations. */
38
38
swapCommit?: cid;
39
39
}): {
40
40
commit?: com.atproto.repo.defs.CommitMeta;
41
41
results?: WriteResult[];
42
42
};
43
43
44
-
@doc("Operation which creates a new record.")
44
+
/** Operation which creates a new record. */
45
45
model Create {
46
46
@required collection: nsid;
47
47
48
-
@doc("NOTE: maxLength is redundant with record-key format. Keeping it temporarily to ensure backwards compatibility.")
48
+
/** NOTE: maxLength is redundant with record-key format. Keeping it temporarily to ensure backwards compatibility. */
49
49
@maxLength(512)
50
50
rkey?: recordKey;
51
51
52
52
@required value: unknown;
53
53
}
54
54
55
-
@doc("Operation which updates an existing record.")
55
+
/** Operation which updates an existing record. */
56
56
model Update {
57
57
@required collection: nsid;
58
58
@required rkey: recordKey;
59
59
@required value: unknown;
60
60
}
61
61
62
-
@doc("Operation which deletes an existing record.")
62
+
/** Operation which deletes an existing record. */
63
63
model Delete {
64
64
@required collection: nsid;
65
65
@required rkey: recordKey;
···
79
79
80
80
model DeleteResult {}
81
81
}
82
+
83
+
// --- Externals ---
84
+
85
+
@external
86
+
namespace com.atproto.repo.defs {
87
+
model CommitMeta { }
88
+
}
+15
-8
packages/emitter/test/integration/atproto/input/com/atproto/repo/createRecord.tsp
+15
-8
packages/emitter/test/integration/atproto/input/com/atproto/repo/createRecord.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace com.atproto.repo.createRecord {
4
-
@doc("Create a single new repository record. Requires auth, implemented by PDS.")
4
+
/** Create a single new repository record. Requires auth, implemented by PDS. */
5
5
@errors(InvalidSwap)
6
6
@procedure
7
7
op main(input: {
8
-
@doc("The handle or DID of the repo (aka, current account).")
8
+
/** The handle or DID of the repo (aka, current account). */
9
9
@required
10
10
repo: atIdentifier;
11
11
12
-
@doc("The NSID of the record collection.")
12
+
/** The NSID of the record collection. */
13
13
@required
14
14
collection: nsid;
15
15
16
-
@doc("The Record Key.")
16
+
/** The Record Key. */
17
17
@maxLength(512)
18
18
rkey?: recordKey;
19
19
20
-
@doc("Can be set to 'false' to skip Lexicon schema validation of record data, 'true' to require it, or leave unset to validate only for known Lexicons.")
20
+
/** Can be set to 'false' to skip Lexicon schema validation of record data, 'true' to require it, or leave unset to validate only for known Lexicons. */
21
21
validate?: boolean;
22
22
23
-
@doc("The record itself. Must contain a $type field.")
23
+
/** The record itself. Must contain a $type field. */
24
24
@required
25
25
record: unknown;
26
26
27
-
@doc("Compare and swap with the previous commit by CID.")
27
+
/** Compare and swap with the previous commit by CID. */
28
28
swapCommit?: cid;
29
29
}): {
30
30
@required uri: atUri;
···
33
33
validationStatus?: "valid" | "unknown" | string;
34
34
};
35
35
36
-
@doc("Indicates that 'swapCommit' didn't match current repo commit.")
36
+
/** Indicates that 'swapCommit' didn't match current repo commit. */
37
37
model InvalidSwap {}
38
38
}
39
+
40
+
// --- Externals ---
41
+
42
+
@external
43
+
namespace com.atproto.repo.defs {
44
+
model CommitMeta { }
45
+
}
+13
-6
packages/emitter/test/integration/atproto/input/com/atproto/repo/deleteRecord.tsp
+13
-6
packages/emitter/test/integration/atproto/input/com/atproto/repo/deleteRecord.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace com.atproto.repo.deleteRecord {
4
-
@doc("Delete a repository record, or ensure it doesn't exist. Requires auth, implemented by PDS.")
4
+
/** Delete a repository record, or ensure it doesn't exist. Requires auth, implemented by PDS. */
5
5
@errors(InvalidSwap)
6
6
@procedure
7
7
op main(input: {
8
-
@doc("The handle or DID of the repo (aka, current account).")
8
+
/** The handle or DID of the repo (aka, current account). */
9
9
@required
10
10
repo: atIdentifier;
11
11
12
-
@doc("The NSID of the record collection.")
12
+
/** The NSID of the record collection. */
13
13
@required
14
14
collection: nsid;
15
15
16
-
@doc("The Record Key.")
16
+
/** The Record Key. */
17
17
@required
18
18
rkey: recordKey;
19
19
20
-
@doc("Compare and swap with the previous record by CID.")
20
+
/** Compare and swap with the previous record by CID. */
21
21
swapRecord?: cid;
22
22
23
-
@doc("Compare and swap with the previous commit by CID.")
23
+
/** Compare and swap with the previous commit by CID. */
24
24
swapCommit?: cid;
25
25
}): {
26
26
commit?: com.atproto.repo.defs.CommitMeta;
···
28
28
29
29
model InvalidSwap {}
30
30
}
31
+
32
+
// --- Externals ---
33
+
34
+
@external
35
+
namespace com.atproto.repo.defs {
36
+
model CommitMeta { }
37
+
}
+5
-5
packages/emitter/test/integration/atproto/input/com/atproto/repo/describeRepo.tsp
+5
-5
packages/emitter/test/integration/atproto/input/com/atproto/repo/describeRepo.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace com.atproto.repo.describeRepo {
4
-
@doc("Get information about an account and repository, including the list of collections. Does not require auth.")
4
+
/** Get information about an account and repository, including the list of collections. Does not require auth. */
5
5
@query
6
6
op main(
7
-
@doc("The handle or DID of the repo.")
7
+
/** The handle or DID of the repo. */
8
8
@required
9
9
repo: atIdentifier
10
10
): {
11
11
@required handle: handle;
12
12
@required did: did;
13
13
14
-
@doc("The complete DID document for this account.")
14
+
/** The complete DID document for this account. */
15
15
@required
16
16
didDoc: unknown;
17
17
18
-
@doc("List of all the collections (NSIDs) for which this repo contains at least one record.")
18
+
/** List of all the collections (NSIDs) for which this repo contains at least one record. */
19
19
@required
20
20
collections: nsid[];
21
21
22
-
@doc("Indicates if handle is currently valid (resolves bi-directionally)")
22
+
/** Indicates if handle is currently valid (resolves bi-directionally) */
23
23
@required
24
24
handleIsCorrect: boolean;
25
25
};
+5
-5
packages/emitter/test/integration/atproto/input/com/atproto/repo/getRecord.tsp
+5
-5
packages/emitter/test/integration/atproto/input/com/atproto/repo/getRecord.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace com.atproto.repo.getRecord {
4
-
@doc("Get a single record from a repository. Does not require auth.")
4
+
/** Get a single record from a repository. Does not require auth. */
5
5
@query
6
6
@errors(RecordNotFound)
7
7
op main(
8
-
@doc("The handle or DID of the repo.")
8
+
/** The handle or DID of the repo. */
9
9
@required
10
10
repo: atIdentifier,
11
11
12
-
@doc("The NSID of the record collection.")
12
+
/** The NSID of the record collection. */
13
13
@required
14
14
collection: nsid,
15
15
16
-
@doc("The Record Key.")
16
+
/** The Record Key. */
17
17
@required
18
18
rkey: recordKey,
19
19
20
-
@doc("The CID of the version of the record. If not specified, then return the most recent version.")
20
+
/** The CID of the version of the record. If not specified, then return the most recent version. */
21
21
cid?: cid
22
22
): {
23
23
@required uri: atUri;
+1
-1
packages/emitter/test/integration/atproto/input/com/atproto/repo/importRepo.tsp
+1
-1
packages/emitter/test/integration/atproto/input/com/atproto/repo/importRepo.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace com.atproto.repo.importRepo {
4
-
@doc("Import a repo in the form of a CAR file. Requires Content-Length HTTP header to be set.")
4
+
/** Import a repo in the form of a CAR file. Requires Content-Length HTTP header to be set. */
5
5
@procedure
6
6
op main(
7
7
@encoding("application/vnd.ipld.car")
+1
-1
packages/emitter/test/integration/atproto/input/com/atproto/repo/listMissingBlobs.tsp
+1
-1
packages/emitter/test/integration/atproto/input/com/atproto/repo/listMissingBlobs.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace com.atproto.repo.listMissingBlobs {
4
-
@doc("Returns a list of missing blobs for the requesting account. Intended to be used in the account migration flow.")
4
+
/** Returns a list of missing blobs for the requesting account. Intended to be used in the account migration flow. */
5
5
@query
6
6
op main(
7
7
@minValue(1)
+5
-5
packages/emitter/test/integration/atproto/input/com/atproto/repo/listRecords.tsp
+5
-5
packages/emitter/test/integration/atproto/input/com/atproto/repo/listRecords.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace com.atproto.repo.listRecords {
4
-
@doc("List a range of records in a repository, matching a specific collection. Does not require auth.")
4
+
/** List a range of records in a repository, matching a specific collection. Does not require auth. */
5
5
@query
6
6
op main(
7
-
@doc("The handle or DID of the repo.")
7
+
/** The handle or DID of the repo. */
8
8
@required
9
9
repo: atIdentifier,
10
10
11
-
@doc("The NSID of the record type.")
11
+
/** The NSID of the record type. */
12
12
@required
13
13
collection: nsid,
14
14
15
-
@doc("The number of records to return.")
15
+
/** The number of records to return. */
16
16
@minValue(1)
17
17
@maxValue(100)
18
18
limit?: int32 = 50,
19
19
20
20
cursor?: string,
21
21
22
-
@doc("Flag to reverse the order of the returned records.")
22
+
/** Flag to reverse the order of the returned records. */
23
23
reverse?: boolean
24
24
): {
25
25
cursor?: string;
+15
-8
packages/emitter/test/integration/atproto/input/com/atproto/repo/putRecord.tsp
+15
-8
packages/emitter/test/integration/atproto/input/com/atproto/repo/putRecord.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace com.atproto.repo.putRecord {
4
-
@doc("Write a repository record, creating or updating it as needed. Requires auth, implemented by PDS.")
4
+
/** Write a repository record, creating or updating it as needed. Requires auth, implemented by PDS. */
5
5
@errors(InvalidSwap)
6
6
@procedure
7
7
op main(input: {
8
-
@doc("The handle or DID of the repo (aka, current account).")
8
+
/** The handle or DID of the repo (aka, current account). */
9
9
@required
10
10
repo: atIdentifier;
11
11
12
-
@doc("The NSID of the record collection.")
12
+
/** The NSID of the record collection. */
13
13
@required
14
14
collection: nsid;
15
15
16
-
@doc("The Record Key.")
16
+
/** The Record Key. */
17
17
@maxLength(512)
18
18
@required
19
19
rkey: recordKey;
20
20
21
-
@doc("Can be set to 'false' to skip Lexicon schema validation of record data, 'true' to require it, or leave unset to validate only for known Lexicons.")
21
+
/** Can be set to 'false' to skip Lexicon schema validation of record data, 'true' to require it, or leave unset to validate only for known Lexicons. */
22
22
validate?: boolean;
23
23
24
-
@doc("The record to write.")
24
+
/** The record to write. */
25
25
@required
26
26
record: unknown;
27
27
28
-
@doc("Compare and swap with the previous record by CID. WARNING: nullable and optional field; may cause problems with golang implementation")
28
+
/** Compare and swap with the previous record by CID. WARNING: nullable and optional field; may cause problems with golang implementation */
29
29
swapRecord?: cid | null;
30
30
31
-
@doc("Compare and swap with the previous commit by CID.")
31
+
/** Compare and swap with the previous commit by CID. */
32
32
swapCommit?: cid;
33
33
}): {
34
34
@required uri: atUri;
···
39
39
40
40
model InvalidSwap {}
41
41
}
42
+
43
+
// --- Externals ---
44
+
45
+
@external
46
+
namespace com.atproto.repo.defs {
47
+
model CommitMeta { }
48
+
}
+1
-1
packages/emitter/test/integration/atproto/input/com/atproto/repo/strongRef.tsp
+1
-1
packages/emitter/test/integration/atproto/input/com/atproto/repo/strongRef.tsp
+1
-1
packages/emitter/test/integration/atproto/input/com/atproto/repo/uploadBlob.tsp
+1
-1
packages/emitter/test/integration/atproto/input/com/atproto/repo/uploadBlob.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace com.atproto.repo.uploadBlob {
4
-
@doc("Upload a new blob, to be referenced from a repository record. The blob will be deleted if it is not referenced within a time window (eg, minutes). Blob restrictions (mimetype, size, etc) are enforced when the reference is created. Requires auth, implemented by PDS.")
4
+
/** Upload a new blob, to be referenced from a repository record. The blob will be deleted if it is not referenced within a time window (eg, minutes). Blob restrictions (mimetype, size, etc) are enforced when the reference is created. Requires auth, implemented by PDS. */
5
5
@procedure
6
6
op main(
7
7
@encoding("*/*")
+1
-1
packages/emitter/test/integration/atproto/input/com/atproto/server/activateAccount.tsp
+1
-1
packages/emitter/test/integration/atproto/input/com/atproto/server/activateAccount.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace com.atproto.server.activateAccount {
4
-
@doc("Activates a currently deactivated account. Used to finalize account migration after the account's repo is imported and identity is setup.")
4
+
/** Activates a currently deactivated account. Used to finalize account migration after the account's repo is imported and identity is setup. */
5
5
@procedure
6
6
op main(): void;
7
7
}
+1
-1
packages/emitter/test/integration/atproto/input/com/atproto/server/checkAccountStatus.tsp
+1
-1
packages/emitter/test/integration/atproto/input/com/atproto/server/checkAccountStatus.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace com.atproto.server.checkAccountStatus {
4
-
@doc("Returns the status of an account, especially as pertaining to import or recovery. Can be called many times over the course of an account migration. Requires auth and can only be called pertaining to oneself.")
4
+
/** Returns the status of an account, especially as pertaining to import or recovery. Can be called many times over the course of an account migration. Requires auth and can only be called pertaining to oneself. */
5
5
@query
6
6
op main(): {
7
7
@required activated: boolean;
+1
-1
packages/emitter/test/integration/atproto/input/com/atproto/server/confirmEmail.tsp
+1
-1
packages/emitter/test/integration/atproto/input/com/atproto/server/confirmEmail.tsp
···
6
6
model InvalidToken {}
7
7
model InvalidEmail {}
8
8
9
-
@doc("Confirm an email using a token from com.atproto.server.requestEmailConfirmation.")
9
+
/** Confirm an email using a token from com.atproto.server.requestEmailConfirmation. */
10
10
@procedure
11
11
@errors(AccountNotFound, ExpiredToken, InvalidToken, InvalidEmail)
12
12
op main(input: {
+9
-9
packages/emitter/test/integration/atproto/input/com/atproto/server/createAccount.tsp
+9
-9
packages/emitter/test/integration/atproto/input/com/atproto/server/createAccount.tsp
···
9
9
model UnresolvableDid {}
10
10
model IncompatibleDidDoc {}
11
11
12
-
@doc("Account login session returned on successful account creation.")
12
+
/** Account login session returned on successful account creation. */
13
13
@inline
14
14
model Output {
15
15
@required accessJwt: string;
16
16
@required refreshJwt: string;
17
17
@required handle: handle;
18
18
19
-
@doc("The DID of the new account.")
19
+
/** The DID of the new account. */
20
20
@required
21
21
did: did;
22
22
23
-
@doc("Complete DID document.")
23
+
/** Complete DID document. */
24
24
didDoc?: unknown;
25
25
}
26
26
27
-
@doc("Create an account. Implemented by PDS.")
27
+
/** Create an account. Implemented by PDS. */
28
28
@procedure
29
29
@errors(InvalidHandle, InvalidPassword, InvalidInviteCode, HandleNotAvailable, UnsupportedDomain, UnresolvableDid, IncompatibleDidDoc)
30
30
op main(input: {
31
31
email?: string;
32
32
33
-
@doc("Requested handle for the account.")
33
+
/** Requested handle for the account. */
34
34
@required
35
35
handle: handle;
36
36
37
-
@doc("Pre-existing atproto DID, being imported to a new account.")
37
+
/** Pre-existing atproto DID, being imported to a new account. */
38
38
did?: did;
39
39
40
40
inviteCode?: string;
41
41
verificationCode?: string;
42
42
verificationPhone?: string;
43
43
44
-
@doc("Initial account password. May need to meet instance-specific password strength requirements.")
44
+
/** Initial account password. May need to meet instance-specific password strength requirements. */
45
45
password?: string;
46
46
47
-
@doc("DID PLC rotation key (aka, recovery key) to be included in PLC creation operation.")
47
+
/** DID PLC rotation key (aka, recovery key) to be included in PLC creation operation. */
48
48
recoveryKey?: string;
49
49
50
-
@doc("A signed DID PLC operation to be submitted as part of importing an existing account to this instance. NOTE: this optional field may be updated when full account migration is implemented.")
50
+
/** A signed DID PLC operation to be submitted as part of importing an existing account to this instance. NOTE: this optional field may be updated when full account migration is implemented. */
51
51
plcOp?: unknown;
52
52
}): Output;
53
53
}
+3
-3
packages/emitter/test/integration/atproto/input/com/atproto/server/createAppPassword.tsp
+3
-3
packages/emitter/test/integration/atproto/input/com/atproto/server/createAppPassword.tsp
···
10
10
privileged?: boolean;
11
11
}
12
12
13
-
@doc("Create an App Password.")
13
+
/** Create an App Password. */
14
14
@procedure
15
15
@errors(AccountTakedown)
16
16
op main(input: {
17
-
@doc("A short name for the App Password, to help distinguish them.")
17
+
/** A short name for the App Password, to help distinguish them. */
18
18
@required
19
19
name: string;
20
20
21
-
@doc("If an app password has 'privileged' access to possibly sensitive account state. Meant for use with trusted clients.")
21
+
/** If an app password has 'privileged' access to possibly sensitive account state. Meant for use with trusted clients. */
22
22
privileged?: boolean;
23
23
}): AppPassword;
24
24
}
+1
-1
packages/emitter/test/integration/atproto/input/com/atproto/server/createInviteCode.tsp
+1
-1
packages/emitter/test/integration/atproto/input/com/atproto/server/createInviteCode.tsp
+1
-1
packages/emitter/test/integration/atproto/input/com/atproto/server/createInviteCodes.tsp
+1
-1
packages/emitter/test/integration/atproto/input/com/atproto/server/createInviteCodes.tsp
+4
-4
packages/emitter/test/integration/atproto/input/com/atproto/server/createSession.tsp
+4
-4
packages/emitter/test/integration/atproto/input/com/atproto/server/createSession.tsp
···
5
5
6
6
model AuthFactorTokenRequired {}
7
7
8
-
@doc("Create an authentication session.")
8
+
/** Create an authentication session. */
9
9
@procedure
10
10
@errors(AccountTakedown, AuthFactorTokenRequired)
11
11
op main(input: {
12
-
@doc("Handle or other identifier supported by the server for the authenticating user.")
12
+
/** Handle or other identifier supported by the server for the authenticating user. */
13
13
@required
14
14
identifier: string;
15
15
···
17
17
18
18
authFactorToken?: string;
19
19
20
-
@doc("When true, instead of throwing error for takendown accounts, a valid response with a narrow scoped token will be returned")
20
+
/** When true, instead of throwing error for takendown accounts, a valid response with a narrow scoped token will be returned */
21
21
allowTakendown?: boolean;
22
22
}): {
23
23
@required accessJwt: string;
···
30
30
emailAuthFactor?: boolean;
31
31
active?: boolean;
32
32
33
-
@doc("If active=false, this optional field indicates a possible reason for why the account is not active. If active=false and no status is supplied, then the host makes no claim for why the repository is no longer being hosted.")
33
+
/** If active=false, this optional field indicates a possible reason for why the account is not active. If active=false and no status is supplied, then the host makes no claim for why the repository is no longer being hosted. */
34
34
status?: "takendown" | "suspended" | "deactivated" | string;
35
35
};
36
36
}
+2
-2
packages/emitter/test/integration/atproto/input/com/atproto/server/deactivateAccount.tsp
+2
-2
packages/emitter/test/integration/atproto/input/com/atproto/server/deactivateAccount.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace com.atproto.server.deactivateAccount {
4
-
@doc("Deactivates a currently active account. Stops serving of repo, and future writes to repo until reactivated. Used to finalize account migration with the old host after the account has been activated on the new host.")
4
+
/** Deactivates a currently active account. Stops serving of repo, and future writes to repo until reactivated. Used to finalize account migration with the old host after the account has been activated on the new host. */
5
5
@procedure
6
6
op main(input: {
7
-
@doc("A recommendation to server as to how long they should hold onto the deactivated account before deleting.")
7
+
/** A recommendation to server as to how long they should hold onto the deactivated account before deleting. */
8
8
deleteAfter?: datetime;
9
9
}): void;
10
10
}
+1
-1
packages/emitter/test/integration/atproto/input/com/atproto/server/deleteAccount.tsp
+1
-1
packages/emitter/test/integration/atproto/input/com/atproto/server/deleteAccount.tsp
···
4
4
model ExpiredToken {}
5
5
model InvalidToken {}
6
6
7
-
@doc("Delete an actor's account with a token and password. Can only be called after requesting a deletion token. Requires auth.")
7
+
/** Delete an actor's account with a token and password. Can only be called after requesting a deletion token. Requires auth. */
8
8
@procedure
9
9
@errors(ExpiredToken, InvalidToken)
10
10
op main(input: {
+1
-1
packages/emitter/test/integration/atproto/input/com/atproto/server/deleteSession.tsp
+1
-1
packages/emitter/test/integration/atproto/input/com/atproto/server/deleteSession.tsp
+6
-6
packages/emitter/test/integration/atproto/input/com/atproto/server/describeServer.tsp
+6
-6
packages/emitter/test/integration/atproto/input/com/atproto/server/describeServer.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace com.atproto.server.describeServer {
4
-
@doc("Describes the server's account creation requirements and capabilities. Implemented by PDS.")
4
+
/** Describes the server's account creation requirements and capabilities. Implemented by PDS. */
5
5
@query
6
6
op main(): {
7
7
@required did: did;
8
8
9
-
@doc("If true, an invite code must be supplied to create an account on this instance.")
9
+
/** If true, an invite code must be supplied to create an account on this instance. */
10
10
inviteCodeRequired?: boolean;
11
11
12
-
@doc("If true, a phone verification token must be supplied to create an account on this instance.")
12
+
/** If true, a phone verification token must be supplied to create an account on this instance. */
13
13
phoneVerificationRequired?: boolean;
14
14
15
-
@doc("List of domain suffixes that can be used in account handles.")
15
+
/** List of domain suffixes that can be used in account handles. */
16
16
@required
17
17
availableUserDomains: string[];
18
18
19
-
@doc("URLs of service policy documents.")
19
+
/** URLs of service policy documents. */
20
20
links?: Links;
21
21
22
-
@doc("Contact information")
22
+
/** Contact information */
23
23
contact?: Contact;
24
24
};
25
25
+9
-2
packages/emitter/test/integration/atproto/input/com/atproto/server/getAccountInviteCodes.tsp
+9
-2
packages/emitter/test/integration/atproto/input/com/atproto/server/getAccountInviteCodes.tsp
···
3
3
namespace com.atproto.server.getAccountInviteCodes {
4
4
model DuplicateCreate {}
5
5
6
-
@doc("Get all invite codes for the current account. Requires auth.")
6
+
/** Get all invite codes for the current account. Requires auth. */
7
7
@query
8
8
@errors(DuplicateCreate)
9
9
op main(
10
10
includeUsed?: boolean = true,
11
11
12
-
@doc("Controls whether any new 'earned' but not 'created' invites should be created.")
12
+
/** Controls whether any new 'earned' but not 'created' invites should be created. */
13
13
createAvailable?: boolean = true
14
14
): {
15
15
@required codes: com.atproto.server.defs.InviteCode[];
16
16
};
17
17
}
18
+
19
+
// --- Externals ---
20
+
21
+
@external
22
+
namespace com.atproto.server.defs {
23
+
model InviteCode { }
24
+
}
+5
-5
packages/emitter/test/integration/atproto/input/com/atproto/server/getServiceAuth.tsp
+5
-5
packages/emitter/test/integration/atproto/input/com/atproto/server/getServiceAuth.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace com.atproto.server.getServiceAuth {
4
-
@doc("Indicates that the requested expiration date is not a valid. May be in the past or may be reliant on the requested scopes.")
4
+
/** Indicates that the requested expiration date is not a valid. May be in the past or may be reliant on the requested scopes. */
5
5
model BadExpiration {}
6
6
7
-
@doc("Get a signed token on behalf of the requesting DID for the requested service.")
7
+
/** Get a signed token on behalf of the requesting DID for the requested service. */
8
8
@query
9
9
@errors(BadExpiration)
10
10
op main(
11
-
@doc("The DID of the service that the token will be used to authenticate with")
11
+
/** The DID of the service that the token will be used to authenticate with */
12
12
@required
13
13
aud: did,
14
14
15
-
@doc("The time in Unix Epoch seconds that the JWT expires. Defaults to 60 seconds in the future. The service may enforce certain time bounds on tokens depending on the requested scope.")
15
+
/** The time in Unix Epoch seconds that the JWT expires. Defaults to 60 seconds in the future. The service may enforce certain time bounds on tokens depending on the requested scope. */
16
16
exp?: integer,
17
17
18
-
@doc("Lexicon (XRPC) method to bind the requested token to")
18
+
/** Lexicon (XRPC) method to bind the requested token to */
19
19
lxm?: nsid
20
20
): {
21
21
@required token: string;
+2
-2
packages/emitter/test/integration/atproto/input/com/atproto/server/getSession.tsp
+2
-2
packages/emitter/test/integration/atproto/input/com/atproto/server/getSession.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace com.atproto.server.getSession {
4
-
@doc("Get information about the current auth session. Requires auth.")
4
+
/** Get information about the current auth session. Requires auth. */
5
5
@query
6
6
op main(): {
7
7
@required handle: handle;
···
12
12
didDoc?: unknown;
13
13
active?: boolean;
14
14
15
-
@doc("If active=false, this optional field indicates a possible reason for why the account is not active. If active=false and no status is supplied, then the host makes no claim for why the repository is no longer being hosted.")
15
+
/** If active=false, this optional field indicates a possible reason for why the account is not active. If active=false and no status is supplied, then the host makes no claim for why the repository is no longer being hosted. */
16
16
status?: "takendown" | "suspended" | "deactivated" | string;
17
17
};
18
18
}
+1
-1
packages/emitter/test/integration/atproto/input/com/atproto/server/listAppPasswords.tsp
+1
-1
packages/emitter/test/integration/atproto/input/com/atproto/server/listAppPasswords.tsp
+2
-2
packages/emitter/test/integration/atproto/input/com/atproto/server/refreshSession.tsp
+2
-2
packages/emitter/test/integration/atproto/input/com/atproto/server/refreshSession.tsp
···
3
3
namespace com.atproto.server.refreshSession {
4
4
model AccountTakedown {}
5
5
6
-
@doc("Refresh an authentication session. Requires auth using the 'refreshJwt' (not the 'accessJwt').")
6
+
/** Refresh an authentication session. Requires auth using the 'refreshJwt' (not the 'accessJwt'). */
7
7
@procedure
8
8
@errors(AccountTakedown)
9
9
op main(): {
···
14
14
didDoc?: unknown;
15
15
active?: boolean;
16
16
17
-
@doc("Hosting status of the account. If not specified, then assume 'active'.")
17
+
/** Hosting status of the account. If not specified, then assume 'active'. */
18
18
status?: "takendown" | "suspended" | "deactivated" | string;
19
19
};
20
20
}
+1
-1
packages/emitter/test/integration/atproto/input/com/atproto/server/requestAccountDelete.tsp
+1
-1
packages/emitter/test/integration/atproto/input/com/atproto/server/requestAccountDelete.tsp
+1
-1
packages/emitter/test/integration/atproto/input/com/atproto/server/requestEmailConfirmation.tsp
+1
-1
packages/emitter/test/integration/atproto/input/com/atproto/server/requestEmailConfirmation.tsp
+1
-1
packages/emitter/test/integration/atproto/input/com/atproto/server/requestEmailUpdate.tsp
+1
-1
packages/emitter/test/integration/atproto/input/com/atproto/server/requestEmailUpdate.tsp
+1
-1
packages/emitter/test/integration/atproto/input/com/atproto/server/requestPasswordReset.tsp
+1
-1
packages/emitter/test/integration/atproto/input/com/atproto/server/requestPasswordReset.tsp
+3
-3
packages/emitter/test/integration/atproto/input/com/atproto/server/reserveSigningKey.tsp
+3
-3
packages/emitter/test/integration/atproto/input/com/atproto/server/reserveSigningKey.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace com.atproto.server.reserveSigningKey {
4
-
@doc("Reserve a repo signing key, for use with account creation. Necessary so that a DID PLC update operation can be constructed during an account migraiton. Public and does not require auth; implemented by PDS. NOTE: this endpoint may change when full account migration is implemented.")
4
+
/** Reserve a repo signing key, for use with account creation. Necessary so that a DID PLC update operation can be constructed during an account migraiton. Public and does not require auth; implemented by PDS. NOTE: this endpoint may change when full account migration is implemented. */
5
5
@procedure
6
6
op main(input: {
7
-
@doc("The DID to reserve a key for.")
7
+
/** The DID to reserve a key for. */
8
8
did?: did;
9
9
}): {
10
-
@doc("The public key for the reserved signing key, in did:key serialization.")
10
+
/** The public key for the reserved signing key, in did:key serialization. */
11
11
@required
12
12
signingKey: string;
13
13
};
+1
-1
packages/emitter/test/integration/atproto/input/com/atproto/server/resetPassword.tsp
+1
-1
packages/emitter/test/integration/atproto/input/com/atproto/server/resetPassword.tsp
+1
-1
packages/emitter/test/integration/atproto/input/com/atproto/server/revokeAppPassword.tsp
+1
-1
packages/emitter/test/integration/atproto/input/com/atproto/server/revokeAppPassword.tsp
+2
-2
packages/emitter/test/integration/atproto/input/com/atproto/server/updateEmail.tsp
+2
-2
packages/emitter/test/integration/atproto/input/com/atproto/server/updateEmail.tsp
···
5
5
model InvalidToken {}
6
6
model TokenRequired {}
7
7
8
-
@doc("Update an account's email.")
8
+
/** Update an account's email. */
9
9
@procedure
10
10
@errors(ExpiredToken, InvalidToken, TokenRequired)
11
11
op main(input: {
12
12
@required email: string;
13
13
emailAuthFactor?: boolean;
14
14
15
-
@doc("Requires a token from com.atproto.sever.requestEmailUpdate if the account's email has been confirmed.")
15
+
/** Requires a token from com.atproto.sever.requestEmailUpdate if the account's email has been confirmed. */
16
16
token?: string;
17
17
}): void;
18
18
}
+3
-3
packages/emitter/test/integration/atproto/input/com/atproto/sync/getBlob.tsp
+3
-3
packages/emitter/test/integration/atproto/input/com/atproto/sync/getBlob.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace com.atproto.sync.getBlob {
4
-
@doc("Get a blob associated with a given account. Returns the full blob as originally uploaded. Does not require auth; implemented by PDS.")
4
+
/** Get a blob associated with a given account. Returns the full blob as originally uploaded. Does not require auth; implemented by PDS. */
5
5
@query
6
6
@encoding("*/*")
7
7
@errors(BlobNotFound, RepoNotFound, RepoTakendown, RepoSuspended, RepoDeactivated)
8
8
op main(
9
-
@doc("The DID of the account.")
9
+
/** The DID of the account. */
10
10
@required
11
11
did: did,
12
12
13
-
@doc("The CID of the blob to fetch")
13
+
/** The CID of the blob to fetch */
14
14
@required
15
15
cid: cid
16
16
): void;
+2
-2
packages/emitter/test/integration/atproto/input/com/atproto/sync/getBlocks.tsp
+2
-2
packages/emitter/test/integration/atproto/input/com/atproto/sync/getBlocks.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace com.atproto.sync.getBlocks {
4
-
@doc("Get data blocks from a given repo, by CID. For example, intermediate MST nodes, or records. Does not require auth; implemented by PDS.")
4
+
/** Get data blocks from a given repo, by CID. For example, intermediate MST nodes, or records. Does not require auth; implemented by PDS. */
5
5
@query
6
6
@encoding("application/vnd.ipld.car")
7
7
@errors(BlockNotFound, RepoNotFound, RepoTakendown, RepoSuspended, RepoDeactivated)
8
8
op main(
9
-
@doc("The DID of the repo.")
9
+
/** The DID of the repo. */
10
10
@required
11
11
did: did,
12
12
+2
-2
packages/emitter/test/integration/atproto/input/com/atproto/sync/getCheckout.tsp
+2
-2
packages/emitter/test/integration/atproto/input/com/atproto/sync/getCheckout.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace com.atproto.sync.getCheckout {
4
-
@doc("DEPRECATED - please use com.atproto.sync.getRepo instead")
4
+
/** DEPRECATED - please use com.atproto.sync.getRepo instead */
5
5
@query
6
6
@encoding("application/vnd.ipld.car")
7
7
op main(
8
-
@doc("The DID of the repo.")
8
+
/** The DID of the repo. */
9
9
@required
10
10
did: did
11
11
): void;
+2
-2
packages/emitter/test/integration/atproto/input/com/atproto/sync/getHead.tsp
+2
-2
packages/emitter/test/integration/atproto/input/com/atproto/sync/getHead.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace com.atproto.sync.getHead {
4
-
@doc("DEPRECATED - please use com.atproto.sync.getLatestCommit instead")
4
+
/** DEPRECATED - please use com.atproto.sync.getLatestCommit instead */
5
5
@query
6
6
@errors(HeadNotFound)
7
7
op main(
8
-
@doc("The DID of the repo.")
8
+
/** The DID of the repo. */
9
9
@required
10
10
did: did
11
11
): {
+11
-4
packages/emitter/test/integration/atproto/input/com/atproto/sync/getHostStatus.tsp
+11
-4
packages/emitter/test/integration/atproto/input/com/atproto/sync/getHostStatus.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace com.atproto.sync.getHostStatus {
4
-
@doc("Returns information about a specified upstream host, as consumed by the server. Implemented by relays.")
4
+
/** Returns information about a specified upstream host, as consumed by the server. Implemented by relays. */
5
5
@query
6
6
@errors(HostNotFound)
7
7
op main(
8
-
@doc("Hostname of the host (eg, PDS or relay) being queried.")
8
+
/** Hostname of the host (eg, PDS or relay) being queried. */
9
9
@required
10
10
hostname: string
11
11
): {
12
12
@required hostname: string;
13
13
14
-
@doc("Recent repo stream event sequence number. May be delayed from actual stream processing (eg, persisted cursor not in-memory cursor).")
14
+
/** Recent repo stream event sequence number. May be delayed from actual stream processing (eg, persisted cursor not in-memory cursor). */
15
15
seq?: integer;
16
16
17
-
@doc("Number of accounts on the server which are associated with the upstream host. Note that the upstream may actually have more accounts.")
17
+
/** Number of accounts on the server which are associated with the upstream host. Note that the upstream may actually have more accounts. */
18
18
accountCount?: integer;
19
19
20
20
status?: com.atproto.sync.defs.HostStatus;
···
22
22
23
23
model HostNotFound {}
24
24
}
25
+
26
+
// --- Externals ---
27
+
28
+
@external
29
+
namespace com.atproto.sync.defs {
30
+
model HostStatus { }
31
+
}
+2
-2
packages/emitter/test/integration/atproto/input/com/atproto/sync/getLatestCommit.tsp
+2
-2
packages/emitter/test/integration/atproto/input/com/atproto/sync/getLatestCommit.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace com.atproto.sync.getLatestCommit {
4
-
@doc("Get the current commit CID & revision of the specified repo. Does not require auth.")
4
+
/** Get the current commit CID & revision of the specified repo. Does not require auth. */
5
5
@query
6
6
@errors(RepoNotFound, RepoTakendown, RepoSuspended, RepoDeactivated)
7
7
op main(
8
-
@doc("The DID of the repo.")
8
+
/** The DID of the repo. */
9
9
@required
10
10
did: did
11
11
): {
+3
-3
packages/emitter/test/integration/atproto/input/com/atproto/sync/getRecord.tsp
+3
-3
packages/emitter/test/integration/atproto/input/com/atproto/sync/getRecord.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace com.atproto.sync.getRecord {
4
-
@doc("Get data blocks needed to prove the existence or non-existence of record in the current version of repo. Does not require auth.")
4
+
/** Get data blocks needed to prove the existence or non-existence of record in the current version of repo. Does not require auth. */
5
5
@query
6
6
@encoding("application/vnd.ipld.car")
7
7
@errors(RecordNotFound, RepoNotFound, RepoTakendown, RepoSuspended, RepoDeactivated)
8
8
op main(
9
-
@doc("The DID of the repo.")
9
+
/** The DID of the repo. */
10
10
@required
11
11
did: did,
12
12
13
13
@required collection: nsid,
14
14
15
-
@doc("Record Key")
15
+
/** Record Key */
16
16
@required
17
17
rkey: recordKey
18
18
): void;
+3
-3
packages/emitter/test/integration/atproto/input/com/atproto/sync/getRepo.tsp
+3
-3
packages/emitter/test/integration/atproto/input/com/atproto/sync/getRepo.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace com.atproto.sync.getRepo {
4
-
@doc("Download a repository export as CAR file. Optionally only a 'diff' since a previous revision. Does not require auth; implemented by PDS.")
4
+
/** Download a repository export as CAR file. Optionally only a 'diff' since a previous revision. Does not require auth; implemented by PDS. */
5
5
@query
6
6
@encoding("application/vnd.ipld.car")
7
7
@errors(RepoNotFound, RepoTakendown, RepoSuspended, RepoDeactivated)
8
8
op main(
9
-
@doc("The DID of the repo.")
9
+
/** The DID of the repo. */
10
10
@required
11
11
did: did,
12
12
13
-
@doc("The revision ('rev') of the repo to create a diff from.")
13
+
/** The revision ('rev') of the repo to create a diff from. */
14
14
since?: tid
15
15
): void;
16
16
+4
-4
packages/emitter/test/integration/atproto/input/com/atproto/sync/getRepoStatus.tsp
+4
-4
packages/emitter/test/integration/atproto/input/com/atproto/sync/getRepoStatus.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace com.atproto.sync.getRepoStatus {
4
-
@doc("Get the hosting status for a repository, on this server. Expected to be implemented by PDS and Relay.")
4
+
/** Get the hosting status for a repository, on this server. Expected to be implemented by PDS and Relay. */
5
5
@query
6
6
@errors(RepoNotFound)
7
7
op main(
8
-
@doc("The DID of the repo.")
8
+
/** The DID of the repo. */
9
9
@required
10
10
did: did
11
11
): {
12
12
@required did: did;
13
13
@required active: boolean;
14
14
15
-
@doc("If active=false, this optional field indicates a possible reason for why the account is not active. If active=false and no status is supplied, then the host makes no claim for why the repository is no longer being hosted.")
15
+
/** If active=false, this optional field indicates a possible reason for why the account is not active. If active=false and no status is supplied, then the host makes no claim for why the repository is no longer being hosted. */
16
16
status?: "takendown" | "suspended" | "deleted" | "deactivated" | "desynchronized" | "throttled" | string;
17
17
18
-
@doc("Optional field, the current rev of the repo, if active=true")
18
+
/** Optional field, the current rev of the repo, if active=true */
19
19
rev?: tid;
20
20
};
21
21
+3
-3
packages/emitter/test/integration/atproto/input/com/atproto/sync/listBlobs.tsp
+3
-3
packages/emitter/test/integration/atproto/input/com/atproto/sync/listBlobs.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace com.atproto.sync.listBlobs {
4
-
@doc("List blob CIDs for an account, since some repo revision. Does not require auth; implemented by PDS.")
4
+
/** List blob CIDs for an account, since some repo revision. Does not require auth; implemented by PDS. */
5
5
@query
6
6
@errors(RepoNotFound, RepoTakendown, RepoSuspended, RepoDeactivated)
7
7
op main(
8
-
@doc("The DID of the repo.")
8
+
/** The DID of the repo. */
9
9
@required
10
10
did: did,
11
11
12
-
@doc("Optional revision of the repo to list blobs since.")
12
+
/** Optional revision of the repo to list blobs since. */
13
13
since?: tid,
14
14
15
15
@minValue(1)
+11
-4
packages/emitter/test/integration/atproto/input/com/atproto/sync/listHosts.tsp
+11
-4
packages/emitter/test/integration/atproto/input/com/atproto/sync/listHosts.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace com.atproto.sync.listHosts {
4
-
@doc("Enumerates upstream hosts (eg, PDS or relay instances) that this service consumes from. Implemented by relays.")
4
+
/** Enumerates upstream hosts (eg, PDS or relay instances) that this service consumes from. Implemented by relays. */
5
5
@query
6
6
op main(
7
7
@minValue(1)
···
12
12
): {
13
13
cursor?: string;
14
14
15
-
@doc("Sort order is not formally specified. Recommended order is by time host was first seen by the server, with oldest first.")
15
+
/** Sort order is not formally specified. Recommended order is by time host was first seen by the server, with oldest first. */
16
16
@required
17
17
hosts: Host[];
18
18
};
19
19
20
20
model Host {
21
-
@doc("hostname of server; not a URL (no scheme)")
21
+
/** hostname of server; not a URL (no scheme) */
22
22
@required
23
23
hostname: string;
24
24
25
-
@doc("Recent repo stream event sequence number. May be delayed from actual stream processing (eg, persisted cursor not in-memory cursor).")
25
+
/** Recent repo stream event sequence number. May be delayed from actual stream processing (eg, persisted cursor not in-memory cursor). */
26
26
seq?: integer;
27
27
28
28
accountCount?: integer;
29
29
status?: com.atproto.sync.defs.HostStatus;
30
30
}
31
31
}
32
+
33
+
// --- Externals ---
34
+
35
+
@external
36
+
namespace com.atproto.sync.defs {
37
+
model HostStatus { }
38
+
}
+3
-3
packages/emitter/test/integration/atproto/input/com/atproto/sync/listRepos.tsp
+3
-3
packages/emitter/test/integration/atproto/input/com/atproto/sync/listRepos.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace com.atproto.sync.listRepos {
4
-
@doc("Enumerates all the DID, rev, and commit CID for all repos hosted by this service. Does not require auth; implemented by PDS and Relay.")
4
+
/** Enumerates all the DID, rev, and commit CID for all repos hosted by this service. Does not require auth; implemented by PDS and Relay. */
5
5
@query
6
6
op main(
7
7
@minValue(1)
···
17
17
model Repo {
18
18
@required did: did;
19
19
20
-
@doc("Current repo commit CID")
20
+
/** Current repo commit CID */
21
21
@required
22
22
head: cid;
23
23
24
24
@required rev: tid;
25
25
active?: boolean;
26
26
27
-
@doc("If active=false, this optional field indicates a possible reason for why the account is not active. If active=false and no status is supplied, then the host makes no claim for why the repository is no longer being hosted.")
27
+
/** If active=false, this optional field indicates a possible reason for why the account is not active. If active=false and no status is supplied, then the host makes no claim for why the repository is no longer being hosted. */
28
28
status?: "takendown" | "suspended" | "deleted" | "deactivated" | "desynchronized" | "throttled" | string;
29
29
}
30
30
}
+2
-2
packages/emitter/test/integration/atproto/input/com/atproto/sync/listReposByCollection.tsp
+2
-2
packages/emitter/test/integration/atproto/input/com/atproto/sync/listReposByCollection.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace com.atproto.sync.listReposByCollection {
4
-
@doc("Enumerates all the DIDs which have records with the given collection NSID.")
4
+
/** Enumerates all the DIDs which have records with the given collection NSID. */
5
5
@query
6
6
op main(
7
7
@required collection: nsid,
8
8
9
-
@doc("Maximum size of response set. Recommend setting a large maximum (1000+) when enumerating large DID lists.")
9
+
/** Maximum size of response set. Recommend setting a large maximum (1000+) when enumerating large DID lists. */
10
10
@minValue(1)
11
11
@maxValue(2000)
12
12
limit?: int32 = 500,
+2
-2
packages/emitter/test/integration/atproto/input/com/atproto/sync/notifyOfUpdate.tsp
+2
-2
packages/emitter/test/integration/atproto/input/com/atproto/sync/notifyOfUpdate.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace com.atproto.sync.notifyOfUpdate {
4
-
@doc("Notify a crawling service of a recent update, and that crawling should resume. Intended use is after a gap between repo stream events caused the crawling service to disconnect. Does not require auth; implemented by Relay. DEPRECATED: just use com.atproto.sync.requestCrawl")
4
+
/** Notify a crawling service of a recent update, and that crawling should resume. Intended use is after a gap between repo stream events caused the crawling service to disconnect. Does not require auth; implemented by Relay. DEPRECATED: just use com.atproto.sync.requestCrawl */
5
5
@procedure
6
6
op main(input: {
7
-
@doc("Hostname of the current service (usually a PDS) that is notifying of update.")
7
+
/** Hostname of the current service (usually a PDS) that is notifying of update. */
8
8
@required
9
9
hostname: string;
10
10
}): void;
+2
-2
packages/emitter/test/integration/atproto/input/com/atproto/sync/requestCrawl.tsp
+2
-2
packages/emitter/test/integration/atproto/input/com/atproto/sync/requestCrawl.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace com.atproto.sync.requestCrawl {
4
-
@doc("Request a service to persistently crawl hosted repos. Expected use is new PDS instances declaring their existence to Relays. Does not require auth.")
4
+
/** Request a service to persistently crawl hosted repos. Expected use is new PDS instances declaring their existence to Relays. Does not require auth. */
5
5
@procedure
6
6
@errors(HostBanned)
7
7
op main(input: {
8
-
@doc("Hostname of the current service (eg, PDS) that is requesting to be crawled.")
8
+
/** Hostname of the current service (eg, PDS) that is requesting to be crawled. */
9
9
@required
10
10
hostname: string;
11
11
}): void;
+30
-30
packages/emitter/test/integration/atproto/input/com/atproto/sync/subscribeRepos.tsp
+30
-30
packages/emitter/test/integration/atproto/input/com/atproto/sync/subscribeRepos.tsp
···
3
3
namespace com.atproto.sync.subscribeRepos {
4
4
@subscription
5
5
@errors(FutureCursor, ConsumerTooSlow)
6
-
@doc("Repository event stream, aka Firehose endpoint. Outputs repo commits with diff data, and identity update events, for all repositories on the current server. See the atproto specifications for details around stream sequencing, repo versioning, CAR diff format, and more. Public and does not require auth; implemented by PDS and Relay.")
6
+
/** Repository event stream, aka Firehose endpoint. Outputs repo commits with diff data, and identity update events, for all repositories on the current server. See the atproto specifications for details around stream sequencing, repo versioning, CAR diff format, and more. Public and does not require auth; implemented by PDS and Relay. */
7
7
op main(
8
-
@doc("The last known event seq number to backfill from.")
8
+
/** The last known event seq number to backfill from. */
9
9
cursor?: integer
10
10
): (Commit | Sync | Identity | Account | Info | unknown);
11
11
12
12
model FutureCursor {}
13
13
14
-
@doc("If the consumer of the stream can not keep up with events, and a backlog gets too large, the server will drop the connection.")
14
+
/** If the consumer of the stream can not keep up with events, and a backlog gets too large, the server will drop the connection. */
15
15
model ConsumerTooSlow {}
16
16
17
-
@doc("Represents an update of repository state. Note that empty commits are allowed, which include no repo data changes, but an update to rev and signature.")
17
+
/** Represents an update of repository state. Note that empty commits are allowed, which include no repo data changes, but an update to rev and signature. */
18
18
model Commit {
19
-
@doc("The stream sequence number of this message.")
19
+
/** The stream sequence number of this message. */
20
20
@required
21
21
seq: integer;
22
22
23
-
@doc("DEPRECATED -- unused")
23
+
/** DEPRECATED -- unused */
24
24
@required
25
25
rebase: boolean;
26
26
27
-
@doc("DEPRECATED -- replaced by #sync event and data limits. Indicates that this commit contained too many ops, or data size was too large. Consumers will need to make a separate request to get missing data.")
27
+
/** DEPRECATED -- replaced by #sync event and data limits. Indicates that this commit contained too many ops, or data size was too large. Consumers will need to make a separate request to get missing data. */
28
28
@required
29
29
tooBig: boolean;
30
30
31
-
@doc("The repo this event comes from. Note that all other message types name this field 'did'.")
31
+
/** The repo this event comes from. Note that all other message types name this field 'did'. */
32
32
@required
33
33
repo: did;
34
34
35
-
@doc("Repo commit object CID.")
35
+
/** Repo commit object CID. */
36
36
@required
37
37
commit: cidLink;
38
38
39
-
@doc("The rev of the emitted commit. Note that this information is also in the commit object included in blocks, unless this is a tooBig event.")
39
+
/** The rev of the emitted commit. Note that this information is also in the commit object included in blocks, unless this is a tooBig event. */
40
40
@required
41
41
rev: tid;
42
42
43
-
@doc("The rev of the last emitted commit from this repo (if any).")
43
+
/** The rev of the last emitted commit from this repo (if any). */
44
44
@required
45
45
since: tid | null;
46
46
47
-
@doc("CAR file containing relevant blocks, as a diff since the previous repo state. The commit must be included as a block, and the commit block CID must be the first entry in the CAR header 'roots' list.")
47
+
/** CAR file containing relevant blocks, as a diff since the previous repo state. The commit must be included as a block, and the commit block CID must be the first entry in the CAR header 'roots' list. */
48
48
@maxBytes(2000000)
49
49
@required
50
50
blocks: bytes;
51
51
52
52
@maxItems(200)
53
53
@required
54
-
@doc("List of repo mutation operations in this commit (eg, records created, updated, or deleted).")
54
+
/** List of repo mutation operations in this commit (eg, records created, updated, or deleted). */
55
55
ops: RepoOp[];
56
56
57
-
@doc("DEPRECATED -- will soon always be empty. List of new blobs (by CID) referenced by records in this commit.")
57
+
/** DEPRECATED -- will soon always be empty. List of new blobs (by CID) referenced by records in this commit. */
58
58
@required blobs: cidLink[];
59
59
60
-
@doc("The root CID of the MST tree for the previous commit from this repo (indicated by the 'since' revision field in this message). Corresponds to the 'data' field in the repo commit object. NOTE: this field is effectively required for the 'inductive' version of firehose.")
60
+
/** The root CID of the MST tree for the previous commit from this repo (indicated by the 'since' revision field in this message). Corresponds to the 'data' field in the repo commit object. NOTE: this field is effectively required for the 'inductive' version of firehose. */
61
61
prevData?: cidLink;
62
62
63
-
@doc("Timestamp of when this message was originally broadcast.")
63
+
/** Timestamp of when this message was originally broadcast. */
64
64
@required
65
65
time: datetime;
66
66
}
67
67
68
-
@doc("Updates the repo to a new state, without necessarily including that state on the firehose. Used to recover from broken commit streams, data loss incidents, or in situations where upstream host does not know recent state of the repository.")
68
+
/** Updates the repo to a new state, without necessarily including that state on the firehose. Used to recover from broken commit streams, data loss incidents, or in situations where upstream host does not know recent state of the repository. */
69
69
model Sync {
70
-
@doc("The stream sequence number of this message.")
70
+
/** The stream sequence number of this message. */
71
71
@required
72
72
seq: integer;
73
73
74
-
@doc("The account this repo event corresponds to. Must match that in the commit object.")
74
+
/** The account this repo event corresponds to. Must match that in the commit object. */
75
75
@required
76
76
did: did;
77
77
78
-
@doc("CAR file containing the commit, as a block. The CAR header must include the commit block CID as the first 'root'.")
78
+
/** CAR file containing the commit, as a block. The CAR header must include the commit block CID as the first 'root'. */
79
79
@maxBytes(10000)
80
80
@required
81
81
blocks: bytes;
82
82
83
-
@doc("The rev of the commit. This value must match that in the commit object.")
83
+
/** The rev of the commit. This value must match that in the commit object. */
84
84
@required
85
85
rev: string;
86
86
87
-
@doc("Timestamp of when this message was originally broadcast.")
87
+
/** Timestamp of when this message was originally broadcast. */
88
88
@required
89
89
time: datetime;
90
90
}
91
91
92
-
@doc("Represents a change to an account's identity. Could be an updated handle, signing key, or pds hosting endpoint. Serves as a prod to all downstream services to refresh their identity cache.")
92
+
/** Represents a change to an account's identity. Could be an updated handle, signing key, or pds hosting endpoint. Serves as a prod to all downstream services to refresh their identity cache. */
93
93
model Identity {
94
94
@required seq: integer;
95
95
@required did: did;
96
96
@required time: datetime;
97
97
98
-
@doc("The current handle for the account, or 'handle.invalid' if validation fails. This field is optional, might have been validated or passed-through from an upstream source. Semantics and behaviors for PDS vs Relay may evolve in the future; see atproto specs for more details.")
98
+
/** The current handle for the account, or 'handle.invalid' if validation fails. This field is optional, might have been validated or passed-through from an upstream source. Semantics and behaviors for PDS vs Relay may evolve in the future; see atproto specs for more details. */
99
99
handle?: handle;
100
100
}
101
101
102
-
@doc("Represents a change to an account's status on a host (eg, PDS or Relay). The semantics of this event are that the status is at the host which emitted the event, not necessarily that at the currently active PDS. Eg, a Relay takedown would emit a takedown with active=false, even if the PDS is still active.")
102
+
/** Represents a change to an account's status on a host (eg, PDS or Relay). The semantics of this event are that the status is at the host which emitted the event, not necessarily that at the currently active PDS. Eg, a Relay takedown would emit a takedown with active=false, even if the PDS is still active. */
103
103
model Account {
104
104
@required seq: integer;
105
105
@required did: did;
106
106
@required time: datetime;
107
107
108
-
@doc("Indicates that the account has a repository which can be fetched from the host that emitted this event.")
108
+
/** Indicates that the account has a repository which can be fetched from the host that emitted this event. */
109
109
@required
110
110
active: boolean;
111
111
112
-
@doc("If active=false, this optional field indicates a reason for why the account is not active.")
112
+
/** If active=false, this optional field indicates a reason for why the account is not active. */
113
113
status?: "takendown" | "suspended" | "deleted" | "deactivated" | "desynchronized" | "throttled" | string;
114
114
}
115
115
···
118
118
message?: string;
119
119
}
120
120
121
-
@doc("A repo operation, ie a mutation of a single record.")
121
+
/** A repo operation, ie a mutation of a single record. */
122
122
model RepoOp {
123
123
@required action: "create" | "update" | "delete" | string;
124
124
@required path: string;
125
125
126
-
@doc("For creates and updates, the new record CID. For deletions, null.")
126
+
/** For creates and updates, the new record CID. For deletions, null. */
127
127
@required
128
128
cid: cidLink | null;
129
129
130
-
@doc("For updates and deletes, the previous record CID (required for inductive firehose). For creations, field should not be defined.")
130
+
/** For updates and deletes, the previous record CID (required for inductive firehose). For creations, field should not be defined. */
131
131
prev?: cidLink;
132
132
}
133
133
}
+1
-1
packages/emitter/test/integration/atproto/input/com/atproto/temp/addReservedHandle.tsp
+1
-1
packages/emitter/test/integration/atproto/input/com/atproto/temp/addReservedHandle.tsp
+11
-11
packages/emitter/test/integration/atproto/input/com/atproto/temp/checkHandleAvailability.tsp
+11
-11
packages/emitter/test/integration/atproto/input/com/atproto/temp/checkHandleAvailability.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace com.atproto.temp.checkHandleAvailability {
4
-
@doc("An invalid email was provided.")
4
+
/** An invalid email was provided. */
5
5
model InvalidEmail {}
6
6
7
-
@doc("Indicates the provided handle is available.")
7
+
/** Indicates the provided handle is available. */
8
8
model ResultAvailable {}
9
9
10
-
@doc("Indicates the provided handle is unavailable and gives suggestions of available handles.")
10
+
/** Indicates the provided handle is unavailable and gives suggestions of available handles. */
11
11
model ResultUnavailable {
12
-
@doc("List of suggested handles based on the provided inputs.")
12
+
/** List of suggested handles based on the provided inputs. */
13
13
@required
14
14
suggestions: Suggestion[];
15
15
}
···
17
17
model Suggestion {
18
18
@required handle: handle;
19
19
20
-
@doc("Method used to build this suggestion. Should be considered opaque to clients. Can be used for metrics.")
20
+
/** Method used to build this suggestion. Should be considered opaque to clients. Can be used for metrics. */
21
21
@required
22
22
method: string;
23
23
}
24
24
25
-
@doc("Checks whether the provided handle is available. If the handle is not available, available suggestions will be returned. Optional inputs will be used to generate suggestions.")
25
+
/** Checks whether the provided handle is available. If the handle is not available, available suggestions will be returned. Optional inputs will be used to generate suggestions. */
26
26
@query
27
27
@errors(InvalidEmail)
28
28
op main(
29
-
@doc("Tentative handle. Will be checked for availability or used to build handle suggestions.")
30
-
handle: handle,
29
+
/** Tentative handle. Will be checked for availability or used to build handle suggestions. */
30
+
@required handle: handle,
31
31
32
-
@doc("User-provided email. Might be used to build handle suggestions.")
32
+
/** User-provided email. Might be used to build handle suggestions. */
33
33
email?: string,
34
34
35
-
@doc("User-provided birth date. Might be used to build handle suggestions.")
35
+
/** User-provided birth date. Might be used to build handle suggestions. */
36
36
birthDate?: datetime
37
37
): {
38
-
@doc("Echo of the input handle.")
38
+
/** Echo of the input handle. */
39
39
@required
40
40
handle: handle;
41
41
+1
-1
packages/emitter/test/integration/atproto/input/com/atproto/temp/checkSignupQueue.tsp
+1
-1
packages/emitter/test/integration/atproto/input/com/atproto/temp/checkSignupQueue.tsp
+5
-5
packages/emitter/test/integration/atproto/input/com/atproto/temp/dereferenceScope.tsp
+5
-5
packages/emitter/test/integration/atproto/input/com/atproto/temp/dereferenceScope.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace com.atproto.temp.dereferenceScope {
4
-
@doc("An invalid scope reference was provided.")
4
+
/** An invalid scope reference was provided. */
5
5
model InvalidScopeReference {}
6
6
7
-
@doc("Allows finding the oauth permission scope from a reference")
7
+
/** Allows finding the oauth permission scope from a reference */
8
8
@query
9
9
@errors(InvalidScopeReference)
10
10
op main(
11
-
@doc("The scope reference (starts with 'ref:')")
12
-
scope: string
11
+
/** The scope reference (starts with 'ref:') */
12
+
@required scope: string
13
13
): {
14
-
@doc("The full oauth permission scope")
14
+
/** The full oauth permission scope */
15
15
@required
16
16
scope: string;
17
17
};
+8
-1
packages/emitter/test/integration/atproto/input/com/atproto/temp/fetchLabels.tsp
+8
-1
packages/emitter/test/integration/atproto/input/com/atproto/temp/fetchLabels.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace com.atproto.temp.fetchLabels {
4
-
@doc("DEPRECATED: use queryLabels or subscribeLabels instead -- Fetch all labels from a labeler created after a certain date.")
4
+
/** DEPRECATED: use queryLabels or subscribeLabels instead -- Fetch all labels from a labeler created after a certain date. */
5
5
@query
6
6
op main(
7
7
since?: integer,
···
13
13
@required labels: com.atproto.label.defs.Label[];
14
14
};
15
15
}
16
+
17
+
// --- Externals ---
18
+
19
+
@external
20
+
namespace com.atproto.label.defs {
21
+
model Label { }
22
+
}
+1
-1
packages/emitter/test/integration/atproto/input/com/atproto/temp/requestPhoneVerification.tsp
+1
-1
packages/emitter/test/integration/atproto/input/com/atproto/temp/requestPhoneVerification.tsp
+1
-1
packages/emitter/test/integration/atproto/input/com/atproto/temp/revokeAccountCredentials.tsp
+1
-1
packages/emitter/test/integration/atproto/input/com/atproto/temp/revokeAccountCredentials.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace com.atproto.temp.revokeAccountCredentials {
4
-
@doc("Revoke sessions, password, and app passwords associated with account. May be resolved by a password reset.")
4
+
/** Revoke sessions, password, and app passwords associated with account. May be resolved by a password reset. */
5
5
@procedure
6
6
op main(
7
7
input: {
+13
-6
packages/emitter/test/integration/atproto/input/tools/ozone/communication/createTemplate.tsp
+13
-6
packages/emitter/test/integration/atproto/input/tools/ozone/communication/createTemplate.tsp
···
3
3
namespace tools.ozone.communication.createTemplate {
4
4
model DuplicateTemplateName {}
5
5
6
-
@doc("Administrative action to create a new, re-usable communication (email for now) template.")
6
+
/** Administrative action to create a new, re-usable communication (email for now) template. */
7
7
@procedure
8
8
@errors(DuplicateTemplateName)
9
9
op main(input: {
10
-
@doc("Subject of the message, used in emails.")
10
+
/** Subject of the message, used in emails. */
11
11
@required
12
12
subject: string;
13
13
14
-
@doc("Content of the template, markdown supported, can contain variable placeholders.")
14
+
/** Content of the template, markdown supported, can contain variable placeholders. */
15
15
@required
16
16
contentMarkdown: string;
17
17
18
-
@doc("Name of the template.")
18
+
/** Name of the template. */
19
19
@required
20
20
name: string;
21
21
22
-
@doc("Message language.")
22
+
/** Message language. */
23
23
lang?: language;
24
24
25
-
@doc("DID of the user who is creating the template.")
25
+
/** DID of the user who is creating the template. */
26
26
createdBy?: did;
27
27
}): tools.ozone.communication.defs.TemplateView;
28
28
}
29
+
30
+
// --- Externals ---
31
+
32
+
@external
33
+
namespace tools.ozone.communication.defs {
34
+
model TemplateView { }
35
+
}
+5
-5
packages/emitter/test/integration/atproto/input/tools/ozone/communication/defs.tsp
+5
-5
packages/emitter/test/integration/atproto/input/tools/ozone/communication/defs.tsp
···
4
4
model TemplateView {
5
5
@required id: string;
6
6
7
-
@doc("Name of the template.")
7
+
/** Name of the template. */
8
8
@required
9
9
name: string;
10
10
11
-
@doc("Content of the template, can contain markdown and variable placeholders.")
11
+
/** Content of the template, can contain markdown and variable placeholders. */
12
12
subject?: string;
13
13
14
-
@doc("Subject of the message, used in emails.")
14
+
/** Subject of the message, used in emails. */
15
15
@required
16
16
contentMarkdown: string;
17
17
18
18
@required disabled: boolean;
19
19
20
-
@doc("Message language.")
20
+
/** Message language. */
21
21
lang?: language;
22
22
23
-
@doc("DID of the user who last updated the template.")
23
+
/** DID of the user who last updated the template. */
24
24
@required
25
25
lastUpdatedBy: did;
26
26
+1
-1
packages/emitter/test/integration/atproto/input/tools/ozone/communication/deleteTemplate.tsp
+1
-1
packages/emitter/test/integration/atproto/input/tools/ozone/communication/deleteTemplate.tsp
+8
-1
packages/emitter/test/integration/atproto/input/tools/ozone/communication/listTemplates.tsp
+8
-1
packages/emitter/test/integration/atproto/input/tools/ozone/communication/listTemplates.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace tools.ozone.communication.listTemplates {
4
-
@doc("Get list of all communication templates.")
4
+
/** Get list of all communication templates. */
5
5
@query
6
6
op main(): {
7
7
@required communicationTemplates: tools.ozone.communication.defs.TemplateView[];
8
8
};
9
9
}
10
+
11
+
// --- Externals ---
12
+
13
+
@external
14
+
namespace tools.ozone.communication.defs {
15
+
model TemplateView { }
16
+
}
+14
-7
packages/emitter/test/integration/atproto/input/tools/ozone/communication/updateTemplate.tsp
+14
-7
packages/emitter/test/integration/atproto/input/tools/ozone/communication/updateTemplate.tsp
···
3
3
namespace tools.ozone.communication.updateTemplate {
4
4
model DuplicateTemplateName {}
5
5
6
-
@doc("Administrative action to update an existing communication template. Allows passing partial fields to patch specific fields only.")
6
+
/** Administrative action to update an existing communication template. Allows passing partial fields to patch specific fields only. */
7
7
@procedure
8
8
@errors(DuplicateTemplateName)
9
9
op main(input: {
10
-
@doc("ID of the template to be updated.")
10
+
/** ID of the template to be updated. */
11
11
@required
12
12
id: string;
13
13
14
-
@doc("Name of the template.")
14
+
/** Name of the template. */
15
15
name?: string;
16
16
17
-
@doc("Message language.")
17
+
/** Message language. */
18
18
lang?: language;
19
19
20
-
@doc("Content of the template, markdown supported, can contain variable placeholders.")
20
+
/** Content of the template, markdown supported, can contain variable placeholders. */
21
21
contentMarkdown?: string;
22
22
23
-
@doc("Subject of the message, used in emails.")
23
+
/** Subject of the message, used in emails. */
24
24
subject?: string;
25
25
26
-
@doc("DID of the user who is updating the template.")
26
+
/** DID of the user who is updating the template. */
27
27
updatedBy?: did;
28
28
29
29
disabled?: boolean;
30
30
}): tools.ozone.communication.defs.TemplateView;
31
31
}
32
+
33
+
// --- Externals ---
34
+
35
+
@external
36
+
namespace tools.ozone.communication.defs {
37
+
model TemplateView { }
38
+
}
+1
-1
packages/emitter/test/integration/atproto/input/tools/ozone/hosting/getAccountHistory.tsp
+1
-1
packages/emitter/test/integration/atproto/input/tools/ozone/hosting/getAccountHistory.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace tools.ozone.hosting.getAccountHistory {
4
-
@doc("Get account history, e.g. log of updated email addresses or other identity information.")
4
+
/** Get account history, e.g. log of updated email addresses or other identity information. */
5
5
@query
6
6
op main(
7
7
@required did: did,
+130
-96
packages/emitter/test/integration/atproto/input/tools/ozone/moderation/defs.tsp
+130
-96
packages/emitter/test/integration/atproto/input/tools/ozone/moderation/defs.tsp
···
94
94
subjectBlobCids?: cid[];
95
95
subjectRepoHandle?: string;
96
96
97
-
@doc("Timestamp referencing the first moderation status impacting event was emitted on the subject")
97
+
/** Timestamp referencing the first moderation status impacting event was emitted on the subject */
98
98
@required
99
99
createdAt: datetime;
100
100
101
-
@doc("Timestamp referencing when the last update was made to the moderation status of the subject")
101
+
/** Timestamp referencing when the last update was made to the moderation status of the subject */
102
102
@required
103
103
updatedAt: datetime;
104
104
105
105
@required reviewState: SubjectReviewState;
106
106
107
-
@doc("Sticky comment on the subject.")
107
+
/** Sticky comment on the subject. */
108
108
comment?: string;
109
109
110
-
@doc("Numeric value representing the level of priority. Higher score means higher priority.")
110
+
/** Numeric value representing the level of priority. Higher score means higher priority. */
111
111
@minValue(0)
112
112
@maxValue(100)
113
113
priorityScore?: int32;
···
118
118
lastReviewedAt?: datetime;
119
119
lastReportedAt?: datetime;
120
120
121
-
@doc("Timestamp referencing when the author of the subject appealed a moderation action")
121
+
/** Timestamp referencing when the author of the subject appealed a moderation action */
122
122
lastAppealedAt?: datetime;
123
123
124
124
takendown?: boolean;
125
125
126
-
@doc("True indicates that the a previously taken moderator action was appealed against, by the author of the content. False indicates last appeal was resolved by moderators.")
126
+
/** True indicates that the a previously taken moderator action was appealed against, by the author of the content. False indicates last appeal was resolved by moderators. */
127
127
appealed?: boolean;
128
128
129
129
suspendUntil?: datetime;
130
130
tags?: string[];
131
131
132
-
@doc("Statistics related to the account subject")
132
+
/** Statistics related to the account subject */
133
133
accountStats?: AccountStats;
134
134
135
-
@doc("Statistics related to the record subjects authored by the subject's account")
135
+
/** Statistics related to the record subjects authored by the subject's account */
136
136
recordsStats?: RecordsStats;
137
137
138
-
@doc("Current age assurance state of the subject.")
138
+
/** Current age assurance state of the subject. */
139
139
ageAssuranceState?: "pending" | "assured" | "unknown" | "reset" | "blocked" | string;
140
140
141
-
@doc("Whether or not the last successful update to age assurance was made by the user or admin.")
141
+
/** Whether or not the last successful update to age assurance was made by the user or admin. */
142
142
ageAssuranceUpdatedBy?: "admin" | "user" | string;
143
143
}
144
144
145
-
@doc("Detailed view of a subject. For record subjects, the author's repo and profile will be returned.")
145
+
/** Detailed view of a subject. For record subjects, the author's repo and profile will be returned. */
146
146
model SubjectView {
147
147
@required type: com.atproto.moderation.defs.SubjectType;
148
148
@required subject: string;
···
152
152
record?: RecordViewDetail;
153
153
}
154
154
155
-
@doc("Statistics about a particular account subject")
155
+
/** Statistics about a particular account subject */
156
156
model AccountStats {
157
-
@doc("Total number of reports on the account")
157
+
/** Total number of reports on the account */
158
158
reportCount?: int32;
159
159
160
-
@doc("Total number of appeals against a moderation action on the account")
160
+
/** Total number of appeals against a moderation action on the account */
161
161
appealCount?: int32;
162
162
163
-
@doc("Number of times the account was suspended")
163
+
/** Number of times the account was suspended */
164
164
suspendCount?: int32;
165
165
166
-
@doc("Number of times the account was escalated")
166
+
/** Number of times the account was escalated */
167
167
escalateCount?: int32;
168
168
169
-
@doc("Number of times the account was taken down")
169
+
/** Number of times the account was taken down */
170
170
takedownCount?: int32;
171
171
}
172
172
173
-
@doc("Statistics about a set of record subject items")
173
+
/** Statistics about a set of record subject items */
174
174
model RecordsStats {
175
-
@doc("Cumulative sum of the number of reports on the items in the set")
175
+
/** Cumulative sum of the number of reports on the items in the set */
176
176
totalReports?: int32;
177
177
178
-
@doc("Number of items that were reported at least once")
178
+
/** Number of items that were reported at least once */
179
179
reportedCount?: int32;
180
180
181
-
@doc("Number of items that were escalated at least once")
181
+
/** Number of items that were escalated at least once */
182
182
escalatedCount?: int32;
183
183
184
-
@doc("Number of items that were appealed at least once")
184
+
/** Number of items that were appealed at least once */
185
185
appealedCount?: int32;
186
186
187
-
@doc("Total number of item in the set")
187
+
/** Total number of item in the set */
188
188
subjectCount?: int32;
189
189
190
190
@doc("Number of item currently in \"reviewOpen\" or \"reviewEscalated\" state")
···
193
193
@doc("Number of item currently in \"reviewNone\" or \"reviewClosed\" state")
194
194
processedCount?: int32;
195
195
196
-
@doc("Number of item currently taken down")
196
+
/** Number of item currently taken down */
197
197
takendownCount?: int32;
198
198
}
199
199
200
200
union SubjectReviewState {
201
-
"#reviewOpen",
202
-
"#reviewEscalated",
203
-
"#reviewClosed",
204
-
"#reviewNone",
201
+
ReviewOpen,
202
+
ReviewEscalated,
203
+
ReviewClosed,
204
+
ReviewNone,
205
205
string,
206
206
}
207
207
208
-
@doc("Moderator review status of a subject: Open. Indicates that the subject needs to be reviewed by a moderator")
208
+
/** Moderator review status of a subject: Open. Indicates that the subject needs to be reviewed by a moderator */
209
209
@token
210
210
model ReviewOpen {}
211
211
212
-
@doc("Moderator review status of a subject: Escalated. Indicates that the subject was escalated for review by a moderator")
212
+
/** Moderator review status of a subject: Escalated. Indicates that the subject was escalated for review by a moderator */
213
213
@token
214
214
model ReviewEscalated {}
215
215
216
-
@doc("Moderator review status of a subject: Closed. Indicates that the subject was already reviewed and resolved by a moderator")
216
+
/** Moderator review status of a subject: Closed. Indicates that the subject was already reviewed and resolved by a moderator */
217
217
@token
218
218
model ReviewClosed {}
219
219
220
-
@doc("Moderator review status of a subject: Unnecessary. Indicates that the subject does not need a review at the moment but there is probably some moderation related metadata available for it")
220
+
/** Moderator review status of a subject: Unnecessary. Indicates that the subject does not need a review at the moment but there is probably some moderation related metadata available for it */
221
221
@token
222
222
model ReviewNone {}
223
223
224
-
@doc("Take down a subject permanently or temporarily")
224
+
/** Take down a subject permanently or temporarily */
225
225
model ModEventTakedown {
226
226
comment?: string;
227
227
228
-
@doc("Indicates how long the takedown should be in effect before automatically expiring.")
228
+
/** Indicates how long the takedown should be in effect before automatically expiring. */
229
229
durationInHours?: int32;
230
230
231
-
@doc("If true, all other reports on content authored by this account will be resolved (acknowledged).")
231
+
/** If true, all other reports on content authored by this account will be resolved (acknowledged). */
232
232
acknowledgeAccountSubjects?: boolean;
233
233
234
-
@doc("Names/Keywords of the policies that drove the decision.")
234
+
/** Names/Keywords of the policies that drove the decision. */
235
235
@maxItems(5)
236
236
policies?: string[];
237
237
}
238
238
239
-
@doc("Revert take down action on a subject")
239
+
/** Revert take down action on a subject */
240
240
model ModEventReverseTakedown {
241
-
@doc("Describe reasoning behind the reversal.")
241
+
/** Describe reasoning behind the reversal. */
242
242
comment?: string;
243
243
}
244
244
245
-
@doc("Resolve appeal on a subject")
245
+
/** Resolve appeal on a subject */
246
246
model ModEventResolveAppeal {
247
-
@doc("Describe resolution.")
247
+
/** Describe resolution. */
248
248
comment?: string;
249
249
}
250
250
251
-
@doc("Add a comment to a subject. An empty comment will clear any previously set sticky comment.")
251
+
/** Add a comment to a subject. An empty comment will clear any previously set sticky comment. */
252
252
model ModEventComment {
253
253
comment?: string;
254
254
255
-
@doc("Make the comment persistent on the subject")
255
+
/** Make the comment persistent on the subject */
256
256
sticky?: boolean;
257
257
}
258
258
259
-
@doc("Report a subject")
259
+
/** Report a subject */
260
260
model ModEventReport {
261
261
comment?: string;
262
262
263
-
@doc("Set to true if the reporter was muted from reporting at the time of the event. These reports won't impact the reviewState of the subject.")
263
+
/** Set to true if the reporter was muted from reporting at the time of the event. These reports won't impact the reviewState of the subject. */
264
264
isReporterMuted?: boolean;
265
265
266
266
@required reportType: com.atproto.moderation.defs.ReasonType;
267
267
}
268
268
269
-
@doc("Apply/Negate labels on a subject")
269
+
/** Apply/Negate labels on a subject */
270
270
model ModEventLabel {
271
271
comment?: string;
272
272
@required createLabelVals: string[];
273
273
@required negateLabelVals: string[];
274
274
275
-
@doc("Indicates how long the label will remain on the subject. Only applies on labels that are being added.")
275
+
/** Indicates how long the label will remain on the subject. Only applies on labels that are being added. */
276
276
durationInHours?: int32;
277
277
}
278
278
279
-
@doc("Set priority score of the subject. Higher score means higher priority.")
279
+
/** Set priority score of the subject. Higher score means higher priority. */
280
280
model ModEventPriorityScore {
281
281
comment?: string;
282
282
···
286
286
score: int32;
287
287
}
288
288
289
-
@doc("Age assurance info coming directly from users. Only works on DID subjects.")
289
+
/** Age assurance info coming directly from users. Only works on DID subjects. */
290
290
model AgeAssuranceEvent {
291
-
@doc("The date and time of this write operation.")
291
+
/** The date and time of this write operation. */
292
292
@required
293
293
createdAt: datetime;
294
294
295
-
@doc("The status of the age assurance process.")
295
+
/** The status of the age assurance process. */
296
296
@required
297
297
status: "unknown" | "pending" | "assured" | string;
298
298
299
-
@doc("The unique identifier for this instance of the age assurance flow, in UUID format.")
299
+
/** The unique identifier for this instance of the age assurance flow, in UUID format. */
300
300
@required
301
301
attemptId: string;
302
302
303
-
@doc("The IP address used when initiating the AA flow.")
303
+
/** The IP address used when initiating the AA flow. */
304
304
initIp?: string;
305
305
306
-
@doc("The user agent used when initiating the AA flow.")
306
+
/** The user agent used when initiating the AA flow. */
307
307
initUa?: string;
308
308
309
-
@doc("The IP address used when completing the AA flow.")
309
+
/** The IP address used when completing the AA flow. */
310
310
completeIp?: string;
311
311
312
-
@doc("The user agent used when completing the AA flow.")
312
+
/** The user agent used when completing the AA flow. */
313
313
completeUa?: string;
314
314
}
315
315
316
-
@doc("Age assurance status override by moderators. Only works on DID subjects.")
316
+
/** Age assurance status override by moderators. Only works on DID subjects. */
317
317
model AgeAssuranceOverrideEvent {
318
-
@doc("Comment describing the reason for the override.")
318
+
/** Comment describing the reason for the override. */
319
319
@required
320
320
comment: string;
321
321
322
-
@doc("The status to be set for the user decided by a moderator, overriding whatever value the user had previously. Use reset to default to original state.")
322
+
/** The status to be set for the user decided by a moderator, overriding whatever value the user had previously. Use reset to default to original state. */
323
323
@required
324
324
status: "assured" | "reset" | "blocked" | string;
325
325
}
326
326
327
-
@doc("Account credentials revocation by moderators. Only works on DID subjects.")
327
+
/** Account credentials revocation by moderators. Only works on DID subjects. */
328
328
model RevokeAccountCredentialsEvent {
329
-
@doc("Comment describing the reason for the revocation.")
329
+
/** Comment describing the reason for the revocation. */
330
330
@required
331
331
comment: string;
332
332
}
···
334
334
model ModEventAcknowledge {
335
335
comment?: string;
336
336
337
-
@doc("If true, all other reports on content authored by this account will be resolved (acknowledged).")
337
+
/** If true, all other reports on content authored by this account will be resolved (acknowledged). */
338
338
acknowledgeAccountSubjects?: boolean;
339
339
}
340
340
···
342
342
comment?: string;
343
343
}
344
344
345
-
@doc("Mute incoming reports on a subject")
345
+
/** Mute incoming reports on a subject */
346
346
model ModEventMute {
347
347
comment?: string;
348
348
349
-
@doc("Indicates how long the subject should remain muted.")
349
+
/** Indicates how long the subject should remain muted. */
350
350
@required
351
351
durationInHours: int32;
352
352
}
353
353
354
-
@doc("Unmute action on a subject")
354
+
/** Unmute action on a subject */
355
355
model ModEventUnmute {
356
-
@doc("Describe reasoning behind the reversal.")
356
+
/** Describe reasoning behind the reversal. */
357
357
comment?: string;
358
358
}
359
359
360
-
@doc("Mute incoming reports from an account")
360
+
/** Mute incoming reports from an account */
361
361
model ModEventMuteReporter {
362
362
comment?: string;
363
363
364
-
@doc("Indicates how long the account should remain muted. Falsy value here means a permanent mute.")
364
+
/** Indicates how long the account should remain muted. Falsy value here means a permanent mute. */
365
365
durationInHours?: int32;
366
366
}
367
367
368
-
@doc("Unmute incoming reports from an account")
368
+
/** Unmute incoming reports from an account */
369
369
model ModEventUnmuteReporter {
370
-
@doc("Describe reasoning behind the reversal.")
370
+
/** Describe reasoning behind the reversal. */
371
371
comment?: string;
372
372
}
373
373
374
-
@doc("Keep a log of outgoing email to a user")
374
+
/** Keep a log of outgoing email to a user */
375
375
model ModEventEmail {
376
-
@doc("The subject line of the email sent to the user.")
376
+
/** The subject line of the email sent to the user. */
377
377
@required
378
378
subjectLine: string;
379
379
380
-
@doc("The content of the email sent to the user.")
380
+
/** The content of the email sent to the user. */
381
381
content?: string;
382
382
383
-
@doc("Additional comment about the outgoing comm.")
383
+
/** Additional comment about the outgoing comm. */
384
384
comment?: string;
385
385
}
386
386
387
-
@doc("Divert a record's blobs to a 3rd party service for further scanning/tagging")
387
+
/** Divert a record's blobs to a 3rd party service for further scanning/tagging */
388
388
model ModEventDivert {
389
389
comment?: string;
390
390
}
391
391
392
-
@doc("Add/Remove a tag on a subject")
392
+
/** Add/Remove a tag on a subject */
393
393
model ModEventTag {
394
-
@doc("Tags to be added to the subject. If already exists, won't be duplicated.")
394
+
/** Tags to be added to the subject. If already exists, won't be duplicated. */
395
395
@required
396
396
add: string[];
397
397
398
-
@doc("Tags to be removed to the subject. Ignores a tag If it doesn't exist, won't be duplicated.")
398
+
/** Tags to be removed to the subject. Ignores a tag If it doesn't exist, won't be duplicated. */
399
399
@required
400
400
remove: string[];
401
401
402
-
@doc("Additional comment about added/removed tags.")
402
+
/** Additional comment about added/removed tags. */
403
403
comment?: string;
404
404
}
405
405
406
-
@doc("Logs account status related events on a repo subject. Normally captured by automod from the firehose and emitted to ozone for historical tracking.")
406
+
/** Logs account status related events on a repo subject. Normally captured by automod from the firehose and emitted to ozone for historical tracking. */
407
407
model AccountEvent {
408
408
comment?: string;
409
409
@required timestamp: datetime;
410
410
411
-
@doc("Indicates that the account has a repository which can be fetched from the host that emitted this event.")
411
+
/** Indicates that the account has a repository which can be fetched from the host that emitted this event. */
412
412
@required
413
413
active: boolean;
414
414
415
415
status?: "unknown" | "deactivated" | "deleted" | "takendown" | "suspended" | "tombstoned" | string;
416
416
}
417
417
418
-
@doc("Logs identity related events on a repo subject. Normally captured by automod from the firehose and emitted to ozone for historical tracking.")
418
+
/** Logs identity related events on a repo subject. Normally captured by automod from the firehose and emitted to ozone for historical tracking. */
419
419
model IdentityEvent {
420
420
comment?: string;
421
421
handle?: handle;
···
424
424
@required timestamp: datetime;
425
425
}
426
426
427
-
@doc("Logs lifecycle event on a record subject. Normally captured by automod from the firehose and emitted to ozone for historical tracking.")
427
+
/** Logs lifecycle event on a record subject. Normally captured by automod from the firehose and emitted to ozone for historical tracking. */
428
428
model RecordEvent {
429
429
comment?: string;
430
430
@required timestamp: datetime;
···
546
546
model ReporterStats {
547
547
@required did: did;
548
548
549
-
@doc("The total number of reports made by the user on accounts.")
549
+
/** The total number of reports made by the user on accounts. */
550
550
@required
551
551
accountReportCount: int32;
552
552
553
-
@doc("The total number of reports made by the user on records.")
553
+
/** The total number of reports made by the user on records. */
554
554
@required
555
555
recordReportCount: int32;
556
556
557
-
@doc("The total number of accounts reported by the user.")
557
+
/** The total number of accounts reported by the user. */
558
558
@required
559
559
reportedAccountCount: int32;
560
560
561
-
@doc("The total number of records reported by the user.")
561
+
/** The total number of records reported by the user. */
562
562
@required
563
563
reportedRecordCount: int32;
564
564
565
-
@doc("The total number of accounts taken down as a result of the user's reports.")
565
+
/** The total number of accounts taken down as a result of the user's reports. */
566
566
@required
567
567
takendownAccountCount: int32;
568
568
569
-
@doc("The total number of records taken down as a result of the user's reports.")
569
+
/** The total number of records taken down as a result of the user's reports. */
570
570
@required
571
571
takendownRecordCount: int32;
572
572
573
-
@doc("The total number of accounts labeled as a result of the user's reports.")
573
+
/** The total number of accounts labeled as a result of the user's reports. */
574
574
@required
575
575
labeledAccountCount: int32;
576
576
577
-
@doc("The total number of records labeled as a result of the user's reports.")
577
+
/** The total number of records labeled as a result of the user's reports. */
578
578
@required
579
579
labeledRecordCount: int32;
580
580
}
581
581
582
-
@doc("Moderation tool information for tracing the source of the action")
582
+
/** Moderation tool information for tracing the source of the action */
583
583
model ModTool {
584
-
@doc("Name/identifier of the source (e.g., 'automod', 'ozone/workspace')")
584
+
/** Name/identifier of the source (e.g., 'automod', 'ozone/workspace') */
585
585
@required
586
586
name: string;
587
587
588
-
@doc("Additional arbitrary metadata about the source")
588
+
/** Additional arbitrary metadata about the source */
589
589
meta?: unknown;
590
590
}
591
591
592
-
@doc("Moderation event timeline event for a PLC create operation")
592
+
/** Moderation event timeline event for a PLC create operation */
593
593
@token
594
594
model TimelineEventPlcCreate {}
595
595
596
-
@doc("Moderation event timeline event for generic PLC operation")
596
+
/** Moderation event timeline event for generic PLC operation */
597
597
@token
598
598
model TimelineEventPlcOperation {}
599
599
600
-
@doc("Moderation event timeline event for a PLC tombstone operation")
600
+
/** Moderation event timeline event for a PLC tombstone operation */
601
601
@token
602
602
model TimelineEventPlcTombstone {}
603
603
}
604
+
605
+
// --- Externals ---
606
+
607
+
@external
608
+
namespace com.atproto.admin.defs {
609
+
model RepoRef { }
610
+
model ThreatSignature { }
611
+
}
612
+
613
+
@external
614
+
namespace com.atproto.repo.strongRef {
615
+
model Main { }
616
+
}
617
+
618
+
@external
619
+
namespace chat.bsky.convo.defs {
620
+
model MessageRef { }
621
+
}
622
+
623
+
@external
624
+
namespace com.atproto.moderation.defs {
625
+
model SubjectType { }
626
+
model ReasonType { }
627
+
}
628
+
629
+
@external
630
+
namespace com.atproto.server.defs {
631
+
model InviteCode { }
632
+
}
633
+
634
+
@external
635
+
namespace com.atproto.label.defs {
636
+
model Label { }
637
+
}
+43
-3
packages/emitter/test/integration/atproto/input/tools/ozone/moderation/emitEvent.tsp
+43
-3
packages/emitter/test/integration/atproto/input/tools/ozone/moderation/emitEvent.tsp
···
3
3
namespace tools.ozone.moderation.emitEvent {
4
4
model SubjectHasAction {}
5
5
6
-
@doc("An event with the same external ID already exists for the subject.")
6
+
/** An event with the same external ID already exists for the subject. */
7
7
model DuplicateExternalId {}
8
8
9
-
@doc("Take a moderation action on an actor.")
9
+
/** Take a moderation action on an actor. */
10
10
@procedure
11
11
@errors(SubjectHasAction, DuplicateExternalId)
12
12
op main(input: {
···
50
50
51
51
modTool?: tools.ozone.moderation.defs.ModTool;
52
52
53
-
@doc("An optional external ID for the event, used to deduplicate events from external systems. Fails when an event of same type with the same external ID exists for the same subject.")
53
+
/** An optional external ID for the event, used to deduplicate events from external systems. Fails when an event of same type with the same external ID exists for the same subject. */
54
54
externalId?: string;
55
55
}): tools.ozone.moderation.defs.ModEventView;
56
56
}
57
+
58
+
// --- Externals ---
59
+
60
+
@external
61
+
namespace tools.ozone.moderation.defs {
62
+
model ModEventTakedown { }
63
+
model ModEventAcknowledge { }
64
+
model ModEventEscalate { }
65
+
model ModEventComment { }
66
+
model ModEventLabel { }
67
+
model ModEventReport { }
68
+
model ModEventMute { }
69
+
model ModEventUnmute { }
70
+
model ModEventMuteReporter { }
71
+
model ModEventUnmuteReporter { }
72
+
model ModEventReverseTakedown { }
73
+
model ModEventResolveAppeal { }
74
+
model ModEventEmail { }
75
+
model ModEventDivert { }
76
+
model ModEventTag { }
77
+
model AccountEvent { }
78
+
model IdentityEvent { }
79
+
model RecordEvent { }
80
+
model ModEventPriorityScore { }
81
+
model AgeAssuranceEvent { }
82
+
model AgeAssuranceOverrideEvent { }
83
+
model RevokeAccountCredentialsEvent { }
84
+
model ModTool { }
85
+
model ModEventView { }
86
+
}
87
+
88
+
@external
89
+
namespace com.atproto.admin.defs {
90
+
model RepoRef { }
91
+
}
92
+
93
+
@external
94
+
namespace com.atproto.repo.strongRef {
95
+
model Main { }
96
+
}
+40
-1
packages/emitter/test/integration/atproto/input/tools/ozone/moderation/getAccountTimeline.tsp
+40
-1
packages/emitter/test/integration/atproto/input/tools/ozone/moderation/getAccountTimeline.tsp
···
3
3
namespace tools.ozone.moderation.getAccountTimeline {
4
4
model RepoNotFound {}
5
5
6
-
@doc("Get timeline of all available events of an account. This includes moderation events, account history and did history.")
6
+
/** Get timeline of all available events of an account. This includes moderation events, account history and did history. */
7
7
@query
8
8
@errors(RepoNotFound)
9
9
op main(@required did: did): {
···
55
55
@required count: integer;
56
56
}
57
57
}
58
+
59
+
// --- Externals ---
60
+
61
+
@external
62
+
namespace tools.ozone.moderation.defs {
63
+
model ModEventTakedown { }
64
+
model ModEventReverseTakedown { }
65
+
model ModEventComment { }
66
+
model ModEventReport { }
67
+
model ModEventLabel { }
68
+
model ModEventAcknowledge { }
69
+
model ModEventEscalate { }
70
+
model ModEventMute { }
71
+
model ModEventUnmute { }
72
+
model ModEventMuteReporter { }
73
+
model ModEventUnmuteReporter { }
74
+
model ModEventEmail { }
75
+
model ModEventResolveAppeal { }
76
+
model ModEventDivert { }
77
+
model ModEventTag { }
78
+
model AccountEvent { }
79
+
model IdentityEvent { }
80
+
model RecordEvent { }
81
+
model ModEventPriorityScore { }
82
+
model RevokeAccountCredentialsEvent { }
83
+
model AgeAssuranceEvent { }
84
+
model AgeAssuranceOverrideEvent { }
85
+
@token model TimelineEventPlcCreate { }
86
+
@token model TimelineEventPlcOperation { }
87
+
@token model TimelineEventPlcTombstone { }
88
+
}
89
+
90
+
@external
91
+
namespace tools.ozone.hosting.getAccountHistory {
92
+
model AccountCreated { }
93
+
model EmailConfirmed { }
94
+
model PasswordUpdated { }
95
+
model HandleUpdated { }
96
+
}
+8
-1
packages/emitter/test/integration/atproto/input/tools/ozone/moderation/getEvent.tsp
+8
-1
packages/emitter/test/integration/atproto/input/tools/ozone/moderation/getEvent.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace tools.ozone.moderation.getEvent {
4
-
@doc("Get details about a moderation event.")
4
+
/** Get details about a moderation event. */
5
5
@query
6
6
op main(@required id: integer): tools.ozone.moderation.defs.ModEventViewDetail;
7
7
}
8
+
9
+
// --- Externals ---
10
+
11
+
@external
12
+
namespace tools.ozone.moderation.defs {
13
+
model ModEventViewDetail { }
14
+
}
+8
-1
packages/emitter/test/integration/atproto/input/tools/ozone/moderation/getRecord.tsp
+8
-1
packages/emitter/test/integration/atproto/input/tools/ozone/moderation/getRecord.tsp
···
3
3
namespace tools.ozone.moderation.getRecord {
4
4
model RecordNotFound {}
5
5
6
-
@doc("Get details about a record.")
6
+
/** Get details about a record. */
7
7
@query
8
8
@errors(RecordNotFound)
9
9
op main(@required uri: atUri, cid?: cid): tools.ozone.moderation.defs.RecordViewDetail;
10
10
}
11
+
12
+
// --- Externals ---
13
+
14
+
@external
15
+
namespace tools.ozone.moderation.defs {
16
+
model RecordViewDetail { }
17
+
}
+9
-1
packages/emitter/test/integration/atproto/input/tools/ozone/moderation/getRecords.tsp
+9
-1
packages/emitter/test/integration/atproto/input/tools/ozone/moderation/getRecords.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace tools.ozone.moderation.getRecords {
4
-
@doc("Get details about some records.")
4
+
/** Get details about some records. */
5
5
@query
6
6
op main(
7
7
@maxItems(100)
···
16
16
)[];
17
17
};
18
18
}
19
+
20
+
// --- Externals ---
21
+
22
+
@external
23
+
namespace tools.ozone.moderation.defs {
24
+
model RecordViewDetail { }
25
+
model RecordViewNotFound { }
26
+
}
+8
-1
packages/emitter/test/integration/atproto/input/tools/ozone/moderation/getRepo.tsp
+8
-1
packages/emitter/test/integration/atproto/input/tools/ozone/moderation/getRepo.tsp
···
3
3
namespace tools.ozone.moderation.getRepo {
4
4
model RepoNotFound {}
5
5
6
-
@doc("Get details about a repository.")
6
+
/** Get details about a repository. */
7
7
@query
8
8
@errors(RepoNotFound)
9
9
op main(@required did: did): tools.ozone.moderation.defs.RepoViewDetail;
10
10
}
11
+
12
+
// --- Externals ---
13
+
14
+
@external
15
+
namespace tools.ozone.moderation.defs {
16
+
model RepoViewDetail { }
17
+
}
+8
-1
packages/emitter/test/integration/atproto/input/tools/ozone/moderation/getReporterStats.tsp
+8
-1
packages/emitter/test/integration/atproto/input/tools/ozone/moderation/getReporterStats.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace tools.ozone.moderation.getReporterStats {
4
-
@doc("Get reporter stats for a list of users.")
4
+
/** Get reporter stats for a list of users. */
5
5
@query
6
6
op main(
7
7
@maxItems(100)
···
11
11
@required stats: tools.ozone.moderation.defs.ReporterStats[];
12
12
};
13
13
}
14
+
15
+
// --- Externals ---
16
+
17
+
@external
18
+
namespace tools.ozone.moderation.defs {
19
+
model ReporterStats { }
20
+
}
+9
-1
packages/emitter/test/integration/atproto/input/tools/ozone/moderation/getRepos.tsp
+9
-1
packages/emitter/test/integration/atproto/input/tools/ozone/moderation/getRepos.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace tools.ozone.moderation.getRepos {
4
-
@doc("Get details about some repositories.")
4
+
/** Get details about some repositories. */
5
5
@query
6
6
op main(
7
7
@maxItems(100)
···
16
16
)[];
17
17
};
18
18
}
19
+
20
+
// --- Externals ---
21
+
22
+
@external
23
+
namespace tools.ozone.moderation.defs {
24
+
model RepoViewDetail { }
25
+
model RepoViewNotFound { }
26
+
}
+8
-1
packages/emitter/test/integration/atproto/input/tools/ozone/moderation/getSubjects.tsp
+8
-1
packages/emitter/test/integration/atproto/input/tools/ozone/moderation/getSubjects.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace tools.ozone.moderation.getSubjects {
4
-
@doc("Get details about subjects.")
4
+
/** Get details about subjects. */
5
5
@query
6
6
op main(
7
7
@minItems(1)
···
12
12
@required subjects: tools.ozone.moderation.defs.SubjectView[];
13
13
};
14
14
}
15
+
16
+
// --- Externals ---
17
+
18
+
@external
19
+
namespace tools.ozone.moderation.defs {
20
+
model SubjectView { }
21
+
}
+25
-18
packages/emitter/test/integration/atproto/input/tools/ozone/moderation/queryEvents.tsp
+25
-18
packages/emitter/test/integration/atproto/input/tools/ozone/moderation/queryEvents.tsp
···
8
8
"desc",
9
9
}
10
10
11
-
@doc("List moderation events related to a subject.")
11
+
/** List moderation events related to a subject. */
12
12
@query
13
13
op main(
14
-
@doc("The types of events (fully qualified string in the format of tools.ozone.moderation.defs#modEvent<name>) to filter by. If not specified, all events are returned.")
14
+
/** The types of events (fully qualified string in the format of tools.ozone.moderation.defs#modEvent<name>) to filter by. If not specified, all events are returned. */
15
15
types?: string[],
16
16
17
17
createdBy?: did,
18
18
19
-
@doc("Sort direction for the events. Defaults to descending order of created at timestamp.")
19
+
/** Sort direction for the events. Defaults to descending order of created at timestamp. */
20
20
sortDirection?: SortDirection = "desc",
21
21
22
-
@doc("Retrieve events created after a given timestamp")
22
+
/** Retrieve events created after a given timestamp */
23
23
createdAfter?: datetime,
24
24
25
-
@doc("Retrieve events created before a given timestamp")
25
+
/** Retrieve events created before a given timestamp */
26
26
createdBefore?: datetime,
27
27
28
28
subject?: uri,
29
29
30
30
@maxItems(20)
31
-
@doc("If specified, only events where the subject belongs to the given collections will be returned. When subjectType is set to 'account', this will be ignored.")
31
+
/** If specified, only events where the subject belongs to the given collections will be returned. When subjectType is set to 'account', this will be ignored. */
32
32
collections?: nsid[],
33
33
34
-
@doc("If specified, only events where the subject is of the given type (account or record) will be returned. When this is set to 'account' the 'collections' parameter will be ignored. When includeAllUserRecords or subject is set, this will be ignored.")
34
+
/** If specified, only events where the subject is of the given type (account or record) will be returned. When this is set to 'account' the 'collections' parameter will be ignored. When includeAllUserRecords or subject is set, this will be ignored. */
35
35
subjectType?: "account" | "record" | string,
36
36
37
-
@doc("If true, events on all record types (posts, lists, profile etc.) or records from given 'collections' param, owned by the did are returned.")
37
+
/** If true, events on all record types (posts, lists, profile etc.) or records from given 'collections' param, owned by the did are returned. */
38
38
includeAllUserRecords?: boolean = false,
39
39
40
40
@minValue(1)
41
41
@maxValue(100)
42
42
limit?: int32 = 50,
43
43
44
-
@doc("If true, only events with comments are returned")
44
+
/** If true, only events with comments are returned */
45
45
hasComment?: boolean,
46
46
47
-
@doc("If specified, only events with comments containing the keyword are returned. Apply || separator to use multiple keywords and match using OR condition.")
47
+
/** If specified, only events with comments containing the keyword are returned. Apply || separator to use multiple keywords and match using OR condition. */
48
48
comment?: string,
49
49
50
-
@doc("If specified, only events where all of these labels were added are returned")
50
+
/** If specified, only events where all of these labels were added are returned */
51
51
addedLabels?: string[],
52
52
53
-
@doc("If specified, only events where all of these labels were removed are returned")
53
+
/** If specified, only events where all of these labels were removed are returned */
54
54
removedLabels?: string[],
55
55
56
-
@doc("If specified, only events where all of these tags were added are returned")
56
+
/** If specified, only events where all of these tags were added are returned */
57
57
addedTags?: string[],
58
58
59
-
@doc("If specified, only events where all of these tags were removed are returned")
59
+
/** If specified, only events where all of these tags were removed are returned */
60
60
removedTags?: string[],
61
61
62
62
reportTypes?: string[],
63
63
64
-
@doc("If specified, only events where the action policies match any of the given policies are returned")
64
+
/** If specified, only events where the action policies match any of the given policies are returned */
65
65
policies?: string[],
66
66
67
-
@doc("If specified, only events where the modTool name matches any of the given values are returned")
67
+
/** If specified, only events where the modTool name matches any of the given values are returned */
68
68
modTool?: string[],
69
69
70
-
@doc("If specified, only events where the batchId matches the given value are returned")
70
+
/** If specified, only events where the batchId matches the given value are returned */
71
71
batchId?: string,
72
72
73
-
@doc("If specified, only events where the age assurance state matches the given value are returned")
73
+
/** If specified, only events where the age assurance state matches the given value are returned */
74
74
ageAssuranceState?: "pending" | "assured" | "unknown" | "reset" | "blocked" | string,
75
75
76
76
cursor?: string
···
80
80
@required events: tools.ozone.moderation.defs.ModEventView[];
81
81
};
82
82
}
83
+
84
+
// --- Externals ---
85
+
86
+
@external
87
+
namespace tools.ozone.moderation.defs {
88
+
model ModEventView { }
89
+
}
+37
-30
packages/emitter/test/integration/atproto/input/tools/ozone/moderation/queryStatuses.tsp
+37
-30
packages/emitter/test/integration/atproto/input/tools/ozone/moderation/queryStatuses.tsp
···
18
18
"desc",
19
19
}
20
20
21
-
@doc("View moderation statuses of subjects (record or repo).")
21
+
/** View moderation statuses of subjects (record or repo). */
22
22
@query
23
23
op main(
24
-
@doc("Number of queues being used by moderators. Subjects will be split among all queues.")
24
+
/** Number of queues being used by moderators. Subjects will be split among all queues. */
25
25
queueCount?: integer,
26
26
27
-
@doc("Index of the queue to fetch subjects from. Works only when queueCount value is specified.")
27
+
/** Index of the queue to fetch subjects from. Works only when queueCount value is specified. */
28
28
queueIndex?: integer,
29
29
30
-
@doc("A seeder to shuffle/balance the queue items.")
30
+
/** A seeder to shuffle/balance the queue items. */
31
31
queueSeed?: string,
32
32
33
-
@doc("All subjects, or subjects from given 'collections' param, belonging to the account specified in the 'subject' param will be returned.")
33
+
/** All subjects, or subjects from given 'collections' param, belonging to the account specified in the 'subject' param will be returned. */
34
34
includeAllUserRecords?: boolean,
35
35
36
-
@doc("The subject to get the status for.")
36
+
/** The subject to get the status for. */
37
37
subject?: uri,
38
38
39
-
@doc("Search subjects by keyword from comments")
39
+
/** Search subjects by keyword from comments */
40
40
comment?: string,
41
41
42
-
@doc("Search subjects reported after a given timestamp")
42
+
/** Search subjects reported after a given timestamp */
43
43
reportedAfter?: datetime,
44
44
45
-
@doc("Search subjects reported before a given timestamp")
45
+
/** Search subjects reported before a given timestamp */
46
46
reportedBefore?: datetime,
47
47
48
-
@doc("Search subjects reviewed after a given timestamp")
48
+
/** Search subjects reviewed after a given timestamp */
49
49
reviewedAfter?: datetime,
50
50
51
-
@doc("Search subjects where the associated record/account was deleted after a given timestamp")
51
+
/** Search subjects where the associated record/account was deleted after a given timestamp */
52
52
hostingDeletedAfter?: datetime,
53
53
54
-
@doc("Search subjects where the associated record/account was deleted before a given timestamp")
54
+
/** Search subjects where the associated record/account was deleted before a given timestamp */
55
55
hostingDeletedBefore?: datetime,
56
56
57
-
@doc("Search subjects where the associated record/account was updated after a given timestamp")
57
+
/** Search subjects where the associated record/account was updated after a given timestamp */
58
58
hostingUpdatedAfter?: datetime,
59
59
60
-
@doc("Search subjects where the associated record/account was updated before a given timestamp")
60
+
/** Search subjects where the associated record/account was updated before a given timestamp */
61
61
hostingUpdatedBefore?: datetime,
62
62
63
-
@doc("Search subjects by the status of the associated record/account")
63
+
/** Search subjects by the status of the associated record/account */
64
64
hostingStatuses?: string[],
65
65
66
-
@doc("Search subjects reviewed before a given timestamp")
66
+
/** Search subjects reviewed before a given timestamp */
67
67
reviewedBefore?: datetime,
68
68
69
-
@doc("By default, we don't include muted subjects in the results. Set this to true to include them.")
69
+
/** By default, we don't include muted subjects in the results. Set this to true to include them. */
70
70
includeMuted?: boolean,
71
71
72
-
@doc("When set to true, only muted subjects and reporters will be returned.")
72
+
/** When set to true, only muted subjects and reporters will be returned. */
73
73
onlyMuted?: boolean,
74
74
75
-
@doc("Specify when fetching subjects in a certain state")
75
+
/** Specify when fetching subjects in a certain state */
76
76
reviewState?: string,
77
77
78
78
ignoreSubjects?: uri[],
79
79
80
-
@doc("Get all subject statuses that were reviewed by a specific moderator")
80
+
/** Get all subject statuses that were reviewed by a specific moderator */
81
81
lastReviewedBy?: did,
82
82
83
83
sortField?: SortField = "lastReportedAt",
84
84
85
85
sortDirection?: SortDirection = "desc",
86
86
87
-
@doc("Get subjects that were taken down")
87
+
/** Get subjects that were taken down */
88
88
takendown?: boolean,
89
89
90
-
@doc("Get subjects in unresolved appealed status")
90
+
/** Get subjects in unresolved appealed status */
91
91
appealed?: boolean,
92
92
93
93
@minValue(1)
94
94
@maxValue(100)
95
95
limit?: int32 = 50,
96
96
97
-
@doc("Items in this array are applied with OR filters. To apply AND filter, put all tags in the same string and separate using && characters")
97
+
/** Items in this array are applied with OR filters. To apply AND filter, put all tags in the same string and separate using && characters */
98
98
@maxItems(25)
99
99
tags?: string[],
100
100
···
103
103
cursor?: string,
104
104
105
105
@maxItems(20)
106
-
@doc("If specified, subjects belonging to the given collections will be returned. When subjectType is set to 'account', this will be ignored.")
106
+
/** If specified, subjects belonging to the given collections will be returned. When subjectType is set to 'account', this will be ignored. */
107
107
collections?: nsid[],
108
108
109
-
@doc("If specified, subjects of the given type (account or record) will be returned. When this is set to 'account' the 'collections' parameter will be ignored. When includeAllUserRecords or subject is set, this will be ignored.")
109
+
/** If specified, subjects of the given type (account or record) will be returned. When this is set to 'account' the 'collections' parameter will be ignored. When includeAllUserRecords or subject is set, this will be ignored. */
110
110
subjectType?: "account" | "record" | string,
111
111
112
-
@doc("If specified, only subjects that belong to an account that has at least this many suspensions will be returned.")
112
+
/** If specified, only subjects that belong to an account that has at least this many suspensions will be returned. */
113
113
minAccountSuspendCount?: integer,
114
114
115
-
@doc("If specified, only subjects that belong to an account that has at least this many reported records will be returned.")
115
+
/** If specified, only subjects that belong to an account that has at least this many reported records will be returned. */
116
116
minReportedRecordsCount?: integer,
117
117
118
-
@doc("If specified, only subjects that belong to an account that has at least this many taken down records will be returned.")
118
+
/** If specified, only subjects that belong to an account that has at least this many taken down records will be returned. */
119
119
minTakendownRecordsCount?: integer,
120
120
121
121
@minValue(0)
122
122
@maxValue(100)
123
-
@doc("If specified, only subjects that have priority score value above the given value will be returned.")
123
+
/** If specified, only subjects that have priority score value above the given value will be returned. */
124
124
minPriorityScore?: integer,
125
125
126
-
@doc("If specified, only subjects with the given age assurance state will be returned.")
126
+
/** If specified, only subjects with the given age assurance state will be returned. */
127
127
ageAssuranceState?: "pending" | "assured" | "unknown" | "reset" | "blocked" | string
128
128
): {
129
129
cursor?: string;
···
131
131
@required subjectStatuses: tools.ozone.moderation.defs.SubjectStatusView[];
132
132
};
133
133
}
134
+
135
+
// --- Externals ---
136
+
137
+
@external
138
+
namespace tools.ozone.moderation.defs {
139
+
model SubjectStatusView { }
140
+
}
+9
-2
packages/emitter/test/integration/atproto/input/tools/ozone/moderation/searchRepos.tsp
+9
-2
packages/emitter/test/integration/atproto/input/tools/ozone/moderation/searchRepos.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace tools.ozone.moderation.searchRepos {
4
-
@doc("Find repositories based on a search term.")
4
+
/** Find repositories based on a search term. */
5
5
@query
6
6
op main(
7
-
@doc("DEPRECATED: use 'q' instead")
7
+
/** DEPRECATED: use 'q' instead */
8
8
term?: string,
9
9
10
10
q?: string,
···
20
20
@required repos: tools.ozone.moderation.defs.RepoView[];
21
21
};
22
22
}
23
+
24
+
// --- Externals ---
25
+
26
+
@external
27
+
namespace tools.ozone.moderation.defs {
28
+
model RepoView { }
29
+
}
+90
-98
packages/emitter/test/integration/atproto/input/tools/ozone/report/defs.tsp
+90
-98
packages/emitter/test/integration/atproto/input/tools/ozone/report/defs.tsp
···
3
3
namespace tools.ozone.report.defs {
4
4
union ReasonType {
5
5
string,
6
-
7
-
ReasonAppeal: "tools.ozone.report.defs#reasonAppeal",
8
-
9
-
ReasonViolenceAnimalWelfare: "tools.ozone.report.defs#reasonViolenceAnimalWelfare",
10
-
ReasonViolenceThreats: "tools.ozone.report.defs#reasonViolenceThreats",
11
-
ReasonViolenceGraphicContent: "tools.ozone.report.defs#reasonViolenceGraphicContent",
12
-
ReasonViolenceSelfHarm: "tools.ozone.report.defs#reasonViolenceSelfHarm",
13
-
ReasonViolenceGlorification: "tools.ozone.report.defs#reasonViolenceGlorification",
14
-
ReasonViolenceExtremistContent: "tools.ozone.report.defs#reasonViolenceExtremistContent",
15
-
ReasonViolenceTrafficking: "tools.ozone.report.defs#reasonViolenceTrafficking",
16
-
ReasonViolenceOther: "tools.ozone.report.defs#reasonViolenceOther",
17
-
18
-
ReasonSexualAbuseContent: "tools.ozone.report.defs#reasonSexualAbuseContent",
19
-
ReasonSexualNCII: "tools.ozone.report.defs#reasonSexualNCII",
20
-
ReasonSexualSextortion: "tools.ozone.report.defs#reasonSexualSextortion",
21
-
ReasonSexualDeepfake: "tools.ozone.report.defs#reasonSexualDeepfake",
22
-
ReasonSexualAnimal: "tools.ozone.report.defs#reasonSexualAnimal",
23
-
ReasonSexualUnlabeled: "tools.ozone.report.defs#reasonSexualUnlabeled",
24
-
ReasonSexualOther: "tools.ozone.report.defs#reasonSexualOther",
25
-
26
-
ReasonChildSafetyCSAM: "tools.ozone.report.defs#reasonChildSafetyCSAM",
27
-
ReasonChildSafetyGroom: "tools.ozone.report.defs#reasonChildSafetyGroom",
28
-
ReasonChildSafetyMinorPrivacy: "tools.ozone.report.defs#reasonChildSafetyMinorPrivacy",
29
-
ReasonChildSafetyEndangerment: "tools.ozone.report.defs#reasonChildSafetyEndangerment",
30
-
ReasonChildSafetyHarassment: "tools.ozone.report.defs#reasonChildSafetyHarassment",
31
-
ReasonChildSafetyPromotion: "tools.ozone.report.defs#reasonChildSafetyPromotion",
32
-
ReasonChildSafetyOther: "tools.ozone.report.defs#reasonChildSafetyOther",
33
-
34
-
ReasonHarassmentTroll: "tools.ozone.report.defs#reasonHarassmentTroll",
35
-
ReasonHarassmentTargeted: "tools.ozone.report.defs#reasonHarassmentTargeted",
36
-
ReasonHarassmentHateSpeech: "tools.ozone.report.defs#reasonHarassmentHateSpeech",
37
-
ReasonHarassmentDoxxing: "tools.ozone.report.defs#reasonHarassmentDoxxing",
38
-
ReasonHarassmentOther: "tools.ozone.report.defs#reasonHarassmentOther",
39
-
40
-
ReasonMisleadingBot: "tools.ozone.report.defs#reasonMisleadingBot",
41
-
ReasonMisleadingImpersonation: "tools.ozone.report.defs#reasonMisleadingImpersonation",
42
-
ReasonMisleadingSpam: "tools.ozone.report.defs#reasonMisleadingSpam",
43
-
ReasonMisleadingScam: "tools.ozone.report.defs#reasonMisleadingScam",
44
-
ReasonMisleadingSyntheticContent: "tools.ozone.report.defs#reasonMisleadingSyntheticContent",
45
-
ReasonMisleadingMisinformation: "tools.ozone.report.defs#reasonMisleadingMisinformation",
46
-
ReasonMisleadingOther: "tools.ozone.report.defs#reasonMisleadingOther",
47
-
48
-
ReasonRuleSiteSecurity: "tools.ozone.report.defs#reasonRuleSiteSecurity",
49
-
ReasonRuleStolenContent: "tools.ozone.report.defs#reasonRuleStolenContent",
50
-
ReasonRuleProhibitedSales: "tools.ozone.report.defs#reasonRuleProhibitedSales",
51
-
ReasonRuleBanEvasion: "tools.ozone.report.defs#reasonRuleBanEvasion",
52
-
ReasonRuleOther: "tools.ozone.report.defs#reasonRuleOther",
53
-
54
-
ReasonCivicElectoralProcess: "tools.ozone.report.defs#reasonCivicElectoralProcess",
55
-
ReasonCivicDisclosure: "tools.ozone.report.defs#reasonCivicDisclosure",
56
-
ReasonCivicInterference: "tools.ozone.report.defs#reasonCivicInterference",
57
-
ReasonCivicMisinformation: "tools.ozone.report.defs#reasonCivicMisinformation",
58
-
ReasonCivicImpersonation: "tools.ozone.report.defs#reasonCivicImpersonation",
6
+
ReasonAppeal,
7
+
ReasonViolenceAnimalWelfare,
8
+
ReasonViolenceThreats,
9
+
ReasonViolenceGraphicContent,
10
+
ReasonViolenceSelfHarm,
11
+
ReasonViolenceGlorification,
12
+
ReasonViolenceExtremistContent,
13
+
ReasonViolenceTrafficking,
14
+
ReasonViolenceOther,
15
+
ReasonSexualAbuseContent,
16
+
ReasonSexualNCII,
17
+
ReasonSexualSextortion,
18
+
ReasonSexualDeepfake,
19
+
ReasonSexualAnimal,
20
+
ReasonSexualUnlabeled,
21
+
ReasonSexualOther,
22
+
ReasonChildSafetyCSAM,
23
+
ReasonChildSafetyGroom,
24
+
ReasonChildSafetyMinorPrivacy,
25
+
ReasonChildSafetyEndangerment,
26
+
ReasonChildSafetyHarassment,
27
+
ReasonChildSafetyPromotion,
28
+
ReasonChildSafetyOther,
29
+
ReasonHarassmentTroll,
30
+
ReasonHarassmentTargeted,
31
+
ReasonHarassmentHateSpeech,
32
+
ReasonHarassmentDoxxing,
33
+
ReasonHarassmentOther,
34
+
ReasonMisleadingBot,
35
+
ReasonMisleadingImpersonation,
36
+
ReasonMisleadingSpam,
37
+
ReasonMisleadingScam,
38
+
ReasonMisleadingSyntheticContent,
39
+
ReasonMisleadingMisinformation,
40
+
ReasonMisleadingOther,
41
+
ReasonRuleSiteSecurity,
42
+
ReasonRuleStolenContent,
43
+
ReasonRuleProhibitedSales,
44
+
ReasonRuleBanEvasion,
45
+
ReasonRuleOther,
46
+
ReasonCivicElectoralProcess,
47
+
ReasonCivicDisclosure,
48
+
ReasonCivicInterference,
49
+
ReasonCivicMisinformation,
50
+
ReasonCivicImpersonation,
59
51
}
60
52
61
-
@doc("Appeal a previously taken moderation action")
53
+
/** Appeal a previously taken moderation action */
62
54
@token
63
55
model ReasonAppeal {}
64
56
65
-
@doc("Animal welfare violations")
57
+
/** Animal welfare violations */
66
58
@token
67
59
model ReasonViolenceAnimalWelfare {}
68
60
69
-
@doc("Threats or incitement")
61
+
/** Threats or incitement */
70
62
@token
71
63
model ReasonViolenceThreats {}
72
64
73
-
@doc("Graphic violent content")
65
+
/** Graphic violent content */
74
66
@token
75
67
model ReasonViolenceGraphicContent {}
76
68
77
-
@doc("Self harm")
69
+
/** Self harm */
78
70
@token
79
71
model ReasonViolenceSelfHarm {}
80
72
81
-
@doc("Glorification of violence")
73
+
/** Glorification of violence */
82
74
@token
83
75
model ReasonViolenceGlorification {}
84
76
85
-
@doc("Extremist content. These reports will be sent only be sent to the application's Moderation Authority.")
77
+
/** Extremist content. These reports will be sent only be sent to the application's Moderation Authority. */
86
78
@token
87
79
model ReasonViolenceExtremistContent {}
88
80
89
-
@doc("Human trafficking")
81
+
/** Human trafficking */
90
82
@token
91
83
model ReasonViolenceTrafficking {}
92
84
93
-
@doc("Other violent content")
85
+
/** Other violent content */
94
86
@token
95
87
model ReasonViolenceOther {}
96
88
97
-
@doc("Adult sexual abuse content")
89
+
/** Adult sexual abuse content */
98
90
@token
99
91
model ReasonSexualAbuseContent {}
100
92
101
-
@doc("Non-consensual intimate imagery")
93
+
/** Non-consensual intimate imagery */
102
94
@token
103
95
model ReasonSexualNCII {}
104
96
105
-
@doc("Sextortion")
97
+
/** Sextortion */
106
98
@token
107
99
model ReasonSexualSextortion {}
108
100
109
-
@doc("Deepfake adult content")
101
+
/** Deepfake adult content */
110
102
@token
111
103
model ReasonSexualDeepfake {}
112
104
113
-
@doc("Animal sexual abuse")
105
+
/** Animal sexual abuse */
114
106
@token
115
107
model ReasonSexualAnimal {}
116
108
117
-
@doc("Unlabelled adult content")
109
+
/** Unlabelled adult content */
118
110
@token
119
111
model ReasonSexualUnlabeled {}
120
112
121
-
@doc("Other sexual violence content")
113
+
/** Other sexual violence content */
122
114
@token
123
115
model ReasonSexualOther {}
124
116
125
-
@doc("Child sexual abuse material (CSAM). These reports will be sent only be sent to the application's Moderation Authority.")
117
+
/** Child sexual abuse material (CSAM). These reports will be sent only be sent to the application's Moderation Authority. */
126
118
@token
127
119
model ReasonChildSafetyCSAM {}
128
120
129
-
@doc("Grooming or predatory behavior. These reports will be sent only be sent to the application's Moderation Authority.")
121
+
/** Grooming or predatory behavior. These reports will be sent only be sent to the application's Moderation Authority. */
130
122
@token
131
123
model ReasonChildSafetyGroom {}
132
124
133
-
@doc("Privacy violation involving a minor")
125
+
/** Privacy violation involving a minor */
134
126
@token
135
127
model ReasonChildSafetyMinorPrivacy {}
136
128
137
-
@doc("Child endangerment. These reports will be sent only be sent to the application's Moderation Authority.")
129
+
/** Child endangerment. These reports will be sent only be sent to the application's Moderation Authority. */
138
130
@token
139
131
model ReasonChildSafetyEndangerment {}
140
132
141
-
@doc("Harassment or bullying of minors")
133
+
/** Harassment or bullying of minors */
142
134
@token
143
135
model ReasonChildSafetyHarassment {}
144
136
145
-
@doc("Promotion of child exploitation. These reports will be sent only be sent to the application's Moderation Authority.")
137
+
/** Promotion of child exploitation. These reports will be sent only be sent to the application's Moderation Authority. */
146
138
@token
147
139
model ReasonChildSafetyPromotion {}
148
140
149
-
@doc("Other child safety. These reports will be sent only be sent to the application's Moderation Authority.")
141
+
/** Other child safety. These reports will be sent only be sent to the application's Moderation Authority. */
150
142
@token
151
143
model ReasonChildSafetyOther {}
152
144
153
-
@doc("Trolling")
145
+
/** Trolling */
154
146
@token
155
147
model ReasonHarassmentTroll {}
156
148
157
-
@doc("Targeted harassment")
149
+
/** Targeted harassment */
158
150
@token
159
151
model ReasonHarassmentTargeted {}
160
152
161
-
@doc("Hate speech")
153
+
/** Hate speech */
162
154
@token
163
155
model ReasonHarassmentHateSpeech {}
164
156
165
-
@doc("Doxxing")
157
+
/** Doxxing */
166
158
@token
167
159
model ReasonHarassmentDoxxing {}
168
160
169
-
@doc("Other harassing or hateful content")
161
+
/** Other harassing or hateful content */
170
162
@token
171
163
model ReasonHarassmentOther {}
172
164
173
-
@doc("Fake account or bot")
165
+
/** Fake account or bot */
174
166
@token
175
167
model ReasonMisleadingBot {}
176
168
177
-
@doc("Impersonation")
169
+
/** Impersonation */
178
170
@token
179
171
model ReasonMisleadingImpersonation {}
180
172
181
-
@doc("Spam")
173
+
/** Spam */
182
174
@token
183
175
model ReasonMisleadingSpam {}
184
176
185
-
@doc("Scam")
177
+
/** Scam */
186
178
@token
187
179
model ReasonMisleadingScam {}
188
180
189
-
@doc("Unlabelled gen-AI or synthetic content")
181
+
/** Unlabelled gen-AI or synthetic content */
190
182
@token
191
183
model ReasonMisleadingSyntheticContent {}
192
184
193
-
@doc("Harmful false claims")
185
+
/** Harmful false claims */
194
186
@token
195
187
model ReasonMisleadingMisinformation {}
196
188
197
-
@doc("Other misleading content")
189
+
/** Other misleading content */
198
190
@token
199
191
model ReasonMisleadingOther {}
200
192
201
-
@doc("Hacking or system attacks")
193
+
/** Hacking or system attacks */
202
194
@token
203
195
model ReasonRuleSiteSecurity {}
204
196
205
-
@doc("Stolen content")
197
+
/** Stolen content */
206
198
@token
207
199
model ReasonRuleStolenContent {}
208
200
209
-
@doc("Promoting or selling prohibited items or services")
201
+
/** Promoting or selling prohibited items or services */
210
202
@token
211
203
model ReasonRuleProhibitedSales {}
212
204
213
-
@doc("Banned user returning")
205
+
/** Banned user returning */
214
206
@token
215
207
model ReasonRuleBanEvasion {}
216
208
217
-
@doc("Other")
209
+
/** Other */
218
210
@token
219
211
model ReasonRuleOther {}
220
212
221
-
@doc("Electoral process violations")
213
+
/** Electoral process violations */
222
214
@token
223
215
model ReasonCivicElectoralProcess {}
224
216
225
-
@doc("Disclosure & transparency violations")
217
+
/** Disclosure & transparency violations */
226
218
@token
227
219
model ReasonCivicDisclosure {}
228
220
229
-
@doc("Voter intimidation or interference")
221
+
/** Voter intimidation or interference */
230
222
@token
231
223
model ReasonCivicInterference {}
232
224
233
-
@doc("Election misinformation")
225
+
/** Election misinformation */
234
226
@token
235
227
model ReasonCivicMisinformation {}
236
228
237
-
@doc("Impersonation of electoral officials/entities")
229
+
/** Impersonation of electoral officials/entities */
238
230
@token
239
231
model ReasonCivicImpersonation {}
240
232
}
+16
-6
packages/emitter/test/integration/atproto/input/tools/ozone/safelink/addRule.tsp
+16
-6
packages/emitter/test/integration/atproto/input/tools/ozone/safelink/addRule.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace tools.ozone.safelink.addRule {
4
-
@doc("The provided URL is invalid")
4
+
/** The provided URL is invalid */
5
5
model InvalidUrl {}
6
6
7
-
@doc("A rule for this URL/domain already exists")
7
+
/** A rule for this URL/domain already exists */
8
8
model RuleAlreadyExists {}
9
9
10
-
@doc("Add a new URL safety rule")
10
+
/** Add a new URL safety rule */
11
11
@procedure
12
12
@errors(InvalidUrl, RuleAlreadyExists)
13
13
op main(input: {
14
-
@doc("The URL or domain to apply the rule to")
14
+
/** The URL or domain to apply the rule to */
15
15
@required
16
16
url: string;
17
17
···
21
21
22
22
@required reason: tools.ozone.safelink.defs.ReasonType;
23
23
24
-
@doc("Optional comment about the decision")
24
+
/** Optional comment about the decision */
25
25
comment?: string;
26
26
27
-
@doc("Author DID. Only respected when using admin auth")
27
+
/** Author DID. Only respected when using admin auth */
28
28
createdBy?: did;
29
29
}): tools.ozone.safelink.defs.Event;
30
30
}
31
+
32
+
// --- Externals ---
33
+
34
+
@external
35
+
namespace tools.ozone.safelink.defs {
36
+
model PatternType { }
37
+
model ActionType { }
38
+
model ReasonType { }
39
+
model Event { }
40
+
}
+11
-11
packages/emitter/test/integration/atproto/input/tools/ozone/safelink/defs.tsp
+11
-11
packages/emitter/test/integration/atproto/input/tools/ozone/safelink/defs.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace tools.ozone.safelink.defs {
4
-
@doc("An event for URL safety decisions")
4
+
/** An event for URL safety decisions */
5
5
model Event {
6
-
@doc("Auto-incrementing row ID")
6
+
/** Auto-incrementing row ID */
7
7
@required
8
8
id: int32;
9
9
10
10
@required eventType: EventType;
11
11
12
-
@doc("The URL that this rule applies to")
12
+
/** The URL that this rule applies to */
13
13
@required
14
14
url: string;
15
15
···
17
17
@required action: ActionType;
18
18
@required reason: ReasonType;
19
19
20
-
@doc("DID of the user who created this rule")
20
+
/** DID of the user who created this rule */
21
21
@required
22
22
createdBy: did;
23
23
24
24
@required createdAt: datetime;
25
25
26
-
@doc("Optional comment about the decision")
26
+
/** Optional comment about the decision */
27
27
comment?: string;
28
28
}
29
29
···
55
55
string,
56
56
}
57
57
58
-
@doc("Input for creating a URL safety rule")
58
+
/** Input for creating a URL safety rule */
59
59
model UrlRule {
60
-
@doc("The URL or domain to apply the rule to")
60
+
/** The URL or domain to apply the rule to */
61
61
@required
62
62
url: string;
63
63
···
65
65
@required action: ActionType;
66
66
@required reason: ReasonType;
67
67
68
-
@doc("Optional comment about the decision")
68
+
/** Optional comment about the decision */
69
69
comment?: string;
70
70
71
-
@doc("DID of the user added the rule.")
71
+
/** DID of the user added the rule. */
72
72
@required
73
73
createdBy: did;
74
74
75
-
@doc("Timestamp when the rule was created")
75
+
/** Timestamp when the rule was created */
76
76
@required
77
77
createdAt: datetime;
78
78
79
-
@doc("Timestamp when the rule was last updated")
79
+
/** Timestamp when the rule was last updated */
80
80
@required
81
81
updatedAt: datetime;
82
82
}
+14
-7
packages/emitter/test/integration/atproto/input/tools/ozone/safelink/queryEvents.tsp
+14
-7
packages/emitter/test/integration/atproto/input/tools/ozone/safelink/queryEvents.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace tools.ozone.safelink.queryEvents {
4
-
@doc("Query URL safety audit events")
4
+
/** Query URL safety audit events */
5
5
@procedure
6
6
op main(input: {
7
-
@doc("Cursor for pagination")
7
+
/** Cursor for pagination */
8
8
cursor?: string;
9
9
10
10
@minValue(1)
11
11
@maxValue(100)
12
-
@doc("Maximum number of results to return")
12
+
/** Maximum number of results to return */
13
13
limit?: int32 = 50;
14
14
15
-
@doc("Filter by specific URLs or domains")
15
+
/** Filter by specific URLs or domains */
16
16
urls?: string[];
17
17
18
-
@doc("Filter by pattern type")
18
+
/** Filter by pattern type */
19
19
patternType?: string;
20
20
21
-
@doc("Sort direction")
21
+
/** Sort direction */
22
22
sortDirection?: "asc" | "desc" | string = "desc";
23
23
}): {
24
-
@doc("Next cursor for pagination. Only present if there are more results.")
24
+
/** Next cursor for pagination. Only present if there are more results. */
25
25
cursor?: string;
26
26
27
27
@required events: tools.ozone.safelink.defs.Event[];
28
28
};
29
29
}
30
+
31
+
// --- Externals ---
32
+
33
+
@external
34
+
namespace tools.ozone.safelink.defs {
35
+
model Event { }
36
+
}
+17
-10
packages/emitter/test/integration/atproto/input/tools/ozone/safelink/queryRules.tsp
+17
-10
packages/emitter/test/integration/atproto/input/tools/ozone/safelink/queryRules.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace tools.ozone.safelink.queryRules {
4
-
@doc("Query URL safety rules")
4
+
/** Query URL safety rules */
5
5
@procedure
6
6
op main(input: {
7
-
@doc("Cursor for pagination")
7
+
/** Cursor for pagination */
8
8
cursor?: string;
9
9
10
10
@minValue(1)
11
11
@maxValue(100)
12
-
@doc("Maximum number of results to return")
12
+
/** Maximum number of results to return */
13
13
limit?: int32 = 50;
14
14
15
-
@doc("Filter by specific URLs or domains")
15
+
/** Filter by specific URLs or domains */
16
16
urls?: string[];
17
17
18
-
@doc("Filter by pattern type")
18
+
/** Filter by pattern type */
19
19
patternType?: string;
20
20
21
-
@doc("Filter by action types")
21
+
/** Filter by action types */
22
22
actions?: string[];
23
23
24
-
@doc("Filter by reason type")
24
+
/** Filter by reason type */
25
25
reason?: string;
26
26
27
-
@doc("Filter by rule creator")
27
+
/** Filter by rule creator */
28
28
createdBy?: did;
29
29
30
-
@doc("Sort direction")
30
+
/** Sort direction */
31
31
sortDirection?: "asc" | "desc" | string = "desc";
32
32
}): {
33
-
@doc("Next cursor for pagination. Only present if there are more results.")
33
+
/** Next cursor for pagination. Only present if there are more results. */
34
34
cursor?: string;
35
35
36
36
@required rules: tools.ozone.safelink.defs.UrlRule[];
37
37
};
38
38
}
39
+
40
+
// --- Externals ---
41
+
42
+
@external
43
+
namespace tools.ozone.safelink.defs {
44
+
model UrlRule { }
45
+
}
+13
-5
packages/emitter/test/integration/atproto/input/tools/ozone/safelink/removeRule.tsp
+13
-5
packages/emitter/test/integration/atproto/input/tools/ozone/safelink/removeRule.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace tools.ozone.safelink.removeRule {
4
-
@doc("No active rule found for this URL/domain")
4
+
/** No active rule found for this URL/domain */
5
5
model RuleNotFound {}
6
6
7
-
@doc("Remove an existing URL safety rule")
7
+
/** Remove an existing URL safety rule */
8
8
@procedure
9
9
@errors(RuleNotFound)
10
10
op main(input: {
11
-
@doc("The URL or domain to remove the rule for")
11
+
/** The URL or domain to remove the rule for */
12
12
@required
13
13
url: string;
14
14
15
15
@required pattern: tools.ozone.safelink.defs.PatternType;
16
16
17
-
@doc("Optional comment about why the rule is being removed")
17
+
/** Optional comment about why the rule is being removed */
18
18
comment?: string;
19
19
20
-
@doc("Optional DID of the user. Only respected when using admin auth.")
20
+
/** Optional DID of the user. Only respected when using admin auth. */
21
21
createdBy?: did;
22
22
}): tools.ozone.safelink.defs.Event;
23
23
}
24
+
25
+
// --- Externals ---
26
+
27
+
@external
28
+
namespace tools.ozone.safelink.defs {
29
+
model PatternType { }
30
+
model Event { }
31
+
}
+15
-5
packages/emitter/test/integration/atproto/input/tools/ozone/safelink/updateRule.tsp
+15
-5
packages/emitter/test/integration/atproto/input/tools/ozone/safelink/updateRule.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace tools.ozone.safelink.updateRule {
4
-
@doc("No active rule found for this URL/domain")
4
+
/** No active rule found for this URL/domain */
5
5
model RuleNotFound {}
6
6
7
-
@doc("Update an existing URL safety rule")
7
+
/** Update an existing URL safety rule */
8
8
@procedure
9
9
@errors(RuleNotFound)
10
10
op main(input: {
11
-
@doc("The URL or domain to update the rule for")
11
+
/** The URL or domain to update the rule for */
12
12
@required
13
13
url: string;
14
14
···
18
18
19
19
@required reason: tools.ozone.safelink.defs.ReasonType;
20
20
21
-
@doc("Optional comment about the update")
21
+
/** Optional comment about the update */
22
22
comment?: string;
23
23
24
-
@doc("Optional DID to credit as the creator. Only respected for admin_token authentication.")
24
+
/** Optional DID to credit as the creator. Only respected for admin_token authentication. */
25
25
createdBy?: did;
26
26
}): tools.ozone.safelink.defs.Event;
27
27
}
28
+
29
+
// --- Externals ---
30
+
31
+
@external
32
+
namespace tools.ozone.safelink.defs {
33
+
model PatternType { }
34
+
model ActionType { }
35
+
model ReasonType { }
36
+
model Event { }
37
+
}
+18
-9
packages/emitter/test/integration/atproto/input/tools/ozone/server/getConfig.tsp
+18
-9
packages/emitter/test/integration/atproto/input/tools/ozone/server/getConfig.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace tools.ozone.server.getConfig {
4
-
@doc("Get details about ozone's server configuration.")
4
+
/** Get details about ozone's server configuration. */
5
5
@query
6
6
op main(): {
7
7
appview?: ServiceConfig;
···
10
10
chat?: ServiceConfig;
11
11
viewer?: ViewerConfig;
12
12
13
-
@doc("The did of the verifier used for verification.")
13
+
/** The did of the verifier used for verification. */
14
14
verifierDid?: did;
15
15
};
16
16
···
19
19
}
20
20
21
21
model ViewerConfig {
22
-
role?: (
23
-
| "tools.ozone.team.defs#roleAdmin"
24
-
| "tools.ozone.team.defs#roleModerator"
25
-
| "tools.ozone.team.defs#roleTriage"
26
-
| "tools.ozone.team.defs#roleVerifier"
27
-
| string
28
-
);
22
+
role?:
23
+
| tools.ozone.team.defs.RoleAdmin
24
+
| tools.ozone.team.defs.RoleModerator
25
+
| tools.ozone.team.defs.RoleTriage
26
+
| tools.ozone.team.defs.RoleVerifier
27
+
| string;
29
28
}
30
29
}
30
+
31
+
// --- Externals ---
32
+
33
+
@external
34
+
namespace tools.ozone.team.defs {
35
+
@token model RoleAdmin { }
36
+
@token model RoleModerator { }
37
+
@token model RoleTriage { }
38
+
@token model RoleVerifier { }
39
+
}
+3
-3
packages/emitter/test/integration/atproto/input/tools/ozone/set/addValues.tsp
+3
-3
packages/emitter/test/integration/atproto/input/tools/ozone/set/addValues.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace tools.ozone.set.addValues {
4
-
@doc("Add values to a specific set. Attempting to add values to a set that does not exist will result in an error.")
4
+
/** Add values to a specific set. Attempting to add values to a set that does not exist will result in an error. */
5
5
@procedure
6
6
op main(input: {
7
-
@doc("Name of the set to add values to")
7
+
/** Name of the set to add values to */
8
8
@required
9
9
name: string;
10
10
11
11
@minItems(1)
12
12
@maxItems(1000)
13
-
@doc("Array of string values to add to the set")
13
+
/** Array of string values to add to the set */
14
14
@required
15
15
values: string[];
16
16
}): void;
+3
-3
packages/emitter/test/integration/atproto/input/tools/ozone/set/deleteSet.tsp
+3
-3
packages/emitter/test/integration/atproto/input/tools/ozone/set/deleteSet.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace tools.ozone.set.deleteSet {
4
-
@doc("set with the given name does not exist")
4
+
/** set with the given name does not exist */
5
5
model SetNotFound {}
6
6
7
-
@doc("Delete an entire set. Attempting to delete a set that does not exist will result in an error.")
7
+
/** Delete an entire set. Attempting to delete a set that does not exist will result in an error. */
8
8
@procedure
9
9
@errors(SetNotFound)
10
10
op main(input: {
11
-
@doc("Name of the set to delete")
11
+
/** Name of the set to delete */
12
12
@required
13
13
name: string;
14
14
}): {};
+4
-4
packages/emitter/test/integration/atproto/input/tools/ozone/set/deleteValues.tsp
+4
-4
packages/emitter/test/integration/atproto/input/tools/ozone/set/deleteValues.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace tools.ozone.set.deleteValues {
4
-
@doc("set with the given name does not exist")
4
+
/** set with the given name does not exist */
5
5
model SetNotFound {}
6
6
7
-
@doc("Delete values from a specific set. Attempting to delete values that are not in the set will not result in an error")
7
+
/** Delete values from a specific set. Attempting to delete values that are not in the set will not result in an error */
8
8
@procedure
9
9
@errors(SetNotFound)
10
10
op main(input: {
11
-
@doc("Name of the set to delete values from")
11
+
/** Name of the set to delete values from */
12
12
@required
13
13
name: string;
14
14
15
15
@minItems(1)
16
-
@doc("Array of string values to delete from the set")
16
+
/** Array of string values to delete from the set */
17
17
@required
18
18
values: string[];
19
19
}): void;
+9
-2
packages/emitter/test/integration/atproto/input/tools/ozone/set/getValues.tsp
+9
-2
packages/emitter/test/integration/atproto/input/tools/ozone/set/getValues.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace tools.ozone.set.getValues {
4
-
@doc("set with the given name does not exist")
4
+
/** set with the given name does not exist */
5
5
model SetNotFound {}
6
6
7
-
@doc("Get a specific set and its values")
7
+
/** Get a specific set and its values */
8
8
@query
9
9
@errors(SetNotFound)
10
10
op main(
···
23
23
cursor?: string;
24
24
};
25
25
}
26
+
27
+
// --- Externals ---
28
+
29
+
@external
30
+
namespace tools.ozone.set.defs {
31
+
model SetView { }
32
+
}
+9
-2
packages/emitter/test/integration/atproto/input/tools/ozone/set/querySets.tsp
+9
-2
packages/emitter/test/integration/atproto/input/tools/ozone/set/querySets.tsp
···
16
16
"desc",
17
17
}
18
18
19
-
@doc("Query available sets")
19
+
/** Query available sets */
20
20
@query
21
21
op main(
22
22
@minValue(1)
···
29
29
30
30
sortBy?: SortBy = "name",
31
31
32
-
@doc("Defaults to ascending order of name field.")
32
+
/** Defaults to ascending order of name field. */
33
33
sortDirection?: SortDirection = "asc"
34
34
): {
35
35
@required sets: tools.ozone.set.defs.SetView[];
···
37
37
cursor?: string;
38
38
};
39
39
}
40
+
41
+
// --- Externals ---
42
+
43
+
@external
44
+
namespace tools.ozone.set.defs {
45
+
model SetView { }
46
+
}
+9
-1
packages/emitter/test/integration/atproto/input/tools/ozone/set/upsertSet.tsp
+9
-1
packages/emitter/test/integration/atproto/input/tools/ozone/set/upsertSet.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace tools.ozone.set.upsertSet {
4
-
@doc("Create or update set metadata")
4
+
/** Create or update set metadata */
5
5
@procedure
6
6
op main(input: tools.ozone.set.defs.Set): tools.ozone.set.defs.SetView;
7
7
}
8
+
9
+
// --- Externals ---
10
+
11
+
@external
12
+
namespace tools.ozone.set.defs {
13
+
model Set { }
14
+
model SetView { }
15
+
}
+14
-4
packages/emitter/test/integration/atproto/input/tools/ozone/setting/defs.tsp
+14
-4
packages/emitter/test/integration/atproto/input/tools/ozone/setting/defs.tsp
···
16
16
updatedAt?: datetime;
17
17
18
18
managerRole?:
19
-
| "tools.ozone.team.defs#roleModerator"
20
-
| "tools.ozone.team.defs#roleTriage"
21
-
| "tools.ozone.team.defs#roleAdmin"
22
-
| "tools.ozone.team.defs#roleVerifier"
19
+
| tools.ozone.team.defs.RoleModerator
20
+
| tools.ozone.team.defs.RoleTriage
21
+
| tools.ozone.team.defs.RoleAdmin
22
+
| tools.ozone.team.defs.RoleVerifier
23
23
| string;
24
24
25
25
@required scope: "instance" | "personal" | string;
···
27
27
@required lastUpdatedBy: did;
28
28
}
29
29
}
30
+
31
+
// --- Externals ---
32
+
33
+
@external
34
+
namespace tools.ozone.team.defs {
35
+
@token model RoleModerator { }
36
+
@token model RoleTriage { }
37
+
@token model RoleAdmin { }
38
+
@token model RoleVerifier { }
39
+
}
+10
-3
packages/emitter/test/integration/atproto/input/tools/ozone/setting/listOptions.tsp
+10
-3
packages/emitter/test/integration/atproto/input/tools/ozone/setting/listOptions.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace tools.ozone.setting.listOptions {
4
-
@doc("List settings with optional filtering")
4
+
/** List settings with optional filtering */
5
5
@query
6
6
op main(
7
7
@minValue(1)
···
12
12
13
13
scope?: "instance" | "personal" | string = "instance",
14
14
15
-
@doc("Filter keys by prefix")
15
+
/** Filter keys by prefix */
16
16
prefix?: string,
17
17
18
18
@maxItems(100)
19
-
@doc("Filter for only the specified keys. Ignored if prefix is provided")
19
+
/** Filter for only the specified keys. Ignored if prefix is provided */
20
20
keys?: nsid[]
21
21
): {
22
22
cursor?: string;
···
24
24
@required options: tools.ozone.setting.defs.Option[];
25
25
};
26
26
}
27
+
28
+
// --- Externals ---
29
+
30
+
@external
31
+
namespace tools.ozone.setting.defs {
32
+
model Option { }
33
+
}
+1
-1
packages/emitter/test/integration/atproto/input/tools/ozone/setting/removeOptions.tsp
+1
-1
packages/emitter/test/integration/atproto/input/tools/ozone/setting/removeOptions.tsp
+20
-5
packages/emitter/test/integration/atproto/input/tools/ozone/setting/upsertOption.tsp
+20
-5
packages/emitter/test/integration/atproto/input/tools/ozone/setting/upsertOption.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace tools.ozone.setting.upsertOption {
4
-
@doc("Create or update setting option")
4
+
/** Create or update setting option */
5
5
@procedure
6
6
op main(input: {
7
7
@required key: nsid;
···
14
14
description?: string;
15
15
16
16
managerRole?:
17
-
| "tools.ozone.team.defs#roleModerator"
18
-
| "tools.ozone.team.defs#roleTriage"
19
-
| "tools.ozone.team.defs#roleVerifier"
20
-
| "tools.ozone.team.defs#roleAdmin"
17
+
| tools.ozone.team.defs.RoleModerator
18
+
| tools.ozone.team.defs.RoleTriage
19
+
| tools.ozone.team.defs.RoleVerifier
20
+
| tools.ozone.team.defs.RoleAdmin
21
21
| string;
22
22
}): {
23
23
@required option: tools.ozone.setting.defs.Option;
24
24
};
25
25
}
26
+
27
+
// --- Externals ---
28
+
29
+
@external
30
+
namespace tools.ozone.team.defs {
31
+
@token model RoleModerator { }
32
+
@token model RoleTriage { }
33
+
@token model RoleVerifier { }
34
+
@token model RoleAdmin { }
35
+
}
36
+
37
+
@external
38
+
namespace tools.ozone.setting.defs {
39
+
model Option { }
40
+
}
+8
-1
packages/emitter/test/integration/atproto/input/tools/ozone/signature/findCorrelation.tsp
+8
-1
packages/emitter/test/integration/atproto/input/tools/ozone/signature/findCorrelation.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace tools.ozone.signature.findCorrelation {
4
-
@doc("Find all correlated threat signatures between 2 or more accounts.")
4
+
/** Find all correlated threat signatures between 2 or more accounts. */
5
5
@query
6
6
op main(@required dids: did[]): {
7
7
@required details: tools.ozone.signature.defs.SigDetail[];
8
8
};
9
9
}
10
+
11
+
// --- Externals ---
12
+
13
+
@external
14
+
namespace tools.ozone.signature.defs {
15
+
model SigDetail { }
16
+
}
+13
-1
packages/emitter/test/integration/atproto/input/tools/ozone/signature/findRelatedAccounts.tsp
+13
-1
packages/emitter/test/integration/atproto/input/tools/ozone/signature/findRelatedAccounts.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace tools.ozone.signature.findRelatedAccounts {
4
-
@doc("Get accounts that share some matching threat signatures with the root account.")
4
+
/** Get accounts that share some matching threat signatures with the root account. */
5
5
@query
6
6
op main(
7
7
@required did: did,
···
23
23
similarities?: tools.ozone.signature.defs.SigDetail[];
24
24
}
25
25
}
26
+
27
+
// --- Externals ---
28
+
29
+
@external
30
+
namespace com.atproto.admin.defs {
31
+
model AccountView { }
32
+
}
33
+
34
+
@external
35
+
namespace tools.ozone.signature.defs {
36
+
model SigDetail { }
37
+
}
+8
-1
packages/emitter/test/integration/atproto/input/tools/ozone/signature/searchAccounts.tsp
+8
-1
packages/emitter/test/integration/atproto/input/tools/ozone/signature/searchAccounts.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace tools.ozone.signature.searchAccounts {
4
-
@doc("Search for accounts that match one or more threat signature values.")
4
+
/** Search for accounts that match one or more threat signature values. */
5
5
@query
6
6
op main(
7
7
@required values: string[],
···
17
17
@required accounts: com.atproto.admin.defs.AccountView[];
18
18
};
19
19
}
20
+
21
+
// --- Externals ---
22
+
23
+
@external
24
+
namespace com.atproto.admin.defs {
25
+
model AccountView { }
26
+
}
+19
-9
packages/emitter/test/integration/atproto/input/tools/ozone/team/addMember.tsp
+19
-9
packages/emitter/test/integration/atproto/input/tools/ozone/team/addMember.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace tools.ozone.team.addMember {
4
-
@doc("Member already exists in the team.")
4
+
/** Member already exists in the team. */
5
5
model MemberAlreadyExists {}
6
6
7
-
@doc("Add a member to the ozone team. Requires admin role.")
7
+
/** Add a member to the ozone team. Requires admin role. */
8
8
@procedure
9
9
@errors(MemberAlreadyExists)
10
10
op main(input: {
11
11
@required did: did;
12
12
13
13
@required
14
-
role: (
15
-
| "tools.ozone.team.defs#roleAdmin"
16
-
| "tools.ozone.team.defs#roleModerator"
17
-
| "tools.ozone.team.defs#roleVerifier"
18
-
| "tools.ozone.team.defs#roleTriage"
19
-
| string
20
-
);
14
+
role:
15
+
| tools.ozone.team.defs.RoleAdmin
16
+
| tools.ozone.team.defs.RoleModerator
17
+
| tools.ozone.team.defs.RoleVerifier
18
+
| tools.ozone.team.defs.RoleTriage
19
+
| string;
21
20
}): tools.ozone.team.defs.Member;
22
21
}
22
+
23
+
// --- Externals ---
24
+
25
+
@external
26
+
namespace tools.ozone.team.defs {
27
+
@token model RoleAdmin { }
28
+
@token model RoleModerator { }
29
+
@token model RoleVerifier { }
30
+
@token model RoleTriage { }
31
+
model Member { }
32
+
}
+12
-5
packages/emitter/test/integration/atproto/input/tools/ozone/team/defs.tsp
+12
-5
packages/emitter/test/integration/atproto/input/tools/ozone/team/defs.tsp
···
8
8
createdAt?: datetime;
9
9
updatedAt?: datetime;
10
10
lastUpdatedBy?: string;
11
-
@required role: "#roleAdmin" | "#roleModerator" | "#roleTriage" | "#roleVerifier" | string;
11
+
@required role: RoleAdmin | RoleModerator | RoleTriage | RoleVerifier | string;
12
12
}
13
13
14
-
@doc("Admin role. Highest level of access, can perform all actions.")
14
+
/** Admin role. Highest level of access, can perform all actions. */
15
15
@token
16
16
model RoleAdmin {}
17
17
18
-
@doc("Moderator role. Can perform most actions.")
18
+
/** Moderator role. Can perform most actions. */
19
19
@token
20
20
model RoleModerator {}
21
21
22
-
@doc("Triage role. Mostly intended for monitoring and escalating issues.")
22
+
/** Triage role. Mostly intended for monitoring and escalating issues. */
23
23
@token
24
24
model RoleTriage {}
25
25
26
-
@doc("Verifier role. Only allowed to issue verifications.")
26
+
/** Verifier role. Only allowed to issue verifications. */
27
27
@token
28
28
model RoleVerifier {}
29
29
}
30
+
31
+
// --- Externals ---
32
+
33
+
@external
34
+
namespace app.bsky.actor.defs {
35
+
model ProfileViewDetailed { }
36
+
}
+3
-3
packages/emitter/test/integration/atproto/input/tools/ozone/team/deleteMember.tsp
+3
-3
packages/emitter/test/integration/atproto/input/tools/ozone/team/deleteMember.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace tools.ozone.team.deleteMember {
4
-
@doc("The member being deleted does not exist")
4
+
/** The member being deleted does not exist */
5
5
model MemberNotFound {}
6
6
7
-
@doc("You can not delete yourself from the team")
7
+
/** You can not delete yourself from the team */
8
8
model CannotDeleteSelf {}
9
9
10
-
@doc("Delete a member from ozone team. Requires admin role.")
10
+
/** Delete a member from ozone team. Requires admin role. */
11
11
@procedure
12
12
@errors(MemberNotFound, CannotDeleteSelf)
13
13
op main(input: {
+8
-1
packages/emitter/test/integration/atproto/input/tools/ozone/team/listMembers.tsp
+8
-1
packages/emitter/test/integration/atproto/input/tools/ozone/team/listMembers.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace tools.ozone.team.listMembers {
4
-
@doc("List all members with access to the ozone service.")
4
+
/** List all members with access to the ozone service. */
5
5
@query
6
6
op main(
7
7
q?: string,
···
18
18
@required members: tools.ozone.team.defs.Member[];
19
19
};
20
20
}
21
+
22
+
// --- Externals ---
23
+
24
+
@external
25
+
namespace tools.ozone.team.defs {
26
+
model Member { }
27
+
}
+19
-9
packages/emitter/test/integration/atproto/input/tools/ozone/team/updateMember.tsp
+19
-9
packages/emitter/test/integration/atproto/input/tools/ozone/team/updateMember.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace tools.ozone.team.updateMember {
4
-
@doc("The member being updated does not exist in the team")
4
+
/** The member being updated does not exist in the team */
5
5
model MemberNotFound {}
6
6
7
-
@doc("Update a member in the ozone service. Requires admin role.")
7
+
/** Update a member in the ozone service. Requires admin role. */
8
8
@procedure
9
9
@errors(MemberNotFound)
10
10
op main(input: {
11
11
@required did: did;
12
12
disabled?: boolean;
13
13
14
-
role?: (
15
-
| "tools.ozone.team.defs#roleAdmin"
16
-
| "tools.ozone.team.defs#roleModerator"
17
-
| "tools.ozone.team.defs#roleVerifier"
18
-
| "tools.ozone.team.defs#roleTriage"
19
-
| string
20
-
);
14
+
role?:
15
+
| tools.ozone.team.defs.RoleAdmin
16
+
| tools.ozone.team.defs.RoleModerator
17
+
| tools.ozone.team.defs.RoleVerifier
18
+
| tools.ozone.team.defs.RoleTriage
19
+
| string;
21
20
}): tools.ozone.team.defs.Member;
22
21
}
22
+
23
+
// --- Externals ---
24
+
25
+
@external
26
+
namespace tools.ozone.team.defs {
27
+
@token model RoleAdmin { }
28
+
@token model RoleModerator { }
29
+
@token model RoleVerifier { }
30
+
@token model RoleTriage { }
31
+
model Member { }
32
+
}
+18
-10
packages/emitter/test/integration/atproto/input/tools/ozone/verification/defs.tsp
+18
-10
packages/emitter/test/integration/atproto/input/tools/ozone/verification/defs.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace tools.ozone.verification.defs {
4
-
@doc("Verification data for the associated subject.")
4
+
/** Verification data for the associated subject. */
5
5
model VerificationView {
6
-
@doc("The user who issued this verification.")
6
+
/** The user who issued this verification. */
7
7
@required
8
8
issuer: did;
9
9
10
-
@doc("The AT-URI of the verification record.")
10
+
/** The AT-URI of the verification record. */
11
11
@required
12
12
uri: atUri;
13
13
14
-
@doc("The subject of the verification.")
14
+
/** The subject of the verification. */
15
15
@required
16
16
subject: did;
17
17
18
-
@doc("Handle of the subject the verification applies to at the moment of verifying, which might not be the same at the time of viewing. The verification is only valid if the current handle matches the one at the time of verifying.")
18
+
/** Handle of the subject the verification applies to at the moment of verifying, which might not be the same at the time of viewing. The verification is only valid if the current handle matches the one at the time of verifying. */
19
19
@required
20
20
handle: handle;
21
21
22
-
@doc("Display name of the subject the verification applies to at the moment of verifying, which might not be the same at the time of viewing. The verification is only valid if the current displayName matches the one at the time of verifying.")
22
+
/** Display name of the subject the verification applies to at the moment of verifying, which might not be the same at the time of viewing. The verification is only valid if the current displayName matches the one at the time of verifying. */
23
23
@required
24
24
displayName: string;
25
25
26
-
@doc("Timestamp when the verification was created.")
26
+
/** Timestamp when the verification was created. */
27
27
@required
28
28
createdAt: datetime;
29
29
30
-
@doc("Describes the reason for revocation, also indicating that the verification is no longer valid.")
30
+
/** Describes the reason for revocation, also indicating that the verification is no longer valid. */
31
31
revokeReason?: string;
32
32
33
-
@doc("Timestamp when the verification was revoked.")
33
+
/** Timestamp when the verification was revoked. */
34
34
revokedAt?: datetime;
35
35
36
-
@doc("The user who revoked this verification.")
36
+
/** The user who revoked this verification. */
37
37
revokedBy?: did;
38
38
39
39
subjectProfile?: (never | unknown);
···
52
52
);
53
53
}
54
54
}
55
+
56
+
// --- Externals ---
57
+
58
+
@external
59
+
namespace tools.ozone.moderation.defs {
60
+
model RepoViewDetail { }
61
+
model RepoViewNotFound { }
62
+
}
+16
-9
packages/emitter/test/integration/atproto/input/tools/ozone/verification/grantVerifications.tsp
+16
-9
packages/emitter/test/integration/atproto/input/tools/ozone/verification/grantVerifications.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace tools.ozone.verification.grantVerifications {
4
-
@doc("Grant verifications to multiple subjects. Allows batch processing of up to 100 verifications at once.")
4
+
/** Grant verifications to multiple subjects. Allows batch processing of up to 100 verifications at once. */
5
5
@procedure
6
6
op main(input: {
7
-
@doc("Array of verification requests to process")
7
+
/** Array of verification requests to process */
8
8
@maxItems(100)
9
9
@required
10
10
verifications: VerificationInput[];
···
14
14
};
15
15
16
16
model VerificationInput {
17
-
@doc("The did of the subject being verified")
17
+
/** The did of the subject being verified */
18
18
@required
19
19
subject: did;
20
20
21
-
@doc("Handle of the subject the verification applies to at the moment of verifying.")
21
+
/** Handle of the subject the verification applies to at the moment of verifying. */
22
22
@required
23
23
handle: handle;
24
24
25
-
@doc("Display name of the subject the verification applies to at the moment of verifying.")
25
+
/** Display name of the subject the verification applies to at the moment of verifying. */
26
26
@required
27
27
displayName: string;
28
28
29
-
@doc("Timestamp for verification record. Defaults to current time when not specified.")
29
+
/** Timestamp for verification record. Defaults to current time when not specified. */
30
30
createdAt?: datetime;
31
31
}
32
32
33
-
@doc("Error object for failed verifications.")
33
+
/** Error object for failed verifications. */
34
34
model GrantError {
35
-
@doc("Error message describing the reason for failure.")
35
+
/** Error message describing the reason for failure. */
36
36
@required
37
37
error: string;
38
38
39
-
@doc("The did of the subject being verified")
39
+
/** The did of the subject being verified */
40
40
@required
41
41
subject: did;
42
42
}
43
43
}
44
+
45
+
// --- Externals ---
46
+
47
+
@external
48
+
namespace tools.ozone.verification.defs {
49
+
model VerificationView { }
50
+
}
+16
-9
packages/emitter/test/integration/atproto/input/tools/ozone/verification/listVerifications.tsp
+16
-9
packages/emitter/test/integration/atproto/input/tools/ozone/verification/listVerifications.tsp
···
8
8
"desc",
9
9
}
10
10
11
-
@doc("List verifications")
11
+
/** List verifications */
12
12
@query
13
13
op main(
14
-
@doc("Pagination cursor")
14
+
/** Pagination cursor */
15
15
cursor?: string,
16
16
17
-
@doc("Maximum number of results to return")
17
+
/** Maximum number of results to return */
18
18
@minValue(1)
19
19
@maxValue(100)
20
20
limit?: int32 = 50,
21
21
22
-
@doc("Filter to verifications created after this timestamp")
22
+
/** Filter to verifications created after this timestamp */
23
23
createdAfter?: datetime,
24
24
25
-
@doc("Filter to verifications created before this timestamp")
25
+
/** Filter to verifications created before this timestamp */
26
26
createdBefore?: datetime,
27
27
28
-
@doc("Filter to verifications from specific issuers")
28
+
/** Filter to verifications from specific issuers */
29
29
@maxItems(100)
30
30
issuers?: did[],
31
31
32
-
@doc("Filter to specific verified DIDs")
32
+
/** Filter to specific verified DIDs */
33
33
@maxItems(100)
34
34
subjects?: did[],
35
35
36
-
@doc("Sort direction for creation date")
36
+
/** Sort direction for creation date */
37
37
sortDirection?: SortDirection = "desc",
38
38
39
-
@doc("Filter to verifications that are revoked or not. By default, includes both.")
39
+
/** Filter to verifications that are revoked or not. By default, includes both. */
40
40
isRevoked?: boolean
41
41
): {
42
42
cursor?: string;
43
43
@required verifications: tools.ozone.verification.defs.VerificationView[];
44
44
};
45
45
}
46
+
47
+
// --- Externals ---
48
+
49
+
@external
50
+
namespace tools.ozone.verification.defs {
51
+
model VerificationView { }
52
+
}
+8
-8
packages/emitter/test/integration/atproto/input/tools/ozone/verification/revokeVerifications.tsp
+8
-8
packages/emitter/test/integration/atproto/input/tools/ozone/verification/revokeVerifications.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace tools.ozone.verification.revokeVerifications {
4
-
@doc("Revoke previously granted verifications in batches of up to 100.")
4
+
/** Revoke previously granted verifications in batches of up to 100. */
5
5
@procedure
6
6
op main(input: {
7
-
@doc("Array of verification record uris to revoke")
7
+
/** Array of verification record uris to revoke */
8
8
@maxItems(100)
9
9
@required
10
10
uris: atUri[];
11
11
12
-
@doc("Reason for revoking the verification. This is optional and can be omitted if not needed.")
12
+
/** Reason for revoking the verification. This is optional and can be omitted if not needed. */
13
13
@maxLength(1000)
14
14
revokeReason?: string;
15
15
}): {
16
-
@doc("List of verification uris successfully revoked")
16
+
/** List of verification uris successfully revoked */
17
17
@required
18
18
revokedVerifications: atUri[];
19
19
20
-
@doc("List of verification uris that couldn't be revoked, including failure reasons")
20
+
/** List of verification uris that couldn't be revoked, including failure reasons */
21
21
@required
22
22
failedRevocations: RevokeError[];
23
23
};
24
24
25
-
@doc("Error object for failed revocations")
25
+
/** Error object for failed revocations */
26
26
model RevokeError {
27
-
@doc("The AT-URI of the verification record that failed to revoke.")
27
+
/** The AT-URI of the verification record that failed to revoke. */
28
28
@required
29
29
uri: atUri;
30
30
31
-
@doc("Description of the error that occurred during revocation.")
31
+
/** Description of the error that occurred during revocation. */
32
32
@required
33
33
error: string;
34
34
}
+2
-2
packages/emitter/test/integration/atproto/output/app/bsky/richtext/facet.json
+2
-2
packages/emitter/test/integration/atproto/output/app/bsky/richtext/facet.json
···
16
16
},
17
17
"mention": {
18
18
"type": "object",
19
-
"description": "Facet feature for mention of another account. The text is usually a handle, including a '@' prefix, but the facet reference is a DID.",
19
+
"description": "Facet feature for mention of another account. The text is usually a handle, including a `@` prefix, but the facet reference is a DID.",
20
20
"required": ["did"],
21
21
"properties": {
22
22
"did": { "type": "string", "format": "did" }
···
32
32
},
33
33
"tag": {
34
34
"type": "object",
35
-
"description": "Facet feature for a hashtag. The text usually includes a '#' prefix, but the facet reference should not (except in the case of 'double hash tags').",
35
+
"description": "Facet feature for a hashtag. The text usually includes a `#` prefix, but the facet reference should not (except in the case of 'double hash tags').",
36
36
"required": ["tag"],
37
37
"properties": {
38
38
"tag": { "type": "string", "maxLength": 640, "maxGraphemes": 64 }
+4
-4
packages/emitter/test/integration/atproto/output/tools/ozone/moderation/defs.json
+4
-4
packages/emitter/test/integration/atproto/output/tools/ozone/moderation/defs.json
···
319
319
"subjectReviewState": {
320
320
"type": "string",
321
321
"knownValues": [
322
-
"#reviewOpen",
323
-
"#reviewEscalated",
324
-
"#reviewClosed",
325
-
"#reviewNone"
322
+
"tools.ozone.moderation.defs#reviewOpen",
323
+
"tools.ozone.moderation.defs#reviewEscalated",
324
+
"tools.ozone.moderation.defs#reviewClosed",
325
+
"tools.ozone.moderation.defs#reviewNone"
326
326
]
327
327
},
328
328
"reviewOpen": {
+4
-4
packages/emitter/test/integration/atproto/output/tools/ozone/team/defs.json
+4
-4
packages/emitter/test/integration/atproto/output/tools/ozone/team/defs.json
···
18
18
"role": {
19
19
"type": "string",
20
20
"knownValues": [
21
-
"#roleAdmin",
22
-
"#roleModerator",
23
-
"#roleTriage",
24
-
"#roleVerifier"
21
+
"tools.ozone.team.defs#roleAdmin",
22
+
"tools.ozone.team.defs#roleModerator",
23
+
"tools.ozone.team.defs#roleTriage",
24
+
"tools.ozone.team.defs#roleVerifier"
25
25
]
26
26
}
27
27
}
+7
packages/emitter/test/integration/lexicon-examples/input/com/atproto/admin/defs.tsp
+7
packages/emitter/test/integration/lexicon-examples/input/com/atproto/admin/defs.tsp
+1
-1
packages/emitter/test/integration/lexicon-examples/input/com/atproto/admin/deleteAccount.tsp
+1
-1
packages/emitter/test/integration/lexicon-examples/input/com/atproto/admin/deleteAccount.tsp
+2
-2
packages/emitter/test/integration/lexicon-examples/input/com/atproto/admin/disableAccountInvites.tsp
+2
-2
packages/emitter/test/integration/lexicon-examples/input/com/atproto/admin/disableAccountInvites.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace com.atproto.admin.disableAccountInvites {
4
-
@doc("Disable an account from receiving new invite codes, but does not invalidate existing codes.")
4
+
/** Disable an account from receiving new invite codes, but does not invalidate existing codes. */
5
5
@procedure
6
6
op main(input: {
7
7
@required account: did;
8
8
9
-
@doc("Optional reason for disabled invites.")
9
+
/** Optional reason for disabled invites. */
10
10
note?: string;
11
11
}): void;
12
12
}
+1
-1
packages/emitter/test/integration/lexicon-examples/input/com/atproto/admin/disableInviteCodes.tsp
+1
-1
packages/emitter/test/integration/lexicon-examples/input/com/atproto/admin/disableInviteCodes.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace com.atproto.admin.disableInviteCodes {
4
-
@doc("Disable some set of codes and/or all codes associated with a set of users.")
4
+
/** Disable some set of codes and/or all codes associated with a set of users. */
5
5
@procedure
6
6
op main(input: {
7
7
codes?: string[];
+2
-2
packages/emitter/test/integration/lexicon-examples/input/com/atproto/admin/enableAccountInvites.tsp
+2
-2
packages/emitter/test/integration/lexicon-examples/input/com/atproto/admin/enableAccountInvites.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace com.atproto.admin.enableAccountInvites {
4
-
@doc("Re-enable an account's ability to receive invite codes.")
4
+
/** Re-enable an account's ability to receive invite codes. */
5
5
@procedure
6
6
op main(input: {
7
7
@required account: did;
8
8
9
-
@doc("Optional reason for enabled invites.")
9
+
/** Optional reason for enabled invites. */
10
10
note?: string;
11
11
}): void;
12
12
}
+8
-1
packages/emitter/test/integration/lexicon-examples/input/com/atproto/admin/getAccountInfo.tsp
+8
-1
packages/emitter/test/integration/lexicon-examples/input/com/atproto/admin/getAccountInfo.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace com.atproto.admin.getAccountInfo {
4
-
@doc("Get details about an account.")
4
+
/** Get details about an account. */
5
5
@query
6
6
op main(
7
7
@required did: did
8
8
): com.atproto.admin.defs.AccountView;
9
9
}
10
+
11
+
// --- Externals ---
12
+
13
+
@external
14
+
namespace com.atproto.admin.defs {
15
+
model AccountView { }
16
+
}
+8
-1
packages/emitter/test/integration/lexicon-examples/input/com/atproto/admin/getAccountInfos.tsp
+8
-1
packages/emitter/test/integration/lexicon-examples/input/com/atproto/admin/getAccountInfos.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace com.atproto.admin.getAccountInfos {
4
-
@doc("Get details about some accounts.")
4
+
/** Get details about some accounts. */
5
5
@query
6
6
op main(
7
7
@required dids: did[]
···
9
9
@required infos: com.atproto.admin.defs.AccountView[];
10
10
};
11
11
}
12
+
13
+
// --- Externals ---
14
+
15
+
@external
16
+
namespace com.atproto.admin.defs {
17
+
model AccountView { }
18
+
}
+8
-1
packages/emitter/test/integration/lexicon-examples/input/com/atproto/admin/getInviteCodes.tsp
+8
-1
packages/emitter/test/integration/lexicon-examples/input/com/atproto/admin/getInviteCodes.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace com.atproto.admin.getInviteCodes {
4
-
@doc("Get an admin view of invite codes.")
4
+
/** Get an admin view of invite codes. */
5
5
@query
6
6
op main(
7
7
sort?: "recent" | "usage" | string = "recent",
···
16
16
@required codes: com.atproto.server.defs.InviteCode[];
17
17
};
18
18
}
19
+
20
+
// --- Externals ---
21
+
22
+
@external
23
+
namespace com.atproto.server.defs {
24
+
model InviteCode { }
25
+
}
+15
-1
packages/emitter/test/integration/lexicon-examples/input/com/atproto/admin/getSubjectStatus.tsp
+15
-1
packages/emitter/test/integration/lexicon-examples/input/com/atproto/admin/getSubjectStatus.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace com.atproto.admin.getSubjectStatus {
4
-
@doc("Get the service-specific admin status of a subject (account, record, or blob).")
4
+
/** Get the service-specific admin status of a subject (account, record, or blob). */
5
5
@query
6
6
op main(
7
7
did?: did,
···
20
20
deactivated?: com.atproto.admin.defs.StatusAttr;
21
21
};
22
22
}
23
+
24
+
// --- Externals ---
25
+
26
+
@external
27
+
namespace com.atproto.admin.defs {
28
+
model RepoRef { }
29
+
model RepoBlobRef { }
30
+
model StatusAttr { }
31
+
}
32
+
33
+
@external
34
+
namespace com.atproto.repo.strongRef {
35
+
model Main { }
36
+
}
+8
-1
packages/emitter/test/integration/lexicon-examples/input/com/atproto/admin/searchAccounts.tsp
+8
-1
packages/emitter/test/integration/lexicon-examples/input/com/atproto/admin/searchAccounts.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace com.atproto.admin.searchAccounts {
4
-
@doc("Get list of accounts that matches your search query.")
4
+
/** Get list of accounts that matches your search query. */
5
5
@query
6
6
op main(
7
7
email?: string,
···
15
15
@required accounts: com.atproto.admin.defs.AccountView[];
16
16
};
17
17
}
18
+
19
+
// --- Externals ---
20
+
21
+
@external
22
+
namespace com.atproto.admin.defs {
23
+
model AccountView { }
24
+
}
+2
-2
packages/emitter/test/integration/lexicon-examples/input/com/atproto/admin/sendEmail.tsp
+2
-2
packages/emitter/test/integration/lexicon-examples/input/com/atproto/admin/sendEmail.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace com.atproto.admin.sendEmail {
4
-
@doc("Send email to a user's account email address.")
4
+
/** Send email to a user's account email address. */
5
5
@procedure
6
6
op main(input: {
7
7
@required recipientDid: did;
···
9
9
subject?: string;
10
10
@required senderDid: did;
11
11
12
-
@doc("Additional comment by the sender that won't be used in the email itself but helpful to provide more context for moderators/reviewers")
12
+
/** Additional comment by the sender that won't be used in the email itself but helpful to provide more context for moderators/reviewers */
13
13
comment?: string;
14
14
}): {
15
15
@required sent: boolean;
+2
-2
packages/emitter/test/integration/lexicon-examples/input/com/atproto/admin/updateAccountEmail.tsp
+2
-2
packages/emitter/test/integration/lexicon-examples/input/com/atproto/admin/updateAccountEmail.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace com.atproto.admin.updateAccountEmail {
4
-
@doc("Administrative action to update an account's email.")
4
+
/** Administrative action to update an account's email. */
5
5
@procedure
6
6
op main(input: {
7
-
@doc("The handle or DID of the repo.")
7
+
/** The handle or DID of the repo. */
8
8
@required
9
9
account: atIdentifier;
10
10
+1
-1
packages/emitter/test/integration/lexicon-examples/input/com/atproto/admin/updateAccountHandle.tsp
+1
-1
packages/emitter/test/integration/lexicon-examples/input/com/atproto/admin/updateAccountHandle.tsp
+1
-1
packages/emitter/test/integration/lexicon-examples/input/com/atproto/admin/updateAccountPassword.tsp
+1
-1
packages/emitter/test/integration/lexicon-examples/input/com/atproto/admin/updateAccountPassword.tsp
+2
-2
packages/emitter/test/integration/lexicon-examples/input/com/atproto/admin/updateAccountSigningKey.tsp
+2
-2
packages/emitter/test/integration/lexicon-examples/input/com/atproto/admin/updateAccountSigningKey.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace com.atproto.admin.updateAccountSigningKey {
4
-
@doc("Administrative action to update an account's signing key in their Did document.")
4
+
/** Administrative action to update an account's signing key in their Did document. */
5
5
@procedure
6
6
op main(input: {
7
7
@required did: did;
8
8
9
-
@doc("Did-key formatted public key")
9
+
/** Did-key formatted public key */
10
10
@required
11
11
signingKey: did;
12
12
}): void;
+15
-1
packages/emitter/test/integration/lexicon-examples/input/com/atproto/admin/updateSubjectStatus.tsp
+15
-1
packages/emitter/test/integration/lexicon-examples/input/com/atproto/admin/updateSubjectStatus.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace com.atproto.admin.updateSubjectStatus {
4
-
@doc("Update the service-specific admin status of a subject (account, record, or blob).")
4
+
/** Update the service-specific admin status of a subject (account, record, or blob). */
5
5
@procedure
6
6
op main(input: {
7
7
@required
···
26
26
takedown?: com.atproto.admin.defs.StatusAttr;
27
27
};
28
28
}
29
+
30
+
// --- Externals ---
31
+
32
+
@external
33
+
namespace com.atproto.admin.defs {
34
+
model RepoRef { }
35
+
model RepoBlobRef { }
36
+
model StatusAttr { }
37
+
}
38
+
39
+
@external
40
+
namespace com.atproto.repo.strongRef {
41
+
model Main { }
42
+
}
+2
-2
packages/emitter/test/integration/lexicon-examples/input/com/atproto/identity/defs.tsp
+2
-2
packages/emitter/test/integration/lexicon-examples/input/com/atproto/identity/defs.tsp
···
4
4
model IdentityInfo {
5
5
@required did: did;
6
6
7
-
@doc("The validated handle of the account; or 'handle.invalid' if the handle did not bi-directionally match the DID document.")
7
+
/** The validated handle of the account; or 'handle.invalid' if the handle did not bi-directionally match the DID document. */
8
8
@required
9
9
handle: handle;
10
10
11
-
@doc("The complete DID document for the identity.")
11
+
/** The complete DID document for the identity. */
12
12
@required
13
13
didDoc: unknown;
14
14
}
+2
-2
packages/emitter/test/integration/lexicon-examples/input/com/atproto/identity/getRecommendedDidCredentials.tsp
+2
-2
packages/emitter/test/integration/lexicon-examples/input/com/atproto/identity/getRecommendedDidCredentials.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace com.atproto.identity.getRecommendedDidCredentials {
4
-
@doc("Describe the credentials that should be included in the DID doc of an account that is migrating to this service.")
4
+
/** Describe the credentials that should be included in the DID doc of an account that is migrating to this service. */
5
5
@query
6
6
op main(): {
7
-
@doc("Recommended rotation keys for PLC dids. Should be undefined (or ignored) for did:webs.")
7
+
/** Recommended rotation keys for PLC dids. Should be undefined (or ignored) for did:webs. */
8
8
rotationKeys?: string[];
9
9
10
10
alsoKnownAs?: string[];
+11
-4
packages/emitter/test/integration/lexicon-examples/input/com/atproto/identity/refreshIdentity.tsp
+11
-4
packages/emitter/test/integration/lexicon-examples/input/com/atproto/identity/refreshIdentity.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace com.atproto.identity.refreshIdentity {
4
-
@doc("The resolution process confirmed that the handle does not resolve to any DID.")
4
+
/** The resolution process confirmed that the handle does not resolve to any DID. */
5
5
model HandleNotFound {}
6
6
7
-
@doc("The DID resolution process confirmed that there is no current DID.")
7
+
/** The DID resolution process confirmed that there is no current DID. */
8
8
model DidNotFound {}
9
9
10
-
@doc("The DID previously existed, but has been deactivated.")
10
+
/** The DID previously existed, but has been deactivated. */
11
11
model DidDeactivated {}
12
12
13
-
@doc("Request that the server re-resolve an identity (DID and handle). The server may ignore this request, or require authentication, depending on the role, implementation, and policy of the server.")
13
+
/** Request that the server re-resolve an identity (DID and handle). The server may ignore this request, or require authentication, depending on the role, implementation, and policy of the server. */
14
14
@procedure
15
15
@errors(HandleNotFound, DidNotFound, DidDeactivated)
16
16
op main(input: {
17
17
@required identifier: atIdentifier;
18
18
}): com.atproto.identity.defs.IdentityInfo;
19
19
}
20
+
21
+
// --- Externals ---
22
+
23
+
@external
24
+
namespace com.atproto.identity.defs {
25
+
model IdentityInfo { }
26
+
}
+1
-1
packages/emitter/test/integration/lexicon-examples/input/com/atproto/identity/requestPlcOperationSignature.tsp
+1
-1
packages/emitter/test/integration/lexicon-examples/input/com/atproto/identity/requestPlcOperationSignature.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace com.atproto.identity.requestPlcOperationSignature {
4
-
@doc("Request an email with a code to in order to request a signed PLC operation. Requires Auth.")
4
+
/** Request an email with a code to in order to request a signed PLC operation. Requires Auth. */
5
5
@procedure
6
6
op main(): void;
7
7
}
+5
-5
packages/emitter/test/integration/lexicon-examples/input/com/atproto/identity/resolveDid.tsp
+5
-5
packages/emitter/test/integration/lexicon-examples/input/com/atproto/identity/resolveDid.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace com.atproto.identity.resolveDid {
4
-
@doc("Resolves DID to DID document. Does not bi-directionally verify handle.")
4
+
/** Resolves DID to DID document. Does not bi-directionally verify handle. */
5
5
@query
6
6
@errors(DidNotFound, DidDeactivated)
7
7
op main(
8
-
@doc("DID to resolve.")
8
+
/** DID to resolve. */
9
9
@required
10
10
did: did
11
11
): {
12
-
@doc("The complete DID document for the identity.")
12
+
/** The complete DID document for the identity. */
13
13
@required
14
14
didDoc: unknown;
15
15
};
16
16
17
-
@doc("The DID resolution process confirmed that there is no current DID.")
17
+
/** The DID resolution process confirmed that there is no current DID. */
18
18
model DidNotFound {}
19
19
20
-
@doc("The DID previously existed, but has been deactivated.")
20
+
/** The DID previously existed, but has been deactivated. */
21
21
model DidDeactivated {}
22
22
}
+3
-3
packages/emitter/test/integration/lexicon-examples/input/com/atproto/identity/resolveHandle.tsp
+3
-3
packages/emitter/test/integration/lexicon-examples/input/com/atproto/identity/resolveHandle.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace com.atproto.identity.resolveHandle {
4
-
@doc("Resolves an atproto handle (hostname) to a DID. Does not necessarily bi-directionally verify against the the DID document.")
4
+
/** Resolves an atproto handle (hostname) to a DID. Does not necessarily bi-directionally verify against the the DID document. */
5
5
@query
6
6
@errors(HandleNotFound)
7
7
op main(
8
-
@doc("The handle to resolve.")
8
+
/** The handle to resolve. */
9
9
@required
10
10
handle: handle
11
11
): {
12
12
@required did: did;
13
13
};
14
14
15
-
@doc("The resolution process confirmed that the handle does not resolve to any DID.")
15
+
/** The resolution process confirmed that the handle does not resolve to any DID. */
16
16
model HandleNotFound {}
17
17
}
+12
-5
packages/emitter/test/integration/lexicon-examples/input/com/atproto/identity/resolveIdentity.tsp
+12
-5
packages/emitter/test/integration/lexicon-examples/input/com/atproto/identity/resolveIdentity.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace com.atproto.identity.resolveIdentity {
4
-
@doc("The resolution process confirmed that the handle does not resolve to any DID.")
4
+
/** The resolution process confirmed that the handle does not resolve to any DID. */
5
5
model HandleNotFound {}
6
6
7
-
@doc("The DID resolution process confirmed that there is no current DID.")
7
+
/** The DID resolution process confirmed that there is no current DID. */
8
8
model DidNotFound {}
9
9
10
-
@doc("The DID previously existed, but has been deactivated.")
10
+
/** The DID previously existed, but has been deactivated. */
11
11
model DidDeactivated {}
12
12
13
-
@doc("Resolves an identity (DID or Handle) to a full identity (DID document and verified handle).")
13
+
/** Resolves an identity (DID or Handle) to a full identity (DID document and verified handle). */
14
14
@query
15
15
@errors(HandleNotFound, DidNotFound, DidDeactivated)
16
16
op main(
17
-
@doc("Handle or DID to resolve.")
17
+
/** Handle or DID to resolve. */
18
18
@required
19
19
identifier: atIdentifier
20
20
): com.atproto.identity.defs.IdentityInfo;
21
21
}
22
+
23
+
// --- Externals ---
24
+
25
+
@external
26
+
namespace com.atproto.identity.defs {
27
+
model IdentityInfo { }
28
+
}
+3
-3
packages/emitter/test/integration/lexicon-examples/input/com/atproto/identity/signPlcOperation.tsp
+3
-3
packages/emitter/test/integration/lexicon-examples/input/com/atproto/identity/signPlcOperation.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace com.atproto.identity.signPlcOperation {
4
-
@doc("Signs a PLC operation to update some value(s) in the requesting DID's document.")
4
+
/** Signs a PLC operation to update some value(s) in the requesting DID's document. */
5
5
@procedure
6
6
op main(input: {
7
-
@doc("A token received through com.atproto.identity.requestPlcOperationSignature")
7
+
/** A token received through com.atproto.identity.requestPlcOperationSignature */
8
8
token?: string;
9
9
10
10
rotationKeys?: string[];
···
15
15
16
16
services?: unknown;
17
17
}): {
18
-
@doc("A signed DID PLC operation.")
18
+
/** A signed DID PLC operation. */
19
19
@required
20
20
operation: unknown;
21
21
};
+1
-1
packages/emitter/test/integration/lexicon-examples/input/com/atproto/identity/submitPlcOperation.tsp
+1
-1
packages/emitter/test/integration/lexicon-examples/input/com/atproto/identity/submitPlcOperation.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace com.atproto.identity.submitPlcOperation {
4
-
@doc("Validates a PLC operation to ensure that it doesn't violate a service's constraints or get the identity into a bad state, then submits it to the PLC registry")
4
+
/** Validates a PLC operation to ensure that it doesn't violate a service's constraints or get the identity into a bad state, then submits it to the PLC registry */
5
5
@procedure
6
6
op main(input: {
7
7
@required operation: unknown;
+2
-2
packages/emitter/test/integration/lexicon-examples/input/com/atproto/identity/updateHandle.tsp
+2
-2
packages/emitter/test/integration/lexicon-examples/input/com/atproto/identity/updateHandle.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace com.atproto.identity.updateHandle {
4
-
@doc("Updates the current account's handle. Verifies handle validity, and updates did:plc document if necessary. Implemented by PDS, and requires auth.")
4
+
/** Updates the current account's handle. Verifies handle validity, and updates did:plc document if necessary. Implemented by PDS, and requires auth. */
5
5
@procedure
6
6
op main(input: {
7
-
@doc("The new handle.")
7
+
/** The new handle. */
8
8
@required
9
9
handle: handle;
10
10
}): void;
+23
-23
packages/emitter/test/integration/lexicon-examples/input/com/atproto/label/defs.tsp
+23
-23
packages/emitter/test/integration/lexicon-examples/input/com/atproto/label/defs.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace com.atproto.label.defs {
4
-
@doc("Metadata tag on an atproto resource (eg, repo or record).")
4
+
/** Metadata tag on an atproto resource (eg, repo or record). */
5
5
model Label {
6
-
@doc("The AT Protocol version of the label object.")
6
+
/** The AT Protocol version of the label object. */
7
7
ver?: integer;
8
8
9
-
@doc("DID of the actor who created this label.")
9
+
/** DID of the actor who created this label. */
10
10
@required
11
11
src: did;
12
12
13
-
@doc("AT URI of the record, repository (account), or other resource that this label applies to.")
13
+
/** AT URI of the record, repository (account), or other resource that this label applies to. */
14
14
@required
15
15
uri: uri;
16
16
17
-
@doc("Optionally, CID specifying the specific version of 'uri' resource this label applies to.")
17
+
/** Optionally, CID specifying the specific version of 'uri' resource this label applies to. */
18
18
cid?: cid;
19
19
20
-
@doc("The short string name of the value or type of this label.")
20
+
/** The short string name of the value or type of this label. */
21
21
@maxLength(128)
22
22
@required
23
23
val: string;
24
24
25
-
@doc("If true, this is a negation label, overwriting a previous label.")
25
+
/** If true, this is a negation label, overwriting a previous label. */
26
26
neg?: boolean;
27
27
28
-
@doc("Timestamp when this label was created.")
28
+
/** Timestamp when this label was created. */
29
29
@required
30
30
cts: datetime;
31
31
32
-
@doc("Timestamp at which this label expires (no longer applies).")
32
+
/** Timestamp at which this label expires (no longer applies). */
33
33
exp?: datetime;
34
34
35
-
@doc("Signature of dag-cbor encoded label.")
35
+
/** Signature of dag-cbor encoded label. */
36
36
sig?: bytes;
37
37
}
38
38
39
-
@doc("Metadata tags on an atproto record, published by the author within the record.")
39
+
/** Metadata tags on an atproto record, published by the author within the record. */
40
40
model SelfLabels {
41
41
@maxItems(10)
42
42
@required
43
43
values: SelfLabel[];
44
44
}
45
45
46
-
@doc("Metadata tag on an atproto record, published by the author within the record. Note that schemas should use #selfLabels, not #selfLabel.")
46
+
/** Metadata tag on an atproto record, published by the author within the record. Note that schemas should use #selfLabels, not #selfLabel. */
47
47
model SelfLabel {
48
-
@doc("The short string name of the value or type of this label.")
48
+
/** The short string name of the value or type of this label. */
49
49
@maxLength(128)
50
50
@required
51
51
val: string;
52
52
}
53
53
54
-
@doc("Declares a label value and its expected interpretations and behaviors.")
54
+
/** Declares a label value and its expected interpretations and behaviors. */
55
55
model LabelValueDefinition {
56
-
@doc("The value of the label being defined. Must only include lowercase ascii and the '-' character ([a-z-]+).")
56
+
/** The value of the label being defined. Must only include lowercase ascii and the '-' character ([a-z-]+). */
57
57
@maxLength(100)
58
58
@maxGraphemes(100)
59
59
@required
60
60
identifier: string;
61
61
62
-
@doc("How should a client visually convey this label? 'inform' means neutral and informational; 'alert' means negative and warning; 'none' means show nothing.")
62
+
/** How should a client visually convey this label? 'inform' means neutral and informational; 'alert' means negative and warning; 'none' means show nothing. */
63
63
@required
64
64
severity: "inform" | "alert" | "none" | string;
65
65
66
-
@doc("What should this label hide in the UI, if applied? 'content' hides all of the target; 'media' hides the images/video/audio; 'none' hides nothing.")
66
+
/** What should this label hide in the UI, if applied? 'content' hides all of the target; 'media' hides the images/video/audio; 'none' hides nothing. */
67
67
@required
68
68
blurs: "content" | "media" | "none" | string;
69
69
70
-
@doc("The default setting for this label.")
70
+
/** The default setting for this label. */
71
71
defaultSetting?: "ignore" | "warn" | "hide" | string = "warn";
72
72
73
-
@doc("Does the user need to have adult content enabled in order to configure this label?")
73
+
/** Does the user need to have adult content enabled in order to configure this label? */
74
74
adultOnly?: boolean;
75
75
76
76
@required
77
77
locales: LabelValueDefinitionStrings[];
78
78
}
79
79
80
-
@doc("Strings which describe the label in the UI, localized into a specific language.")
80
+
/** Strings which describe the label in the UI, localized into a specific language. */
81
81
model LabelValueDefinitionStrings {
82
-
@doc("The code of the language these strings are written in.")
82
+
/** The code of the language these strings are written in. */
83
83
@required
84
84
lang: language;
85
85
86
-
@doc("A short human-readable name for the label.")
86
+
/** A short human-readable name for the label. */
87
87
@maxGraphemes(64)
88
88
@maxLength(640)
89
89
@required
90
90
name: string;
91
91
92
-
@doc("A longer description of what the label means and why it might be applied.")
92
+
/** A longer description of what the label means and why it might be applied. */
93
93
@maxGraphemes(10000)
94
94
@maxLength(100000)
95
95
@required
+10
-3
packages/emitter/test/integration/lexicon-examples/input/com/atproto/label/queryLabels.tsp
+10
-3
packages/emitter/test/integration/lexicon-examples/input/com/atproto/label/queryLabels.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace com.atproto.label.queryLabels {
4
-
@doc("Find labels relevant to the provided AT-URI patterns. Public endpoint for moderation services, though may return different or additional results with auth.")
4
+
/** Find labels relevant to the provided AT-URI patterns. Public endpoint for moderation services, though may return different or additional results with auth. */
5
5
@query
6
6
op main(
7
-
@doc("List of AT URI patterns to match (boolean 'OR'). Each may be a prefix (ending with '*'; will match inclusive of the string leading to '*'), or a full URI.")
7
+
/** List of AT URI patterns to match (boolean 'OR'). Each may be a prefix (ending with '*'; will match inclusive of the string leading to '*'), or a full URI. */
8
8
@required
9
9
uriPatterns: string[],
10
10
11
-
@doc("Optional list of label sources (DIDs) to filter on.")
11
+
/** Optional list of label sources (DIDs) to filter on. */
12
12
sources?: did[],
13
13
14
14
@minValue(1)
···
21
21
@required labels: com.atproto.label.defs.Label[];
22
22
};
23
23
}
24
+
25
+
// --- Externals ---
26
+
27
+
@external
28
+
namespace com.atproto.label.defs {
29
+
model Label { }
30
+
}
+9
-2
packages/emitter/test/integration/lexicon-examples/input/com/atproto/label/subscribeLabels.tsp
+9
-2
packages/emitter/test/integration/lexicon-examples/input/com/atproto/label/subscribeLabels.tsp
···
13
13
message?: string;
14
14
}
15
15
16
-
@doc("Subscribe to stream of labels (and negations). Public endpoint implemented by mod services. Uses same sequencing scheme as repo event stream.")
16
+
/** Subscribe to stream of labels (and negations). Public endpoint implemented by mod services. Uses same sequencing scheme as repo event stream. */
17
17
@subscription
18
18
@errors(FutureCursor)
19
19
op main(
20
-
@doc("The last known event seq number to backfill from.")
20
+
/** The last known event seq number to backfill from. */
21
21
cursor?: integer
22
22
): (Labels | Info);
23
23
}
24
+
25
+
// --- Externals ---
26
+
27
+
@external
28
+
namespace com.atproto.label.defs {
29
+
model Label { }
30
+
}
+2
-2
packages/emitter/test/integration/lexicon-examples/input/com/atproto/lexicon/schema.tsp
+2
-2
packages/emitter/test/integration/lexicon-examples/input/com/atproto/lexicon/schema.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace com.atproto.lexicon.schema {
4
-
@doc("Representation of Lexicon schemas themselves, when published as atproto records. Note that the schema language is not defined in Lexicon; this meta schema currently only includes a single version field ('lexicon'). See the atproto specifications for description of the other expected top-level fields ('id', 'defs', etc).")
4
+
/** Representation of Lexicon schemas themselves, when published as atproto records. Note that the schema language is not defined in Lexicon; this meta schema currently only includes a single version field ('lexicon'). See the atproto specifications for description of the other expected top-level fields ('id', 'defs', etc). */
5
5
@rec("nsid")
6
6
model Main {
7
-
@doc("Indicates the 'version' of the Lexicon language. Must be '1' for the current atproto/Lexicon schema system.")
7
+
/** Indicates the 'version' of the Lexicon language. Must be '1' for the current atproto/Lexicon schema system. */
8
8
@required
9
9
lexicon: integer;
10
10
}
+23
-6
packages/emitter/test/integration/lexicon-examples/input/com/atproto/moderation/createReport.tsp
+23
-6
packages/emitter/test/integration/lexicon-examples/input/com/atproto/moderation/createReport.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace com.atproto.moderation.createReport {
4
-
@doc("Submit a moderation report regarding an atproto account or record. Implemented by moderation services (with PDS proxying), and requires auth.")
4
+
/** Submit a moderation report regarding an atproto account or record. Implemented by moderation services (with PDS proxying), and requires auth. */
5
5
@procedure
6
6
op main(input: {
7
-
@doc("Indicates the broad category of violation the report is for.")
7
+
/** Indicates the broad category of violation the report is for. */
8
8
@required
9
9
reasonType: com.atproto.moderation.defs.ReasonType;
10
10
11
11
@maxGraphemes(2000)
12
12
@maxLength(20000)
13
-
@doc("Additional context about the content and violation.")
13
+
/** Additional context about the content and violation. */
14
14
reason?: string;
15
15
16
16
@required
···
40
40
@required createdAt: datetime;
41
41
};
42
42
43
-
@doc("Moderation tool information for tracing the source of the action")
43
+
/** Moderation tool information for tracing the source of the action */
44
44
model ModTool {
45
-
@doc("Name/identifier of the source (e.g., 'bsky-app/android', 'bsky-web/chrome')")
45
+
/** Name/identifier of the source (e.g., 'bsky-app/android', 'bsky-web/chrome') */
46
46
@required
47
47
name: string;
48
48
49
-
@doc("Additional arbitrary metadata about the source")
49
+
/** Additional arbitrary metadata about the source */
50
50
meta?: unknown;
51
51
}
52
52
}
53
+
54
+
// --- Externals ---
55
+
56
+
@external
57
+
namespace com.atproto.moderation.defs {
58
+
model ReasonType { }
59
+
}
60
+
61
+
@external
62
+
namespace com.atproto.admin.defs {
63
+
model RepoRef { }
64
+
}
65
+
66
+
@external
67
+
namespace com.atproto.repo.strongRef {
68
+
model Main { }
69
+
}
+59
-8
packages/emitter/test/integration/lexicon-examples/input/com/atproto/moderation/defs.tsp
+59
-8
packages/emitter/test/integration/lexicon-examples/input/com/atproto/moderation/defs.tsp
···
66
66
ToolsOzoneReportReasonCivicImpersonation: "tools.ozone.report.defs#reasonCivicImpersonation",
67
67
}
68
68
69
-
@doc("Spam: frequent unwanted promotion, replies, mentions. Prefer new lexicon definition `tools.ozone.report.defs#reasonMisleadingSpam`.")
69
+
/** Spam: frequent unwanted promotion, replies, mentions. Prefer new lexicon definition `tools.ozone.report.defs#reasonMisleadingSpam`. */
70
70
@token
71
71
model ReasonSpam {}
72
72
73
-
@doc("Direct violation of server rules, laws, terms of service. Prefer new lexicon definition `tools.ozone.report.defs#reasonRuleOther`.")
73
+
/** Direct violation of server rules, laws, terms of service. Prefer new lexicon definition `tools.ozone.report.defs#reasonRuleOther`. */
74
74
@token
75
75
model ReasonViolation {}
76
76
77
-
@doc("Misleading identity, affiliation, or content. Prefer new lexicon definition `tools.ozone.report.defs#reasonMisleadingOther`.")
77
+
/** Misleading identity, affiliation, or content. Prefer new lexicon definition `tools.ozone.report.defs#reasonMisleadingOther`. */
78
78
@token
79
79
model ReasonMisleading {}
80
80
81
-
@doc("Unwanted or mislabeled sexual content. Prefer new lexicon definition `tools.ozone.report.defs#reasonSexualUnlabeled`.")
81
+
/** Unwanted or mislabeled sexual content. Prefer new lexicon definition `tools.ozone.report.defs#reasonSexualUnlabeled`. */
82
82
@token
83
83
model ReasonSexual {}
84
84
85
-
@doc("Rude, harassing, explicit, or otherwise unwelcoming behavior. Prefer new lexicon definition `tools.ozone.report.defs#reasonHarassmentOther`.")
85
+
/** Rude, harassing, explicit, or otherwise unwelcoming behavior. Prefer new lexicon definition `tools.ozone.report.defs#reasonHarassmentOther`. */
86
86
@token
87
87
model ReasonRude {}
88
88
89
-
@doc("Reports not falling under another report category. Prefer new lexicon definition `tools.ozone.report.defs#reasonRuleOther`.")
89
+
/** Reports not falling under another report category. Prefer new lexicon definition `tools.ozone.report.defs#reasonRuleOther`. */
90
90
@token
91
91
model ReasonOther {}
92
92
93
-
@doc("Appeal a previously taken moderation action")
93
+
/** Appeal a previously taken moderation action */
94
94
@token
95
95
model ReasonAppeal {}
96
96
97
-
@doc("Tag describing a type of subject that might be reported.")
97
+
/** Tag describing a type of subject that might be reported. */
98
98
union SubjectType {
99
99
"account",
100
100
"record",
···
102
102
string,
103
103
}
104
104
}
105
+
106
+
// --- Externals ---
107
+
108
+
@external
109
+
namespace tools.ozone.report.defs {
110
+
@token model ReasonAppeal { }
111
+
@token model ReasonViolenceAnimalWelfare { }
112
+
@token model ReasonViolenceThreats { }
113
+
@token model ReasonViolenceGraphicContent { }
114
+
@token model ReasonViolenceSelfHarm { }
115
+
@token model ReasonViolenceGlorification { }
116
+
@token model ReasonViolenceExtremistContent { }
117
+
@token model ReasonViolenceTrafficking { }
118
+
@token model ReasonViolenceOther { }
119
+
@token model ReasonSexualAbuseContent { }
120
+
@token model ReasonSexualNCII { }
121
+
@token model ReasonSexualSextortion { }
122
+
@token model ReasonSexualDeepfake { }
123
+
@token model ReasonSexualAnimal { }
124
+
@token model ReasonSexualUnlabeled { }
125
+
@token model ReasonSexualOther { }
126
+
@token model ReasonChildSafetyCSAM { }
127
+
@token model ReasonChildSafetyGroom { }
128
+
@token model ReasonChildSafetyMinorPrivacy { }
129
+
@token model ReasonChildSafetyEndangerment { }
130
+
@token model ReasonChildSafetyHarassment { }
131
+
@token model ReasonChildSafetyPromotion { }
132
+
@token model ReasonChildSafetyOther { }
133
+
@token model ReasonHarassmentTroll { }
134
+
@token model ReasonHarassmentTargeted { }
135
+
@token model ReasonHarassmentHateSpeech { }
136
+
@token model ReasonHarassmentDoxxing { }
137
+
@token model ReasonHarassmentOther { }
138
+
@token model ReasonMisleadingBot { }
139
+
@token model ReasonMisleadingImpersonation { }
140
+
@token model ReasonMisleadingSpam { }
141
+
@token model ReasonMisleadingScam { }
142
+
@token model ReasonMisleadingSyntheticContent { }
143
+
@token model ReasonMisleadingMisinformation { }
144
+
@token model ReasonMisleadingOther { }
145
+
@token model ReasonRuleSiteSecurity { }
146
+
@token model ReasonRuleStolenContent { }
147
+
@token model ReasonRuleProhibitedSales { }
148
+
@token model ReasonRuleBanEvasion { }
149
+
@token model ReasonRuleOther { }
150
+
@token model ReasonCivicElectoralProcess { }
151
+
@token model ReasonCivicDisclosure { }
152
+
@token model ReasonCivicInterference { }
153
+
@token model ReasonCivicMisinformation { }
154
+
@token model ReasonCivicImpersonation { }
155
+
}
+16
-9
packages/emitter/test/integration/lexicon-examples/input/com/atproto/repo/applyWrites.tsp
+16
-9
packages/emitter/test/integration/lexicon-examples/input/com/atproto/repo/applyWrites.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace com.atproto.repo.applyWrites {
4
-
@doc("Indicates that the 'swapCommit' parameter did not match current commit.")
4
+
/** Indicates that the 'swapCommit' parameter did not match current commit. */
5
5
model InvalidSwap {}
6
6
7
7
@closed
···
20
20
DeleteResult,
21
21
}
22
22
23
-
@doc("Apply a batch transaction of repository creates, updates, and deletes. Requires auth, implemented by PDS.")
23
+
/** Apply a batch transaction of repository creates, updates, and deletes. Requires auth, implemented by PDS. */
24
24
@procedure
25
25
@errors(InvalidSwap)
26
26
op main(input: {
27
-
@doc("The handle or DID of the repo (aka, current account).")
27
+
/** The handle or DID of the repo (aka, current account). */
28
28
@required
29
29
repo: atIdentifier;
30
30
31
-
@doc("Can be set to 'false' to skip Lexicon schema validation of record data across all operations, 'true' to require it, or leave unset to validate only for known Lexicons.")
31
+
/** Can be set to 'false' to skip Lexicon schema validation of record data across all operations, 'true' to require it, or leave unset to validate only for known Lexicons. */
32
32
validate?: boolean;
33
33
34
34
@required
35
35
writes: WriteAction[];
36
36
37
-
@doc("If provided, the entire operation will fail if the current repo commit CID does not match this value. Used to prevent conflicting repo mutations.")
37
+
/** If provided, the entire operation will fail if the current repo commit CID does not match this value. Used to prevent conflicting repo mutations. */
38
38
swapCommit?: cid;
39
39
}): {
40
40
commit?: com.atproto.repo.defs.CommitMeta;
41
41
results?: WriteResult[];
42
42
};
43
43
44
-
@doc("Operation which creates a new record.")
44
+
/** Operation which creates a new record. */
45
45
model Create {
46
46
@required collection: nsid;
47
47
48
-
@doc("NOTE: maxLength is redundant with record-key format. Keeping it temporarily to ensure backwards compatibility.")
48
+
/** NOTE: maxLength is redundant with record-key format. Keeping it temporarily to ensure backwards compatibility. */
49
49
@maxLength(512)
50
50
rkey?: recordKey;
51
51
52
52
@required value: unknown;
53
53
}
54
54
55
-
@doc("Operation which updates an existing record.")
55
+
/** Operation which updates an existing record. */
56
56
model Update {
57
57
@required collection: nsid;
58
58
@required rkey: recordKey;
59
59
@required value: unknown;
60
60
}
61
61
62
-
@doc("Operation which deletes an existing record.")
62
+
/** Operation which deletes an existing record. */
63
63
model Delete {
64
64
@required collection: nsid;
65
65
@required rkey: recordKey;
···
79
79
80
80
model DeleteResult {}
81
81
}
82
+
83
+
// --- Externals ---
84
+
85
+
@external
86
+
namespace com.atproto.repo.defs {
87
+
model CommitMeta { }
88
+
}
+15
-8
packages/emitter/test/integration/lexicon-examples/input/com/atproto/repo/createRecord.tsp
+15
-8
packages/emitter/test/integration/lexicon-examples/input/com/atproto/repo/createRecord.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace com.atproto.repo.createRecord {
4
-
@doc("Create a single new repository record. Requires auth, implemented by PDS.")
4
+
/** Create a single new repository record. Requires auth, implemented by PDS. */
5
5
@errors(InvalidSwap)
6
6
@procedure
7
7
op main(input: {
8
-
@doc("The handle or DID of the repo (aka, current account).")
8
+
/** The handle or DID of the repo (aka, current account). */
9
9
@required
10
10
repo: atIdentifier;
11
11
12
-
@doc("The NSID of the record collection.")
12
+
/** The NSID of the record collection. */
13
13
@required
14
14
collection: nsid;
15
15
16
-
@doc("The Record Key.")
16
+
/** The Record Key. */
17
17
@maxLength(512)
18
18
rkey?: recordKey;
19
19
20
-
@doc("Can be set to 'false' to skip Lexicon schema validation of record data, 'true' to require it, or leave unset to validate only for known Lexicons.")
20
+
/** Can be set to 'false' to skip Lexicon schema validation of record data, 'true' to require it, or leave unset to validate only for known Lexicons. */
21
21
validate?: boolean;
22
22
23
-
@doc("The record itself. Must contain a $type field.")
23
+
/** The record itself. Must contain a $type field. */
24
24
@required
25
25
record: unknown;
26
26
27
-
@doc("Compare and swap with the previous commit by CID.")
27
+
/** Compare and swap with the previous commit by CID. */
28
28
swapCommit?: cid;
29
29
}): {
30
30
@required uri: atUri;
···
33
33
validationStatus?: "valid" | "unknown" | string;
34
34
};
35
35
36
-
@doc("Indicates that 'swapCommit' didn't match current repo commit.")
36
+
/** Indicates that 'swapCommit' didn't match current repo commit. */
37
37
model InvalidSwap {}
38
38
}
39
+
40
+
// --- Externals ---
41
+
42
+
@external
43
+
namespace com.atproto.repo.defs {
44
+
model CommitMeta { }
45
+
}
+13
-6
packages/emitter/test/integration/lexicon-examples/input/com/atproto/repo/deleteRecord.tsp
+13
-6
packages/emitter/test/integration/lexicon-examples/input/com/atproto/repo/deleteRecord.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace com.atproto.repo.deleteRecord {
4
-
@doc("Delete a repository record, or ensure it doesn't exist. Requires auth, implemented by PDS.")
4
+
/** Delete a repository record, or ensure it doesn't exist. Requires auth, implemented by PDS. */
5
5
@errors(InvalidSwap)
6
6
@procedure
7
7
op main(input: {
8
-
@doc("The handle or DID of the repo (aka, current account).")
8
+
/** The handle or DID of the repo (aka, current account). */
9
9
@required
10
10
repo: atIdentifier;
11
11
12
-
@doc("The NSID of the record collection.")
12
+
/** The NSID of the record collection. */
13
13
@required
14
14
collection: nsid;
15
15
16
-
@doc("The Record Key.")
16
+
/** The Record Key. */
17
17
@required
18
18
rkey: recordKey;
19
19
20
-
@doc("Compare and swap with the previous record by CID.")
20
+
/** Compare and swap with the previous record by CID. */
21
21
swapRecord?: cid;
22
22
23
-
@doc("Compare and swap with the previous commit by CID.")
23
+
/** Compare and swap with the previous commit by CID. */
24
24
swapCommit?: cid;
25
25
}): {
26
26
commit?: com.atproto.repo.defs.CommitMeta;
···
28
28
29
29
model InvalidSwap {}
30
30
}
31
+
32
+
// --- Externals ---
33
+
34
+
@external
35
+
namespace com.atproto.repo.defs {
36
+
model CommitMeta { }
37
+
}
+5
-5
packages/emitter/test/integration/lexicon-examples/input/com/atproto/repo/describeRepo.tsp
+5
-5
packages/emitter/test/integration/lexicon-examples/input/com/atproto/repo/describeRepo.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace com.atproto.repo.describeRepo {
4
-
@doc("Get information about an account and repository, including the list of collections. Does not require auth.")
4
+
/** Get information about an account and repository, including the list of collections. Does not require auth. */
5
5
@query
6
6
op main(
7
-
@doc("The handle or DID of the repo.")
7
+
/** The handle or DID of the repo. */
8
8
@required
9
9
repo: atIdentifier
10
10
): {
11
11
@required handle: handle;
12
12
@required did: did;
13
13
14
-
@doc("The complete DID document for this account.")
14
+
/** The complete DID document for this account. */
15
15
@required
16
16
didDoc: unknown;
17
17
18
-
@doc("List of all the collections (NSIDs) for which this repo contains at least one record.")
18
+
/** List of all the collections (NSIDs) for which this repo contains at least one record. */
19
19
@required
20
20
collections: nsid[];
21
21
22
-
@doc("Indicates if handle is currently valid (resolves bi-directionally)")
22
+
/** Indicates if handle is currently valid (resolves bi-directionally) */
23
23
@required
24
24
handleIsCorrect: boolean;
25
25
};
+5
-5
packages/emitter/test/integration/lexicon-examples/input/com/atproto/repo/getRecord.tsp
+5
-5
packages/emitter/test/integration/lexicon-examples/input/com/atproto/repo/getRecord.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace com.atproto.repo.getRecord {
4
-
@doc("Get a single record from a repository. Does not require auth.")
4
+
/** Get a single record from a repository. Does not require auth. */
5
5
@query
6
6
@errors(RecordNotFound)
7
7
op main(
8
-
@doc("The handle or DID of the repo.")
8
+
/** The handle or DID of the repo. */
9
9
@required
10
10
repo: atIdentifier,
11
11
12
-
@doc("The NSID of the record collection.")
12
+
/** The NSID of the record collection. */
13
13
@required
14
14
collection: nsid,
15
15
16
-
@doc("The Record Key.")
16
+
/** The Record Key. */
17
17
@required
18
18
rkey: recordKey,
19
19
20
-
@doc("The CID of the version of the record. If not specified, then return the most recent version.")
20
+
/** The CID of the version of the record. If not specified, then return the most recent version. */
21
21
cid?: cid
22
22
): {
23
23
@required uri: atUri;
+1
-1
packages/emitter/test/integration/lexicon-examples/input/com/atproto/repo/importRepo.tsp
+1
-1
packages/emitter/test/integration/lexicon-examples/input/com/atproto/repo/importRepo.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace com.atproto.repo.importRepo {
4
-
@doc("Import a repo in the form of a CAR file. Requires Content-Length HTTP header to be set.")
4
+
/** Import a repo in the form of a CAR file. Requires Content-Length HTTP header to be set. */
5
5
@procedure
6
6
op main(
7
7
@encoding("application/vnd.ipld.car")
+1
-1
packages/emitter/test/integration/lexicon-examples/input/com/atproto/repo/listMissingBlobs.tsp
+1
-1
packages/emitter/test/integration/lexicon-examples/input/com/atproto/repo/listMissingBlobs.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace com.atproto.repo.listMissingBlobs {
4
-
@doc("Returns a list of missing blobs for the requesting account. Intended to be used in the account migration flow.")
4
+
/** Returns a list of missing blobs for the requesting account. Intended to be used in the account migration flow. */
5
5
@query
6
6
op main(
7
7
@minValue(1)
+5
-5
packages/emitter/test/integration/lexicon-examples/input/com/atproto/repo/listRecords.tsp
+5
-5
packages/emitter/test/integration/lexicon-examples/input/com/atproto/repo/listRecords.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace com.atproto.repo.listRecords {
4
-
@doc("List a range of records in a repository, matching a specific collection. Does not require auth.")
4
+
/** List a range of records in a repository, matching a specific collection. Does not require auth. */
5
5
@query
6
6
op main(
7
-
@doc("The handle or DID of the repo.")
7
+
/** The handle or DID of the repo. */
8
8
@required
9
9
repo: atIdentifier,
10
10
11
-
@doc("The NSID of the record type.")
11
+
/** The NSID of the record type. */
12
12
@required
13
13
collection: nsid,
14
14
15
-
@doc("The number of records to return.")
15
+
/** The number of records to return. */
16
16
@minValue(1)
17
17
@maxValue(100)
18
18
limit?: int32 = 50,
19
19
20
20
cursor?: string,
21
21
22
-
@doc("Flag to reverse the order of the returned records.")
22
+
/** Flag to reverse the order of the returned records. */
23
23
reverse?: boolean
24
24
): {
25
25
cursor?: string;
+15
-8
packages/emitter/test/integration/lexicon-examples/input/com/atproto/repo/putRecord.tsp
+15
-8
packages/emitter/test/integration/lexicon-examples/input/com/atproto/repo/putRecord.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace com.atproto.repo.putRecord {
4
-
@doc("Write a repository record, creating or updating it as needed. Requires auth, implemented by PDS.")
4
+
/** Write a repository record, creating or updating it as needed. Requires auth, implemented by PDS. */
5
5
@errors(InvalidSwap)
6
6
@procedure
7
7
op main(input: {
8
-
@doc("The handle or DID of the repo (aka, current account).")
8
+
/** The handle or DID of the repo (aka, current account). */
9
9
@required
10
10
repo: atIdentifier;
11
11
12
-
@doc("The NSID of the record collection.")
12
+
/** The NSID of the record collection. */
13
13
@required
14
14
collection: nsid;
15
15
16
-
@doc("The Record Key.")
16
+
/** The Record Key. */
17
17
@maxLength(512)
18
18
@required
19
19
rkey: recordKey;
20
20
21
-
@doc("Can be set to 'false' to skip Lexicon schema validation of record data, 'true' to require it, or leave unset to validate only for known Lexicons.")
21
+
/** Can be set to 'false' to skip Lexicon schema validation of record data, 'true' to require it, or leave unset to validate only for known Lexicons. */
22
22
validate?: boolean;
23
23
24
-
@doc("The record to write.")
24
+
/** The record to write. */
25
25
@required
26
26
record: unknown;
27
27
28
-
@doc("Compare and swap with the previous record by CID. WARNING: nullable and optional field; may cause problems with golang implementation")
28
+
/** Compare and swap with the previous record by CID. WARNING: nullable and optional field; may cause problems with golang implementation */
29
29
swapRecord?: cid | null;
30
30
31
-
@doc("Compare and swap with the previous commit by CID.")
31
+
/** Compare and swap with the previous commit by CID. */
32
32
swapCommit?: cid;
33
33
}): {
34
34
@required uri: atUri;
···
39
39
40
40
model InvalidSwap {}
41
41
}
42
+
43
+
// --- Externals ---
44
+
45
+
@external
46
+
namespace com.atproto.repo.defs {
47
+
model CommitMeta { }
48
+
}
+1
-1
packages/emitter/test/integration/lexicon-examples/input/com/atproto/repo/strongRef.tsp
+1
-1
packages/emitter/test/integration/lexicon-examples/input/com/atproto/repo/strongRef.tsp
+1
-1
packages/emitter/test/integration/lexicon-examples/input/com/atproto/repo/uploadBlob.tsp
+1
-1
packages/emitter/test/integration/lexicon-examples/input/com/atproto/repo/uploadBlob.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace com.atproto.repo.uploadBlob {
4
-
@doc("Upload a new blob, to be referenced from a repository record. The blob will be deleted if it is not referenced within a time window (eg, minutes). Blob restrictions (mimetype, size, etc) are enforced when the reference is created. Requires auth, implemented by PDS.")
4
+
/** Upload a new blob, to be referenced from a repository record. The blob will be deleted if it is not referenced within a time window (eg, minutes). Blob restrictions (mimetype, size, etc) are enforced when the reference is created. Requires auth, implemented by PDS. */
5
5
@procedure
6
6
op main(
7
7
@encoding("*/*")
+1
-1
packages/emitter/test/integration/lexicon-examples/input/com/atproto/server/activateAccount.tsp
+1
-1
packages/emitter/test/integration/lexicon-examples/input/com/atproto/server/activateAccount.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace com.atproto.server.activateAccount {
4
-
@doc("Activates a currently deactivated account. Used to finalize account migration after the account's repo is imported and identity is setup.")
4
+
/** Activates a currently deactivated account. Used to finalize account migration after the account's repo is imported and identity is setup. */
5
5
@procedure
6
6
op main(): void;
7
7
}
+1
-1
packages/emitter/test/integration/lexicon-examples/input/com/atproto/server/checkAccountStatus.tsp
+1
-1
packages/emitter/test/integration/lexicon-examples/input/com/atproto/server/checkAccountStatus.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace com.atproto.server.checkAccountStatus {
4
-
@doc("Returns the status of an account, especially as pertaining to import or recovery. Can be called many times over the course of an account migration. Requires auth and can only be called pertaining to oneself.")
4
+
/** Returns the status of an account, especially as pertaining to import or recovery. Can be called many times over the course of an account migration. Requires auth and can only be called pertaining to oneself. */
5
5
@query
6
6
op main(): {
7
7
@required activated: boolean;
+1
-1
packages/emitter/test/integration/lexicon-examples/input/com/atproto/server/confirmEmail.tsp
+1
-1
packages/emitter/test/integration/lexicon-examples/input/com/atproto/server/confirmEmail.tsp
···
6
6
model InvalidToken {}
7
7
model InvalidEmail {}
8
8
9
-
@doc("Confirm an email using a token from com.atproto.server.requestEmailConfirmation.")
9
+
/** Confirm an email using a token from com.atproto.server.requestEmailConfirmation. */
10
10
@procedure
11
11
@errors(AccountNotFound, ExpiredToken, InvalidToken, InvalidEmail)
12
12
op main(input: {
+9
-9
packages/emitter/test/integration/lexicon-examples/input/com/atproto/server/createAccount.tsp
+9
-9
packages/emitter/test/integration/lexicon-examples/input/com/atproto/server/createAccount.tsp
···
9
9
model UnresolvableDid {}
10
10
model IncompatibleDidDoc {}
11
11
12
-
@doc("Account login session returned on successful account creation.")
12
+
/** Account login session returned on successful account creation. */
13
13
@inline
14
14
model Output {
15
15
@required accessJwt: string;
16
16
@required refreshJwt: string;
17
17
@required handle: handle;
18
18
19
-
@doc("The DID of the new account.")
19
+
/** The DID of the new account. */
20
20
@required
21
21
did: did;
22
22
23
-
@doc("Complete DID document.")
23
+
/** Complete DID document. */
24
24
didDoc?: unknown;
25
25
}
26
26
27
-
@doc("Create an account. Implemented by PDS.")
27
+
/** Create an account. Implemented by PDS. */
28
28
@procedure
29
29
@errors(InvalidHandle, InvalidPassword, InvalidInviteCode, HandleNotAvailable, UnsupportedDomain, UnresolvableDid, IncompatibleDidDoc)
30
30
op main(input: {
31
31
email?: string;
32
32
33
-
@doc("Requested handle for the account.")
33
+
/** Requested handle for the account. */
34
34
@required
35
35
handle: handle;
36
36
37
-
@doc("Pre-existing atproto DID, being imported to a new account.")
37
+
/** Pre-existing atproto DID, being imported to a new account. */
38
38
did?: did;
39
39
40
40
inviteCode?: string;
41
41
verificationCode?: string;
42
42
verificationPhone?: string;
43
43
44
-
@doc("Initial account password. May need to meet instance-specific password strength requirements.")
44
+
/** Initial account password. May need to meet instance-specific password strength requirements. */
45
45
password?: string;
46
46
47
-
@doc("DID PLC rotation key (aka, recovery key) to be included in PLC creation operation.")
47
+
/** DID PLC rotation key (aka, recovery key) to be included in PLC creation operation. */
48
48
recoveryKey?: string;
49
49
50
-
@doc("A signed DID PLC operation to be submitted as part of importing an existing account to this instance. NOTE: this optional field may be updated when full account migration is implemented.")
50
+
/** A signed DID PLC operation to be submitted as part of importing an existing account to this instance. NOTE: this optional field may be updated when full account migration is implemented. */
51
51
plcOp?: unknown;
52
52
}): Output;
53
53
}
+3
-3
packages/emitter/test/integration/lexicon-examples/input/com/atproto/server/createAppPassword.tsp
+3
-3
packages/emitter/test/integration/lexicon-examples/input/com/atproto/server/createAppPassword.tsp
···
10
10
privileged?: boolean;
11
11
}
12
12
13
-
@doc("Create an App Password.")
13
+
/** Create an App Password. */
14
14
@procedure
15
15
@errors(AccountTakedown)
16
16
op main(input: {
17
-
@doc("A short name for the App Password, to help distinguish them.")
17
+
/** A short name for the App Password, to help distinguish them. */
18
18
@required
19
19
name: string;
20
20
21
-
@doc("If an app password has 'privileged' access to possibly sensitive account state. Meant for use with trusted clients.")
21
+
/** If an app password has 'privileged' access to possibly sensitive account state. Meant for use with trusted clients. */
22
22
privileged?: boolean;
23
23
}): AppPassword;
24
24
}
+1
-1
packages/emitter/test/integration/lexicon-examples/input/com/atproto/server/createInviteCode.tsp
+1
-1
packages/emitter/test/integration/lexicon-examples/input/com/atproto/server/createInviteCode.tsp
+1
-1
packages/emitter/test/integration/lexicon-examples/input/com/atproto/server/createInviteCodes.tsp
+1
-1
packages/emitter/test/integration/lexicon-examples/input/com/atproto/server/createInviteCodes.tsp
+4
-4
packages/emitter/test/integration/lexicon-examples/input/com/atproto/server/createSession.tsp
+4
-4
packages/emitter/test/integration/lexicon-examples/input/com/atproto/server/createSession.tsp
···
5
5
6
6
model AuthFactorTokenRequired {}
7
7
8
-
@doc("Create an authentication session.")
8
+
/** Create an authentication session. */
9
9
@procedure
10
10
@errors(AccountTakedown, AuthFactorTokenRequired)
11
11
op main(input: {
12
-
@doc("Handle or other identifier supported by the server for the authenticating user.")
12
+
/** Handle or other identifier supported by the server for the authenticating user. */
13
13
@required
14
14
identifier: string;
15
15
···
17
17
18
18
authFactorToken?: string;
19
19
20
-
@doc("When true, instead of throwing error for takendown accounts, a valid response with a narrow scoped token will be returned")
20
+
/** When true, instead of throwing error for takendown accounts, a valid response with a narrow scoped token will be returned */
21
21
allowTakendown?: boolean;
22
22
}): {
23
23
@required accessJwt: string;
···
30
30
emailAuthFactor?: boolean;
31
31
active?: boolean;
32
32
33
-
@doc("If active=false, this optional field indicates a possible reason for why the account is not active. If active=false and no status is supplied, then the host makes no claim for why the repository is no longer being hosted.")
33
+
/** If active=false, this optional field indicates a possible reason for why the account is not active. If active=false and no status is supplied, then the host makes no claim for why the repository is no longer being hosted. */
34
34
status?: "takendown" | "suspended" | "deactivated" | string;
35
35
};
36
36
}
+2
-2
packages/emitter/test/integration/lexicon-examples/input/com/atproto/server/deactivateAccount.tsp
+2
-2
packages/emitter/test/integration/lexicon-examples/input/com/atproto/server/deactivateAccount.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace com.atproto.server.deactivateAccount {
4
-
@doc("Deactivates a currently active account. Stops serving of repo, and future writes to repo until reactivated. Used to finalize account migration with the old host after the account has been activated on the new host.")
4
+
/** Deactivates a currently active account. Stops serving of repo, and future writes to repo until reactivated. Used to finalize account migration with the old host after the account has been activated on the new host. */
5
5
@procedure
6
6
op main(input: {
7
-
@doc("A recommendation to server as to how long they should hold onto the deactivated account before deleting.")
7
+
/** A recommendation to server as to how long they should hold onto the deactivated account before deleting. */
8
8
deleteAfter?: datetime;
9
9
}): void;
10
10
}
+1
-1
packages/emitter/test/integration/lexicon-examples/input/com/atproto/server/deleteAccount.tsp
+1
-1
packages/emitter/test/integration/lexicon-examples/input/com/atproto/server/deleteAccount.tsp
···
4
4
model ExpiredToken {}
5
5
model InvalidToken {}
6
6
7
-
@doc("Delete an actor's account with a token and password. Can only be called after requesting a deletion token. Requires auth.")
7
+
/** Delete an actor's account with a token and password. Can only be called after requesting a deletion token. Requires auth. */
8
8
@procedure
9
9
@errors(ExpiredToken, InvalidToken)
10
10
op main(input: {
+1
-1
packages/emitter/test/integration/lexicon-examples/input/com/atproto/server/deleteSession.tsp
+1
-1
packages/emitter/test/integration/lexicon-examples/input/com/atproto/server/deleteSession.tsp
+6
-6
packages/emitter/test/integration/lexicon-examples/input/com/atproto/server/describeServer.tsp
+6
-6
packages/emitter/test/integration/lexicon-examples/input/com/atproto/server/describeServer.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace com.atproto.server.describeServer {
4
-
@doc("Describes the server's account creation requirements and capabilities. Implemented by PDS.")
4
+
/** Describes the server's account creation requirements and capabilities. Implemented by PDS. */
5
5
@query
6
6
op main(): {
7
7
@required did: did;
8
8
9
-
@doc("If true, an invite code must be supplied to create an account on this instance.")
9
+
/** If true, an invite code must be supplied to create an account on this instance. */
10
10
inviteCodeRequired?: boolean;
11
11
12
-
@doc("If true, a phone verification token must be supplied to create an account on this instance.")
12
+
/** If true, a phone verification token must be supplied to create an account on this instance. */
13
13
phoneVerificationRequired?: boolean;
14
14
15
-
@doc("List of domain suffixes that can be used in account handles.")
15
+
/** List of domain suffixes that can be used in account handles. */
16
16
@required
17
17
availableUserDomains: string[];
18
18
19
-
@doc("URLs of service policy documents.")
19
+
/** URLs of service policy documents. */
20
20
links?: Links;
21
21
22
-
@doc("Contact information")
22
+
/** Contact information */
23
23
contact?: Contact;
24
24
};
25
25
+9
-2
packages/emitter/test/integration/lexicon-examples/input/com/atproto/server/getAccountInviteCodes.tsp
+9
-2
packages/emitter/test/integration/lexicon-examples/input/com/atproto/server/getAccountInviteCodes.tsp
···
3
3
namespace com.atproto.server.getAccountInviteCodes {
4
4
model DuplicateCreate {}
5
5
6
-
@doc("Get all invite codes for the current account. Requires auth.")
6
+
/** Get all invite codes for the current account. Requires auth. */
7
7
@query
8
8
@errors(DuplicateCreate)
9
9
op main(
10
10
includeUsed?: boolean = true,
11
11
12
-
@doc("Controls whether any new 'earned' but not 'created' invites should be created.")
12
+
/** Controls whether any new 'earned' but not 'created' invites should be created. */
13
13
createAvailable?: boolean = true
14
14
): {
15
15
@required codes: com.atproto.server.defs.InviteCode[];
16
16
};
17
17
}
18
+
19
+
// --- Externals ---
20
+
21
+
@external
22
+
namespace com.atproto.server.defs {
23
+
model InviteCode { }
24
+
}
+5
-5
packages/emitter/test/integration/lexicon-examples/input/com/atproto/server/getServiceAuth.tsp
+5
-5
packages/emitter/test/integration/lexicon-examples/input/com/atproto/server/getServiceAuth.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace com.atproto.server.getServiceAuth {
4
-
@doc("Indicates that the requested expiration date is not a valid. May be in the past or may be reliant on the requested scopes.")
4
+
/** Indicates that the requested expiration date is not a valid. May be in the past or may be reliant on the requested scopes. */
5
5
model BadExpiration {}
6
6
7
-
@doc("Get a signed token on behalf of the requesting DID for the requested service.")
7
+
/** Get a signed token on behalf of the requesting DID for the requested service. */
8
8
@query
9
9
@errors(BadExpiration)
10
10
op main(
11
-
@doc("The DID of the service that the token will be used to authenticate with")
11
+
/** The DID of the service that the token will be used to authenticate with */
12
12
@required
13
13
aud: did,
14
14
15
-
@doc("The time in Unix Epoch seconds that the JWT expires. Defaults to 60 seconds in the future. The service may enforce certain time bounds on tokens depending on the requested scope.")
15
+
/** The time in Unix Epoch seconds that the JWT expires. Defaults to 60 seconds in the future. The service may enforce certain time bounds on tokens depending on the requested scope. */
16
16
exp?: integer,
17
17
18
-
@doc("Lexicon (XRPC) method to bind the requested token to")
18
+
/** Lexicon (XRPC) method to bind the requested token to */
19
19
lxm?: nsid
20
20
): {
21
21
@required token: string;
+2
-2
packages/emitter/test/integration/lexicon-examples/input/com/atproto/server/getSession.tsp
+2
-2
packages/emitter/test/integration/lexicon-examples/input/com/atproto/server/getSession.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace com.atproto.server.getSession {
4
-
@doc("Get information about the current auth session. Requires auth.")
4
+
/** Get information about the current auth session. Requires auth. */
5
5
@query
6
6
op main(): {
7
7
@required handle: handle;
···
12
12
didDoc?: unknown;
13
13
active?: boolean;
14
14
15
-
@doc("If active=false, this optional field indicates a possible reason for why the account is not active. If active=false and no status is supplied, then the host makes no claim for why the repository is no longer being hosted.")
15
+
/** If active=false, this optional field indicates a possible reason for why the account is not active. If active=false and no status is supplied, then the host makes no claim for why the repository is no longer being hosted. */
16
16
status?: "takendown" | "suspended" | "deactivated" | string;
17
17
};
18
18
}
+1
-1
packages/emitter/test/integration/lexicon-examples/input/com/atproto/server/listAppPasswords.tsp
+1
-1
packages/emitter/test/integration/lexicon-examples/input/com/atproto/server/listAppPasswords.tsp
+2
-2
packages/emitter/test/integration/lexicon-examples/input/com/atproto/server/refreshSession.tsp
+2
-2
packages/emitter/test/integration/lexicon-examples/input/com/atproto/server/refreshSession.tsp
···
3
3
namespace com.atproto.server.refreshSession {
4
4
model AccountTakedown {}
5
5
6
-
@doc("Refresh an authentication session. Requires auth using the 'refreshJwt' (not the 'accessJwt').")
6
+
/** Refresh an authentication session. Requires auth using the 'refreshJwt' (not the 'accessJwt'). */
7
7
@procedure
8
8
@errors(AccountTakedown)
9
9
op main(): {
···
14
14
didDoc?: unknown;
15
15
active?: boolean;
16
16
17
-
@doc("Hosting status of the account. If not specified, then assume 'active'.")
17
+
/** Hosting status of the account. If not specified, then assume 'active'. */
18
18
status?: "takendown" | "suspended" | "deactivated" | string;
19
19
};
20
20
}
+1
-1
packages/emitter/test/integration/lexicon-examples/input/com/atproto/server/requestAccountDelete.tsp
+1
-1
packages/emitter/test/integration/lexicon-examples/input/com/atproto/server/requestAccountDelete.tsp
+1
-1
packages/emitter/test/integration/lexicon-examples/input/com/atproto/server/requestEmailConfirmation.tsp
+1
-1
packages/emitter/test/integration/lexicon-examples/input/com/atproto/server/requestEmailConfirmation.tsp
+1
-1
packages/emitter/test/integration/lexicon-examples/input/com/atproto/server/requestEmailUpdate.tsp
+1
-1
packages/emitter/test/integration/lexicon-examples/input/com/atproto/server/requestEmailUpdate.tsp
+1
-1
packages/emitter/test/integration/lexicon-examples/input/com/atproto/server/requestPasswordReset.tsp
+1
-1
packages/emitter/test/integration/lexicon-examples/input/com/atproto/server/requestPasswordReset.tsp
+3
-3
packages/emitter/test/integration/lexicon-examples/input/com/atproto/server/reserveSigningKey.tsp
+3
-3
packages/emitter/test/integration/lexicon-examples/input/com/atproto/server/reserveSigningKey.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace com.atproto.server.reserveSigningKey {
4
-
@doc("Reserve a repo signing key, for use with account creation. Necessary so that a DID PLC update operation can be constructed during an account migraiton. Public and does not require auth; implemented by PDS. NOTE: this endpoint may change when full account migration is implemented.")
4
+
/** Reserve a repo signing key, for use with account creation. Necessary so that a DID PLC update operation can be constructed during an account migraiton. Public and does not require auth; implemented by PDS. NOTE: this endpoint may change when full account migration is implemented. */
5
5
@procedure
6
6
op main(input: {
7
-
@doc("The DID to reserve a key for.")
7
+
/** The DID to reserve a key for. */
8
8
did?: did;
9
9
}): {
10
-
@doc("The public key for the reserved signing key, in did:key serialization.")
10
+
/** The public key for the reserved signing key, in did:key serialization. */
11
11
@required
12
12
signingKey: string;
13
13
};
+1
-1
packages/emitter/test/integration/lexicon-examples/input/com/atproto/server/resetPassword.tsp
+1
-1
packages/emitter/test/integration/lexicon-examples/input/com/atproto/server/resetPassword.tsp
+1
-1
packages/emitter/test/integration/lexicon-examples/input/com/atproto/server/revokeAppPassword.tsp
+1
-1
packages/emitter/test/integration/lexicon-examples/input/com/atproto/server/revokeAppPassword.tsp
+2
-2
packages/emitter/test/integration/lexicon-examples/input/com/atproto/server/updateEmail.tsp
+2
-2
packages/emitter/test/integration/lexicon-examples/input/com/atproto/server/updateEmail.tsp
···
5
5
model InvalidToken {}
6
6
model TokenRequired {}
7
7
8
-
@doc("Update an account's email.")
8
+
/** Update an account's email. */
9
9
@procedure
10
10
@errors(ExpiredToken, InvalidToken, TokenRequired)
11
11
op main(input: {
12
12
@required email: string;
13
13
emailAuthFactor?: boolean;
14
14
15
-
@doc("Requires a token from com.atproto.sever.requestEmailUpdate if the account's email has been confirmed.")
15
+
/** Requires a token from com.atproto.sever.requestEmailUpdate if the account's email has been confirmed. */
16
16
token?: string;
17
17
}): void;
18
18
}
+3
-3
packages/emitter/test/integration/lexicon-examples/input/com/atproto/sync/getBlob.tsp
+3
-3
packages/emitter/test/integration/lexicon-examples/input/com/atproto/sync/getBlob.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace com.atproto.sync.getBlob {
4
-
@doc("Get a blob associated with a given account. Returns the full blob as originally uploaded. Does not require auth; implemented by PDS.")
4
+
/** Get a blob associated with a given account. Returns the full blob as originally uploaded. Does not require auth; implemented by PDS. */
5
5
@query
6
6
@encoding("*/*")
7
7
@errors(BlobNotFound, RepoNotFound, RepoTakendown, RepoSuspended, RepoDeactivated)
8
8
op main(
9
-
@doc("The DID of the account.")
9
+
/** The DID of the account. */
10
10
@required
11
11
did: did,
12
12
13
-
@doc("The CID of the blob to fetch")
13
+
/** The CID of the blob to fetch */
14
14
@required
15
15
cid: cid
16
16
): void;
+2
-2
packages/emitter/test/integration/lexicon-examples/input/com/atproto/sync/getBlocks.tsp
+2
-2
packages/emitter/test/integration/lexicon-examples/input/com/atproto/sync/getBlocks.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace com.atproto.sync.getBlocks {
4
-
@doc("Get data blocks from a given repo, by CID. For example, intermediate MST nodes, or records. Does not require auth; implemented by PDS.")
4
+
/** Get data blocks from a given repo, by CID. For example, intermediate MST nodes, or records. Does not require auth; implemented by PDS. */
5
5
@query
6
6
@encoding("application/vnd.ipld.car")
7
7
@errors(BlockNotFound, RepoNotFound, RepoTakendown, RepoSuspended, RepoDeactivated)
8
8
op main(
9
-
@doc("The DID of the repo.")
9
+
/** The DID of the repo. */
10
10
@required
11
11
did: did,
12
12
+2
-2
packages/emitter/test/integration/lexicon-examples/input/com/atproto/sync/getCheckout.tsp
+2
-2
packages/emitter/test/integration/lexicon-examples/input/com/atproto/sync/getCheckout.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace com.atproto.sync.getCheckout {
4
-
@doc("DEPRECATED - please use com.atproto.sync.getRepo instead")
4
+
/** DEPRECATED - please use com.atproto.sync.getRepo instead */
5
5
@query
6
6
@encoding("application/vnd.ipld.car")
7
7
op main(
8
-
@doc("The DID of the repo.")
8
+
/** The DID of the repo. */
9
9
@required
10
10
did: did
11
11
): void;
+2
-2
packages/emitter/test/integration/lexicon-examples/input/com/atproto/sync/getHead.tsp
+2
-2
packages/emitter/test/integration/lexicon-examples/input/com/atproto/sync/getHead.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace com.atproto.sync.getHead {
4
-
@doc("DEPRECATED - please use com.atproto.sync.getLatestCommit instead")
4
+
/** DEPRECATED - please use com.atproto.sync.getLatestCommit instead */
5
5
@query
6
6
@errors(HeadNotFound)
7
7
op main(
8
-
@doc("The DID of the repo.")
8
+
/** The DID of the repo. */
9
9
@required
10
10
did: did
11
11
): {
+11
-4
packages/emitter/test/integration/lexicon-examples/input/com/atproto/sync/getHostStatus.tsp
+11
-4
packages/emitter/test/integration/lexicon-examples/input/com/atproto/sync/getHostStatus.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace com.atproto.sync.getHostStatus {
4
-
@doc("Returns information about a specified upstream host, as consumed by the server. Implemented by relays.")
4
+
/** Returns information about a specified upstream host, as consumed by the server. Implemented by relays. */
5
5
@query
6
6
@errors(HostNotFound)
7
7
op main(
8
-
@doc("Hostname of the host (eg, PDS or relay) being queried.")
8
+
/** Hostname of the host (eg, PDS or relay) being queried. */
9
9
@required
10
10
hostname: string
11
11
): {
12
12
@required hostname: string;
13
13
14
-
@doc("Recent repo stream event sequence number. May be delayed from actual stream processing (eg, persisted cursor not in-memory cursor).")
14
+
/** Recent repo stream event sequence number. May be delayed from actual stream processing (eg, persisted cursor not in-memory cursor). */
15
15
seq?: integer;
16
16
17
-
@doc("Number of accounts on the server which are associated with the upstream host. Note that the upstream may actually have more accounts.")
17
+
/** Number of accounts on the server which are associated with the upstream host. Note that the upstream may actually have more accounts. */
18
18
accountCount?: integer;
19
19
20
20
status?: com.atproto.sync.defs.HostStatus;
···
22
22
23
23
model HostNotFound {}
24
24
}
25
+
26
+
// --- Externals ---
27
+
28
+
@external
29
+
namespace com.atproto.sync.defs {
30
+
model HostStatus { }
31
+
}
+2
-2
packages/emitter/test/integration/lexicon-examples/input/com/atproto/sync/getLatestCommit.tsp
+2
-2
packages/emitter/test/integration/lexicon-examples/input/com/atproto/sync/getLatestCommit.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace com.atproto.sync.getLatestCommit {
4
-
@doc("Get the current commit CID & revision of the specified repo. Does not require auth.")
4
+
/** Get the current commit CID & revision of the specified repo. Does not require auth. */
5
5
@query
6
6
@errors(RepoNotFound, RepoTakendown, RepoSuspended, RepoDeactivated)
7
7
op main(
8
-
@doc("The DID of the repo.")
8
+
/** The DID of the repo. */
9
9
@required
10
10
did: did
11
11
): {
+3
-3
packages/emitter/test/integration/lexicon-examples/input/com/atproto/sync/getRecord.tsp
+3
-3
packages/emitter/test/integration/lexicon-examples/input/com/atproto/sync/getRecord.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace com.atproto.sync.getRecord {
4
-
@doc("Get data blocks needed to prove the existence or non-existence of record in the current version of repo. Does not require auth.")
4
+
/** Get data blocks needed to prove the existence or non-existence of record in the current version of repo. Does not require auth. */
5
5
@query
6
6
@encoding("application/vnd.ipld.car")
7
7
@errors(RecordNotFound, RepoNotFound, RepoTakendown, RepoSuspended, RepoDeactivated)
8
8
op main(
9
-
@doc("The DID of the repo.")
9
+
/** The DID of the repo. */
10
10
@required
11
11
did: did,
12
12
13
13
@required collection: nsid,
14
14
15
-
@doc("Record Key")
15
+
/** Record Key */
16
16
@required
17
17
rkey: recordKey
18
18
): void;
+3
-3
packages/emitter/test/integration/lexicon-examples/input/com/atproto/sync/getRepo.tsp
+3
-3
packages/emitter/test/integration/lexicon-examples/input/com/atproto/sync/getRepo.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace com.atproto.sync.getRepo {
4
-
@doc("Download a repository export as CAR file. Optionally only a 'diff' since a previous revision. Does not require auth; implemented by PDS.")
4
+
/** Download a repository export as CAR file. Optionally only a 'diff' since a previous revision. Does not require auth; implemented by PDS. */
5
5
@query
6
6
@encoding("application/vnd.ipld.car")
7
7
@errors(RepoNotFound, RepoTakendown, RepoSuspended, RepoDeactivated)
8
8
op main(
9
-
@doc("The DID of the repo.")
9
+
/** The DID of the repo. */
10
10
@required
11
11
did: did,
12
12
13
-
@doc("The revision ('rev') of the repo to create a diff from.")
13
+
/** The revision ('rev') of the repo to create a diff from. */
14
14
since?: tid
15
15
): void;
16
16
+4
-4
packages/emitter/test/integration/lexicon-examples/input/com/atproto/sync/getRepoStatus.tsp
+4
-4
packages/emitter/test/integration/lexicon-examples/input/com/atproto/sync/getRepoStatus.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace com.atproto.sync.getRepoStatus {
4
-
@doc("Get the hosting status for a repository, on this server. Expected to be implemented by PDS and Relay.")
4
+
/** Get the hosting status for a repository, on this server. Expected to be implemented by PDS and Relay. */
5
5
@query
6
6
@errors(RepoNotFound)
7
7
op main(
8
-
@doc("The DID of the repo.")
8
+
/** The DID of the repo. */
9
9
@required
10
10
did: did
11
11
): {
12
12
@required did: did;
13
13
@required active: boolean;
14
14
15
-
@doc("If active=false, this optional field indicates a possible reason for why the account is not active. If active=false and no status is supplied, then the host makes no claim for why the repository is no longer being hosted.")
15
+
/** If active=false, this optional field indicates a possible reason for why the account is not active. If active=false and no status is supplied, then the host makes no claim for why the repository is no longer being hosted. */
16
16
status?: "takendown" | "suspended" | "deleted" | "deactivated" | "desynchronized" | "throttled" | string;
17
17
18
-
@doc("Optional field, the current rev of the repo, if active=true")
18
+
/** Optional field, the current rev of the repo, if active=true */
19
19
rev?: tid;
20
20
};
21
21
+3
-3
packages/emitter/test/integration/lexicon-examples/input/com/atproto/sync/listBlobs.tsp
+3
-3
packages/emitter/test/integration/lexicon-examples/input/com/atproto/sync/listBlobs.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace com.atproto.sync.listBlobs {
4
-
@doc("List blob CIDs for an account, since some repo revision. Does not require auth; implemented by PDS.")
4
+
/** List blob CIDs for an account, since some repo revision. Does not require auth; implemented by PDS. */
5
5
@query
6
6
@errors(RepoNotFound, RepoTakendown, RepoSuspended, RepoDeactivated)
7
7
op main(
8
-
@doc("The DID of the repo.")
8
+
/** The DID of the repo. */
9
9
@required
10
10
did: did,
11
11
12
-
@doc("Optional revision of the repo to list blobs since.")
12
+
/** Optional revision of the repo to list blobs since. */
13
13
since?: tid,
14
14
15
15
@minValue(1)
+11
-4
packages/emitter/test/integration/lexicon-examples/input/com/atproto/sync/listHosts.tsp
+11
-4
packages/emitter/test/integration/lexicon-examples/input/com/atproto/sync/listHosts.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace com.atproto.sync.listHosts {
4
-
@doc("Enumerates upstream hosts (eg, PDS or relay instances) that this service consumes from. Implemented by relays.")
4
+
/** Enumerates upstream hosts (eg, PDS or relay instances) that this service consumes from. Implemented by relays. */
5
5
@query
6
6
op main(
7
7
@minValue(1)
···
12
12
): {
13
13
cursor?: string;
14
14
15
-
@doc("Sort order is not formally specified. Recommended order is by time host was first seen by the server, with oldest first.")
15
+
/** Sort order is not formally specified. Recommended order is by time host was first seen by the server, with oldest first. */
16
16
@required
17
17
hosts: Host[];
18
18
};
19
19
20
20
model Host {
21
-
@doc("hostname of server; not a URL (no scheme)")
21
+
/** hostname of server; not a URL (no scheme) */
22
22
@required
23
23
hostname: string;
24
24
25
-
@doc("Recent repo stream event sequence number. May be delayed from actual stream processing (eg, persisted cursor not in-memory cursor).")
25
+
/** Recent repo stream event sequence number. May be delayed from actual stream processing (eg, persisted cursor not in-memory cursor). */
26
26
seq?: integer;
27
27
28
28
accountCount?: integer;
29
29
status?: com.atproto.sync.defs.HostStatus;
30
30
}
31
31
}
32
+
33
+
// --- Externals ---
34
+
35
+
@external
36
+
namespace com.atproto.sync.defs {
37
+
model HostStatus { }
38
+
}
+3
-3
packages/emitter/test/integration/lexicon-examples/input/com/atproto/sync/listRepos.tsp
+3
-3
packages/emitter/test/integration/lexicon-examples/input/com/atproto/sync/listRepos.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace com.atproto.sync.listRepos {
4
-
@doc("Enumerates all the DID, rev, and commit CID for all repos hosted by this service. Does not require auth; implemented by PDS and Relay.")
4
+
/** Enumerates all the DID, rev, and commit CID for all repos hosted by this service. Does not require auth; implemented by PDS and Relay. */
5
5
@query
6
6
op main(
7
7
@minValue(1)
···
17
17
model Repo {
18
18
@required did: did;
19
19
20
-
@doc("Current repo commit CID")
20
+
/** Current repo commit CID */
21
21
@required
22
22
head: cid;
23
23
24
24
@required rev: tid;
25
25
active?: boolean;
26
26
27
-
@doc("If active=false, this optional field indicates a possible reason for why the account is not active. If active=false and no status is supplied, then the host makes no claim for why the repository is no longer being hosted.")
27
+
/** If active=false, this optional field indicates a possible reason for why the account is not active. If active=false and no status is supplied, then the host makes no claim for why the repository is no longer being hosted. */
28
28
status?: "takendown" | "suspended" | "deleted" | "deactivated" | "desynchronized" | "throttled" | string;
29
29
}
30
30
}
+2
-2
packages/emitter/test/integration/lexicon-examples/input/com/atproto/sync/listReposByCollection.tsp
+2
-2
packages/emitter/test/integration/lexicon-examples/input/com/atproto/sync/listReposByCollection.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace com.atproto.sync.listReposByCollection {
4
-
@doc("Enumerates all the DIDs which have records with the given collection NSID.")
4
+
/** Enumerates all the DIDs which have records with the given collection NSID. */
5
5
@query
6
6
op main(
7
7
@required collection: nsid,
8
8
9
-
@doc("Maximum size of response set. Recommend setting a large maximum (1000+) when enumerating large DID lists.")
9
+
/** Maximum size of response set. Recommend setting a large maximum (1000+) when enumerating large DID lists. */
10
10
@minValue(1)
11
11
@maxValue(2000)
12
12
limit?: int32 = 500,
+2
-2
packages/emitter/test/integration/lexicon-examples/input/com/atproto/sync/notifyOfUpdate.tsp
+2
-2
packages/emitter/test/integration/lexicon-examples/input/com/atproto/sync/notifyOfUpdate.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace com.atproto.sync.notifyOfUpdate {
4
-
@doc("Notify a crawling service of a recent update, and that crawling should resume. Intended use is after a gap between repo stream events caused the crawling service to disconnect. Does not require auth; implemented by Relay. DEPRECATED: just use com.atproto.sync.requestCrawl")
4
+
/** Notify a crawling service of a recent update, and that crawling should resume. Intended use is after a gap between repo stream events caused the crawling service to disconnect. Does not require auth; implemented by Relay. DEPRECATED: just use com.atproto.sync.requestCrawl */
5
5
@procedure
6
6
op main(input: {
7
-
@doc("Hostname of the current service (usually a PDS) that is notifying of update.")
7
+
/** Hostname of the current service (usually a PDS) that is notifying of update. */
8
8
@required
9
9
hostname: string;
10
10
}): void;
+2
-2
packages/emitter/test/integration/lexicon-examples/input/com/atproto/sync/requestCrawl.tsp
+2
-2
packages/emitter/test/integration/lexicon-examples/input/com/atproto/sync/requestCrawl.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace com.atproto.sync.requestCrawl {
4
-
@doc("Request a service to persistently crawl hosted repos. Expected use is new PDS instances declaring their existence to Relays. Does not require auth.")
4
+
/** Request a service to persistently crawl hosted repos. Expected use is new PDS instances declaring their existence to Relays. Does not require auth. */
5
5
@procedure
6
6
@errors(HostBanned)
7
7
op main(input: {
8
-
@doc("Hostname of the current service (eg, PDS) that is requesting to be crawled.")
8
+
/** Hostname of the current service (eg, PDS) that is requesting to be crawled. */
9
9
@required
10
10
hostname: string;
11
11
}): void;
+30
-30
packages/emitter/test/integration/lexicon-examples/input/com/atproto/sync/subscribeRepos.tsp
+30
-30
packages/emitter/test/integration/lexicon-examples/input/com/atproto/sync/subscribeRepos.tsp
···
3
3
namespace com.atproto.sync.subscribeRepos {
4
4
@subscription
5
5
@errors(FutureCursor, ConsumerTooSlow)
6
-
@doc("Repository event stream, aka Firehose endpoint. Outputs repo commits with diff data, and identity update events, for all repositories on the current server. See the atproto specifications for details around stream sequencing, repo versioning, CAR diff format, and more. Public and does not require auth; implemented by PDS and Relay.")
6
+
/** Repository event stream, aka Firehose endpoint. Outputs repo commits with diff data, and identity update events, for all repositories on the current server. See the atproto specifications for details around stream sequencing, repo versioning, CAR diff format, and more. Public and does not require auth; implemented by PDS and Relay. */
7
7
op main(
8
-
@doc("The last known event seq number to backfill from.")
8
+
/** The last known event seq number to backfill from. */
9
9
cursor?: integer
10
10
): (Commit | Sync | Identity | Account | Info | unknown);
11
11
12
12
model FutureCursor {}
13
13
14
-
@doc("If the consumer of the stream can not keep up with events, and a backlog gets too large, the server will drop the connection.")
14
+
/** If the consumer of the stream can not keep up with events, and a backlog gets too large, the server will drop the connection. */
15
15
model ConsumerTooSlow {}
16
16
17
-
@doc("Represents an update of repository state. Note that empty commits are allowed, which include no repo data changes, but an update to rev and signature.")
17
+
/** Represents an update of repository state. Note that empty commits are allowed, which include no repo data changes, but an update to rev and signature. */
18
18
model Commit {
19
-
@doc("The stream sequence number of this message.")
19
+
/** The stream sequence number of this message. */
20
20
@required
21
21
seq: integer;
22
22
23
-
@doc("DEPRECATED -- unused")
23
+
/** DEPRECATED -- unused */
24
24
@required
25
25
rebase: boolean;
26
26
27
-
@doc("DEPRECATED -- replaced by #sync event and data limits. Indicates that this commit contained too many ops, or data size was too large. Consumers will need to make a separate request to get missing data.")
27
+
/** DEPRECATED -- replaced by #sync event and data limits. Indicates that this commit contained too many ops, or data size was too large. Consumers will need to make a separate request to get missing data. */
28
28
@required
29
29
tooBig: boolean;
30
30
31
-
@doc("The repo this event comes from. Note that all other message types name this field 'did'.")
31
+
/** The repo this event comes from. Note that all other message types name this field 'did'. */
32
32
@required
33
33
repo: did;
34
34
35
-
@doc("Repo commit object CID.")
35
+
/** Repo commit object CID. */
36
36
@required
37
37
commit: cidLink;
38
38
39
-
@doc("The rev of the emitted commit. Note that this information is also in the commit object included in blocks, unless this is a tooBig event.")
39
+
/** The rev of the emitted commit. Note that this information is also in the commit object included in blocks, unless this is a tooBig event. */
40
40
@required
41
41
rev: tid;
42
42
43
-
@doc("The rev of the last emitted commit from this repo (if any).")
43
+
/** The rev of the last emitted commit from this repo (if any). */
44
44
@required
45
45
since: tid | null;
46
46
47
-
@doc("CAR file containing relevant blocks, as a diff since the previous repo state. The commit must be included as a block, and the commit block CID must be the first entry in the CAR header 'roots' list.")
47
+
/** CAR file containing relevant blocks, as a diff since the previous repo state. The commit must be included as a block, and the commit block CID must be the first entry in the CAR header 'roots' list. */
48
48
@maxBytes(2000000)
49
49
@required
50
50
blocks: bytes;
51
51
52
52
@maxItems(200)
53
53
@required
54
-
@doc("List of repo mutation operations in this commit (eg, records created, updated, or deleted).")
54
+
/** List of repo mutation operations in this commit (eg, records created, updated, or deleted). */
55
55
ops: RepoOp[];
56
56
57
-
@doc("DEPRECATED -- will soon always be empty. List of new blobs (by CID) referenced by records in this commit.")
57
+
/** DEPRECATED -- will soon always be empty. List of new blobs (by CID) referenced by records in this commit. */
58
58
@required blobs: cidLink[];
59
59
60
-
@doc("The root CID of the MST tree for the previous commit from this repo (indicated by the 'since' revision field in this message). Corresponds to the 'data' field in the repo commit object. NOTE: this field is effectively required for the 'inductive' version of firehose.")
60
+
/** The root CID of the MST tree for the previous commit from this repo (indicated by the 'since' revision field in this message). Corresponds to the 'data' field in the repo commit object. NOTE: this field is effectively required for the 'inductive' version of firehose. */
61
61
prevData?: cidLink;
62
62
63
-
@doc("Timestamp of when this message was originally broadcast.")
63
+
/** Timestamp of when this message was originally broadcast. */
64
64
@required
65
65
time: datetime;
66
66
}
67
67
68
-
@doc("Updates the repo to a new state, without necessarily including that state on the firehose. Used to recover from broken commit streams, data loss incidents, or in situations where upstream host does not know recent state of the repository.")
68
+
/** Updates the repo to a new state, without necessarily including that state on the firehose. Used to recover from broken commit streams, data loss incidents, or in situations where upstream host does not know recent state of the repository. */
69
69
model Sync {
70
-
@doc("The stream sequence number of this message.")
70
+
/** The stream sequence number of this message. */
71
71
@required
72
72
seq: integer;
73
73
74
-
@doc("The account this repo event corresponds to. Must match that in the commit object.")
74
+
/** The account this repo event corresponds to. Must match that in the commit object. */
75
75
@required
76
76
did: did;
77
77
78
-
@doc("CAR file containing the commit, as a block. The CAR header must include the commit block CID as the first 'root'.")
78
+
/** CAR file containing the commit, as a block. The CAR header must include the commit block CID as the first 'root'. */
79
79
@maxBytes(10000)
80
80
@required
81
81
blocks: bytes;
82
82
83
-
@doc("The rev of the commit. This value must match that in the commit object.")
83
+
/** The rev of the commit. This value must match that in the commit object. */
84
84
@required
85
85
rev: string;
86
86
87
-
@doc("Timestamp of when this message was originally broadcast.")
87
+
/** Timestamp of when this message was originally broadcast. */
88
88
@required
89
89
time: datetime;
90
90
}
91
91
92
-
@doc("Represents a change to an account's identity. Could be an updated handle, signing key, or pds hosting endpoint. Serves as a prod to all downstream services to refresh their identity cache.")
92
+
/** Represents a change to an account's identity. Could be an updated handle, signing key, or pds hosting endpoint. Serves as a prod to all downstream services to refresh their identity cache. */
93
93
model Identity {
94
94
@required seq: integer;
95
95
@required did: did;
96
96
@required time: datetime;
97
97
98
-
@doc("The current handle for the account, or 'handle.invalid' if validation fails. This field is optional, might have been validated or passed-through from an upstream source. Semantics and behaviors for PDS vs Relay may evolve in the future; see atproto specs for more details.")
98
+
/** The current handle for the account, or 'handle.invalid' if validation fails. This field is optional, might have been validated or passed-through from an upstream source. Semantics and behaviors for PDS vs Relay may evolve in the future; see atproto specs for more details. */
99
99
handle?: handle;
100
100
}
101
101
102
-
@doc("Represents a change to an account's status on a host (eg, PDS or Relay). The semantics of this event are that the status is at the host which emitted the event, not necessarily that at the currently active PDS. Eg, a Relay takedown would emit a takedown with active=false, even if the PDS is still active.")
102
+
/** Represents a change to an account's status on a host (eg, PDS or Relay). The semantics of this event are that the status is at the host which emitted the event, not necessarily that at the currently active PDS. Eg, a Relay takedown would emit a takedown with active=false, even if the PDS is still active. */
103
103
model Account {
104
104
@required seq: integer;
105
105
@required did: did;
106
106
@required time: datetime;
107
107
108
-
@doc("Indicates that the account has a repository which can be fetched from the host that emitted this event.")
108
+
/** Indicates that the account has a repository which can be fetched from the host that emitted this event. */
109
109
@required
110
110
active: boolean;
111
111
112
-
@doc("If active=false, this optional field indicates a reason for why the account is not active.")
112
+
/** If active=false, this optional field indicates a reason for why the account is not active. */
113
113
status?: "takendown" | "suspended" | "deleted" | "deactivated" | "desynchronized" | "throttled" | string;
114
114
}
115
115
···
118
118
message?: string;
119
119
}
120
120
121
-
@doc("A repo operation, ie a mutation of a single record.")
121
+
/** A repo operation, ie a mutation of a single record. */
122
122
model RepoOp {
123
123
@required action: "create" | "update" | "delete" | string;
124
124
@required path: string;
125
125
126
-
@doc("For creates and updates, the new record CID. For deletions, null.")
126
+
/** For creates and updates, the new record CID. For deletions, null. */
127
127
@required
128
128
cid: cidLink | null;
129
129
130
-
@doc("For updates and deletes, the previous record CID (required for inductive firehose). For creations, field should not be defined.")
130
+
/** For updates and deletes, the previous record CID (required for inductive firehose). For creations, field should not be defined. */
131
131
prev?: cidLink;
132
132
}
133
133
}
+1
-1
packages/emitter/test/integration/lexicon-examples/input/com/atproto/temp/addReservedHandle.tsp
+1
-1
packages/emitter/test/integration/lexicon-examples/input/com/atproto/temp/addReservedHandle.tsp
+11
-11
packages/emitter/test/integration/lexicon-examples/input/com/atproto/temp/checkHandleAvailability.tsp
+11
-11
packages/emitter/test/integration/lexicon-examples/input/com/atproto/temp/checkHandleAvailability.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace com.atproto.temp.checkHandleAvailability {
4
-
@doc("An invalid email was provided.")
4
+
/** An invalid email was provided. */
5
5
model InvalidEmail {}
6
6
7
-
@doc("Indicates the provided handle is available.")
7
+
/** Indicates the provided handle is available. */
8
8
model ResultAvailable {}
9
9
10
-
@doc("Indicates the provided handle is unavailable and gives suggestions of available handles.")
10
+
/** Indicates the provided handle is unavailable and gives suggestions of available handles. */
11
11
model ResultUnavailable {
12
-
@doc("List of suggested handles based on the provided inputs.")
12
+
/** List of suggested handles based on the provided inputs. */
13
13
@required
14
14
suggestions: Suggestion[];
15
15
}
···
17
17
model Suggestion {
18
18
@required handle: handle;
19
19
20
-
@doc("Method used to build this suggestion. Should be considered opaque to clients. Can be used for metrics.")
20
+
/** Method used to build this suggestion. Should be considered opaque to clients. Can be used for metrics. */
21
21
@required
22
22
method: string;
23
23
}
24
24
25
-
@doc("Checks whether the provided handle is available. If the handle is not available, available suggestions will be returned. Optional inputs will be used to generate suggestions.")
25
+
/** Checks whether the provided handle is available. If the handle is not available, available suggestions will be returned. Optional inputs will be used to generate suggestions. */
26
26
@query
27
27
@errors(InvalidEmail)
28
28
op main(
29
-
@doc("Tentative handle. Will be checked for availability or used to build handle suggestions.")
30
-
handle: handle,
29
+
/** Tentative handle. Will be checked for availability or used to build handle suggestions. */
30
+
@required handle: handle,
31
31
32
-
@doc("User-provided email. Might be used to build handle suggestions.")
32
+
/** User-provided email. Might be used to build handle suggestions. */
33
33
email?: string,
34
34
35
-
@doc("User-provided birth date. Might be used to build handle suggestions.")
35
+
/** User-provided birth date. Might be used to build handle suggestions. */
36
36
birthDate?: datetime
37
37
): {
38
-
@doc("Echo of the input handle.")
38
+
/** Echo of the input handle. */
39
39
@required
40
40
handle: handle;
41
41
+1
-1
packages/emitter/test/integration/lexicon-examples/input/com/atproto/temp/checkSignupQueue.tsp
+1
-1
packages/emitter/test/integration/lexicon-examples/input/com/atproto/temp/checkSignupQueue.tsp
+5
-5
packages/emitter/test/integration/lexicon-examples/input/com/atproto/temp/dereferenceScope.tsp
+5
-5
packages/emitter/test/integration/lexicon-examples/input/com/atproto/temp/dereferenceScope.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace com.atproto.temp.dereferenceScope {
4
-
@doc("An invalid scope reference was provided.")
4
+
/** An invalid scope reference was provided. */
5
5
model InvalidScopeReference {}
6
6
7
-
@doc("Allows finding the oauth permission scope from a reference")
7
+
/** Allows finding the oauth permission scope from a reference */
8
8
@query
9
9
@errors(InvalidScopeReference)
10
10
op main(
11
-
@doc("The scope reference (starts with 'ref:')")
12
-
scope: string
11
+
/** The scope reference (starts with 'ref:') */
12
+
@required scope: string
13
13
): {
14
-
@doc("The full oauth permission scope")
14
+
/** The full oauth permission scope */
15
15
@required
16
16
scope: string;
17
17
};
+8
-1
packages/emitter/test/integration/lexicon-examples/input/com/atproto/temp/fetchLabels.tsp
+8
-1
packages/emitter/test/integration/lexicon-examples/input/com/atproto/temp/fetchLabels.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace com.atproto.temp.fetchLabels {
4
-
@doc("DEPRECATED: use queryLabels or subscribeLabels instead -- Fetch all labels from a labeler created after a certain date.")
4
+
/** DEPRECATED: use queryLabels or subscribeLabels instead -- Fetch all labels from a labeler created after a certain date. */
5
5
@query
6
6
op main(
7
7
since?: integer,
···
13
13
@required labels: com.atproto.label.defs.Label[];
14
14
};
15
15
}
16
+
17
+
// --- Externals ---
18
+
19
+
@external
20
+
namespace com.atproto.label.defs {
21
+
model Label { }
22
+
}
+1
-1
packages/emitter/test/integration/lexicon-examples/input/com/atproto/temp/requestPhoneVerification.tsp
+1
-1
packages/emitter/test/integration/lexicon-examples/input/com/atproto/temp/requestPhoneVerification.tsp
+1
-1
packages/emitter/test/integration/lexicon-examples/input/com/atproto/temp/revokeAccountCredentials.tsp
+1
-1
packages/emitter/test/integration/lexicon-examples/input/com/atproto/temp/revokeAccountCredentials.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace com.atproto.temp.revokeAccountCredentials {
4
-
@doc("Revoke sessions, password, and app passwords associated with account. May be resolved by a password reset.")
4
+
/** Revoke sessions, password, and app passwords associated with account. May be resolved by a password reset. */
5
5
@procedure
6
6
op main(
7
7
input: {
+7
packages/emitter/test/integration/lexicon-examples/input/pub/leaflet/blocks/blockquote.tsp
+7
packages/emitter/test/integration/lexicon-examples/input/pub/leaflet/blocks/blockquote.tsp
+7
packages/emitter/test/integration/lexicon-examples/input/pub/leaflet/blocks/bskyPost.tsp
+7
packages/emitter/test/integration/lexicon-examples/input/pub/leaflet/blocks/bskyPost.tsp
+7
packages/emitter/test/integration/lexicon-examples/input/pub/leaflet/blocks/header.tsp
+7
packages/emitter/test/integration/lexicon-examples/input/pub/leaflet/blocks/header.tsp
+1
-1
packages/emitter/test/integration/lexicon-examples/input/pub/leaflet/blocks/image.tsp
+1
-1
packages/emitter/test/integration/lexicon-examples/input/pub/leaflet/blocks/image.tsp
+7
packages/emitter/test/integration/lexicon-examples/input/pub/leaflet/blocks/text.tsp
+7
packages/emitter/test/integration/lexicon-examples/input/pub/leaflet/blocks/text.tsp
+17
packages/emitter/test/integration/lexicon-examples/input/pub/leaflet/blocks/unorderedList.tsp
+17
packages/emitter/test/integration/lexicon-examples/input/pub/leaflet/blocks/unorderedList.tsp
···
10
10
children?: ListItem[];
11
11
}
12
12
}
13
+
14
+
// --- Externals ---
15
+
16
+
@external
17
+
namespace `pub`.leaflet.blocks.text {
18
+
model Main { }
19
+
}
20
+
21
+
@external
22
+
namespace `pub`.leaflet.blocks.header {
23
+
model Main { }
24
+
}
25
+
26
+
@external
27
+
namespace `pub`.leaflet.blocks.image {
28
+
model Main { }
29
+
}
+14
-2
packages/emitter/test/integration/lexicon-examples/input/pub/leaflet/comment.tsp
+14
-2
packages/emitter/test/integration/lexicon-examples/input/pub/leaflet/comment.tsp
···
1
1
import "@typelex/emitter";
2
2
3
-
@doc("A lexicon for comments on documents")
3
+
/** A lexicon for comments on documents */
4
4
namespace `pub`.leaflet.comment {
5
-
@doc("Record containing a comment")
5
+
/** Record containing a comment */
6
6
@rec("tid")
7
7
model Main {
8
8
@required subject: atUri;
···
26
26
@required parent: atUri;
27
27
}
28
28
}
29
+
30
+
// --- Externals ---
31
+
32
+
@external
33
+
namespace `pub`.leaflet.richtext.facet {
34
+
model Main { }
35
+
}
36
+
37
+
@external
38
+
namespace `pub`.leaflet.pages.linearDocument {
39
+
model Quote { }
40
+
}
+14
-2
packages/emitter/test/integration/lexicon-examples/input/pub/leaflet/document.tsp
+14
-2
packages/emitter/test/integration/lexicon-examples/input/pub/leaflet/document.tsp
···
1
1
import "@typelex/emitter";
2
2
3
-
@doc("A lexicon for long form rich media documents")
3
+
/** A lexicon for long form rich media documents */
4
4
namespace `pub`.leaflet.document {
5
-
@doc("Record containing a document")
5
+
/** Record containing a document */
6
6
@rec("tid")
7
7
model Main {
8
8
@maxGraphemes(128)
···
23
23
@required pages: (`pub`.leaflet.pages.linearDocument.Main | unknown)[];
24
24
}
25
25
}
26
+
27
+
// --- Externals ---
28
+
29
+
@external
30
+
namespace com.atproto.repo.strongRef {
31
+
model Main { }
32
+
}
33
+
34
+
@external
35
+
namespace `pub`.leaflet.pages.linearDocument {
36
+
model Main { }
37
+
}
+1
-1
packages/emitter/test/integration/lexicon-examples/input/pub/leaflet/graph/subscription.tsp
+1
-1
packages/emitter/test/integration/lexicon-examples/input/pub/leaflet/graph/subscription.tsp
+57
packages/emitter/test/integration/lexicon-examples/input/pub/leaflet/pages/linearDocument.tsp
+57
packages/emitter/test/integration/lexicon-examples/input/pub/leaflet/pages/linearDocument.tsp
···
43
43
@required offset: integer;
44
44
}
45
45
}
46
+
47
+
// --- Externals ---
48
+
49
+
@external
50
+
namespace `pub`.leaflet.blocks.iframe {
51
+
model Main { }
52
+
}
53
+
54
+
@external
55
+
namespace `pub`.leaflet.blocks.text {
56
+
model Main { }
57
+
}
58
+
59
+
@external
60
+
namespace `pub`.leaflet.blocks.blockquote {
61
+
model Main { }
62
+
}
63
+
64
+
@external
65
+
namespace `pub`.leaflet.blocks.header {
66
+
model Main { }
67
+
}
68
+
69
+
@external
70
+
namespace `pub`.leaflet.blocks.image {
71
+
model Main { }
72
+
}
73
+
74
+
@external
75
+
namespace `pub`.leaflet.blocks.unorderedList {
76
+
model Main { }
77
+
}
78
+
79
+
@external
80
+
namespace `pub`.leaflet.blocks.website {
81
+
model Main { }
82
+
}
83
+
84
+
@external
85
+
namespace `pub`.leaflet.blocks.math {
86
+
model Main { }
87
+
}
88
+
89
+
@external
90
+
namespace `pub`.leaflet.blocks.code {
91
+
model Main { }
92
+
}
93
+
94
+
@external
95
+
namespace `pub`.leaflet.blocks.horizontalRule {
96
+
model Main { }
97
+
}
98
+
99
+
@external
100
+
namespace `pub`.leaflet.blocks.bskyPost {
101
+
model Main { }
102
+
}
+14
-1
packages/emitter/test/integration/lexicon-examples/input/pub/leaflet/publication.tsp
+14
-1
packages/emitter/test/integration/lexicon-examples/input/pub/leaflet/publication.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace `pub`.leaflet.publication {
4
-
@doc("Record declaring a publication")
4
+
/** Record declaring a publication */
5
5
@rec("tid")
6
6
model Main {
7
7
@maxLength(2000)
···
34
34
accentText?: (`pub`.leaflet.theme.color.Rgba | `pub`.leaflet.theme.color.Rgb | unknown);
35
35
}
36
36
}
37
+
38
+
// --- Externals ---
39
+
40
+
@external
41
+
namespace `pub`.leaflet.theme.color {
42
+
model Rgba { }
43
+
model Rgb { }
44
+
}
45
+
46
+
@external
47
+
namespace `pub`.leaflet.theme.backgroundImage {
48
+
model Main { }
49
+
}
+10
-10
packages/emitter/test/integration/lexicon-examples/input/pub/leaflet/richtext/facet.tsp
+10
-10
packages/emitter/test/integration/lexicon-examples/input/pub/leaflet/richtext/facet.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace `pub`.leaflet.richtext.facet {
4
-
@doc("Annotation of a sub-string within rich text.")
4
+
/** Annotation of a sub-string within rich text. */
5
5
model Main {
6
6
@required index: ByteSlice;
7
7
@required features: (Link | Code | Highlight | Underline | Strikethrough | Id | Bold | Italic | unknown)[];
8
8
}
9
9
10
-
@doc("Specifies the sub-string range a facet feature applies to. Start index is inclusive, end index is exclusive. Indices are zero-indexed, counting bytes of the UTF-8 encoded text. NOTE: some languages, like Javascript, use UTF-16 or Unicode codepoints for string slice indexing; in these languages, convert to byte arrays before working with facets.")
10
+
/** Specifies the sub-string range a facet feature applies to. Start index is inclusive, end index is exclusive. Indices are zero-indexed, counting bytes of the UTF-8 encoded text. NOTE: some languages, like Javascript, use UTF-16 or Unicode codepoints for string slice indexing; in these languages, convert to byte arrays before working with facets. */
11
11
model ByteSlice {
12
12
@minValue(0)
13
13
@required
···
18
18
byteEnd: integer;
19
19
}
20
20
21
-
@doc("Facet feature for a URL. The text URL may have been simplified or truncated, but the facet reference should be a complete URL.")
21
+
/** Facet feature for a URL. The text URL may have been simplified or truncated, but the facet reference should be a complete URL. */
22
22
model Link {
23
23
@required uri: uri;
24
24
}
25
25
26
-
@doc("Facet feature for inline code.")
26
+
/** Facet feature for inline code. */
27
27
model Code {}
28
28
29
-
@doc("Facet feature for highlighted text.")
29
+
/** Facet feature for highlighted text. */
30
30
model Highlight {}
31
31
32
-
@doc("Facet feature for underline markup")
32
+
/** Facet feature for underline markup */
33
33
model Underline {}
34
34
35
-
@doc("Facet feature for strikethrough markup")
35
+
/** Facet feature for strikethrough markup */
36
36
model Strikethrough {}
37
37
38
-
@doc("Facet feature for an identifier. Used for linking to a segment")
38
+
/** Facet feature for an identifier. Used for linking to a segment */
39
39
model Id {
40
40
id?: string;
41
41
}
42
42
43
-
@doc("Facet feature for bold text")
43
+
/** Facet feature for bold text */
44
44
model Bold {}
45
45
46
-
@doc("Facet feature for italic text")
46
+
/** Facet feature for italic text */
47
47
model Italic {}
48
48
}
+7
-7
packages/emitter/test/integration/lexicon-examples/input/sh/tangled/actor/profile.tsp
+7
-7
packages/emitter/test/integration/lexicon-examples/input/sh/tangled/actor/profile.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace sh.tangled.actor.profile {
4
-
@doc("A declaration of a Tangled account profile.")
4
+
/** A declaration of a Tangled account profile. */
5
5
@rec("literal:self")
6
6
model Main {
7
-
@doc("Free-form profile description text.")
7
+
/** Free-form profile description text. */
8
8
@maxGraphemes(256)
9
9
@maxLength(2560)
10
10
description?: string;
···
17
17
@maxItems(2)
18
18
stats?: StatValue[];
19
19
20
-
@doc("Include link to this account on Bluesky.")
20
+
/** Include link to this account on Bluesky. */
21
21
@required
22
22
bluesky: boolean;
23
23
24
-
@doc("Free-form location text.")
24
+
/** Free-form location text. */
25
25
@maxGraphemes(40)
26
26
@maxLength(400)
27
27
location?: string;
28
28
29
-
@doc("Any ATURI, it is up to appviews to validate these fields.")
29
+
/** Any ATURI, it is up to appviews to validate these fields. */
30
30
@minItems(0)
31
31
@maxItems(6)
32
32
pinnedRepositories?: atUri[];
33
33
}
34
34
35
-
@doc("Any URI, intended for social profiles or websites, can be used to link DIDs/AT-URIs too.")
35
+
/** Any URI, intended for social profiles or websites, can be used to link DIDs/AT-URIs too. */
36
36
@inline
37
37
scalar LinkItem extends uri;
38
38
39
-
@doc("Vanity stats.")
39
+
/** Vanity stats. */
40
40
@closed
41
41
@inline
42
42
union StatValue {
+7
-7
packages/emitter/test/integration/lexicon-examples/input/sh/tangled/git/refUpdate.tsp
+7
-7
packages/emitter/test/integration/lexicon-examples/input/sh/tangled/git/refUpdate.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace sh.tangled.git.refUpdate {
4
-
@doc("An update to a git repository, emitted by knots.")
4
+
/** An update to a git repository, emitted by knots. */
5
5
@rec("tid")
6
6
model Main {
7
-
@doc("Ref being updated")
7
+
/** Ref being updated */
8
8
@maxGraphemes(256)
9
9
@maxLength(2560)
10
10
@required
11
11
ref: string;
12
12
13
-
@doc("did of the user that pushed this ref")
13
+
/** did of the user that pushed this ref */
14
14
@required
15
15
committerDid: did;
16
16
17
-
@doc("did of the owner of the repo")
17
+
/** did of the owner of the repo */
18
18
@required
19
19
repoDid: did;
20
20
21
-
@doc("name of the repo")
21
+
/** name of the repo */
22
22
@required
23
23
repoName: string;
24
24
25
-
@doc("old SHA of this ref")
25
+
/** old SHA of this ref */
26
26
@minLength(40)
27
27
@maxLength(40)
28
28
@required
29
29
oldSha: string;
30
30
31
-
@doc("new SHA of this ref")
31
+
/** new SHA of this ref */
32
32
@minLength(40)
33
33
@maxLength(40)
34
34
@required
+8
-8
packages/emitter/test/integration/lexicon-examples/input/sh/tangled/knot/listKeys.tsp
+8
-8
packages/emitter/test/integration/lexicon-examples/input/sh/tangled/knot/listKeys.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace sh.tangled.knot.listKeys {
4
-
@doc("List all public keys stored in the knot server")
4
+
/** List all public keys stored in the knot server */
5
5
@query
6
6
@errors(InternalServerError)
7
7
op main(
8
-
@doc("Maximum number of keys to return")
8
+
/** Maximum number of keys to return */
9
9
@minValue(1)
10
10
@maxValue(1000)
11
11
limit?: int32 = 100,
12
12
13
-
@doc("Pagination cursor")
13
+
/** Pagination cursor */
14
14
cursor?: string
15
15
): {
16
16
@required keys: PublicKey[];
17
17
18
-
@doc("Pagination cursor for next page")
18
+
/** Pagination cursor for next page */
19
19
cursor?: string;
20
20
};
21
21
22
22
model PublicKey {
23
-
@doc("DID associated with the public key")
23
+
/** DID associated with the public key */
24
24
@required
25
25
did: did;
26
26
27
-
@doc("Public key contents")
27
+
/** Public key contents */
28
28
@maxLength(4096)
29
29
@required
30
30
key: string;
31
31
32
-
@doc("Key upload timestamp")
32
+
/** Key upload timestamp */
33
33
@required
34
34
createdAt: datetime;
35
35
}
36
36
37
-
@doc("Failed to retrieve public keys")
37
+
/** Failed to retrieve public keys */
38
38
model InternalServerError {}
39
39
}
+1
-1
packages/emitter/test/integration/lexicon-examples/input/sh/tangled/knot/member.tsp
+1
-1
packages/emitter/test/integration/lexicon-examples/input/sh/tangled/knot/member.tsp
+1
-1
packages/emitter/test/integration/lexicon-examples/input/sh/tangled/knot/version.tsp
+1
-1
packages/emitter/test/integration/lexicon-examples/input/sh/tangled/knot/version.tsp
+8
-8
packages/emitter/test/integration/lexicon-examples/input/sh/tangled/label/definition.tsp
+8
-8
packages/emitter/test/integration/lexicon-examples/input/sh/tangled/label/definition.tsp
···
3
3
namespace sh.tangled.label.definition {
4
4
@rec("any")
5
5
model Main {
6
-
@doc("The display name of this label.")
6
+
/** The display name of this label. */
7
7
@minGraphemes(1)
8
8
@maxGraphemes(40)
9
9
@required
10
10
name: string;
11
11
12
-
@doc("The type definition of this label. Appviews may allow sorting for certain types.")
12
+
/** The type definition of this label. Appviews may allow sorting for certain types. */
13
13
@required
14
14
valueType: ValueType;
15
15
16
-
@doc("The areas of the repo this label may apply to, eg.: sh.tangled.repo.issue. Appviews may choose to respect this.")
16
+
/** The areas of the repo this label may apply to, eg.: sh.tangled.repo.issue. Appviews may choose to respect this. */
17
17
@required
18
18
scope: nsid[];
19
19
20
-
@doc("The hex value for the background color for the label. Appviews may choose to respect this.")
20
+
/** The hex value for the background color for the label. Appviews may choose to respect this. */
21
21
color?: string;
22
22
23
23
@required createdAt: datetime;
24
24
25
-
@doc("Whether this label can be repeated for a given entity, eg.: [reviewer:foo, reviewer:bar]")
25
+
/** Whether this label can be repeated for a given entity, eg.: [reviewer:foo, reviewer:bar] */
26
26
multiple?: boolean;
27
27
}
28
28
···
44
44
}
45
45
46
46
model ValueType {
47
-
@doc("The concrete type of this label's value.")
47
+
/** The concrete type of this label's value. */
48
48
@required
49
49
type: ConcreteType;
50
50
51
-
@doc("An optional constraint that can be applied on string concrete types.")
51
+
/** An optional constraint that can be applied on string concrete types. */
52
52
@required
53
53
format: FormatType;
54
54
55
-
@doc("Closed set of values that this label can take.")
55
+
/** Closed set of values that this label can take. */
56
56
`enum`?: string[];
57
57
}
58
58
}
+29
packages/emitter/test/integration/lexicon-examples/input/sh/tangled/label/op.tsp
+29
packages/emitter/test/integration/lexicon-examples/input/sh/tangled/label/op.tsp
···
1
+
import "@typelex/emitter";
2
+
3
+
namespace sh.tangled.label.`op` {
4
+
@rec("tid")
5
+
model Main {
6
+
@doc("The subject (task, pull or discussion) of this label. Appviews may apply a `scope` check and refuse this op.")
7
+
@required
8
+
subject: atUri;
9
+
10
+
@required
11
+
add: Operand[];
12
+
13
+
@required
14
+
delete: Operand[];
15
+
16
+
@required
17
+
performedAt: datetime;
18
+
}
19
+
20
+
model Operand {
21
+
@doc("ATURI to the label definition")
22
+
@required
23
+
key: atUri;
24
+
25
+
@doc("Stringified value of the label. This is first unstringed by appviews and then interpreted as a concrete value.")
26
+
@required
27
+
value: string;
28
+
}
29
+
}
-24
packages/emitter/test/integration/lexicon-examples/input/sh/tangled/label.op.tsp
-24
packages/emitter/test/integration/lexicon-examples/input/sh/tangled/label.op.tsp
···
1
-
import "@typelex/emitter";
2
-
3
-
namespace sh.tangled.label.`op` {
4
-
@rec("tid")
5
-
model Main {
6
-
@doc("The subject (task, pull or discussion) of this label. Appviews may apply a `scope` check and refuse this op.")
7
-
@required
8
-
subject: atUri;
9
-
10
-
@required performedAt: datetime;
11
-
@required add: Operand[];
12
-
@required delete: Operand[];
13
-
}
14
-
15
-
model Operand {
16
-
@doc("ATURI to the label definition")
17
-
@required
18
-
key: atUri;
19
-
20
-
@doc("Stringified value of the label. This is first unstringed by appviews and then interpreted as a concrete value.")
21
-
@required
22
-
value: string;
23
-
}
24
-
}
+2
-2
packages/emitter/test/integration/lexicon-examples/input/sh/tangled/owner.tsp
+2
-2
packages/emitter/test/integration/lexicon-examples/input/sh/tangled/owner.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace sh.tangled.owner {
4
-
@doc("Get the owner of a service")
4
+
/** Get the owner of a service */
5
5
@query
6
6
@errors(OwnerNotFound)
7
7
op main(): {
8
8
@required owner: did;
9
9
};
10
10
11
-
@doc("Owner is not set for this service")
11
+
/** Owner is not set for this service */
12
12
model OwnerNotFound {}
13
13
}
+6
-6
packages/emitter/test/integration/lexicon-examples/input/sh/tangled/pipeline/status.tsp
+6
-6
packages/emitter/test/integration/lexicon-examples/input/sh/tangled/pipeline/status.tsp
···
14
14
15
15
@rec("tid")
16
16
model Main {
17
-
@doc("ATURI of the pipeline")
17
+
/** ATURI of the pipeline */
18
18
@required
19
19
pipeline: atUri;
20
20
21
-
@doc("name of the workflow within this pipeline")
21
+
/** name of the workflow within this pipeline */
22
22
@required
23
23
workflow: atUri;
24
24
25
-
@doc("status of the workflow")
25
+
/** status of the workflow */
26
26
@required
27
27
status: WorkflowStatus;
28
28
29
-
@doc("time of creation of this status update")
29
+
/** time of creation of this status update */
30
30
@required
31
31
createdAt: datetime;
32
32
33
-
@doc("error message if failed")
33
+
/** error message if failed */
34
34
error?: string;
35
35
36
-
@doc("exit code if failed")
36
+
/** exit code if failed */
37
37
exitCode?: integer;
38
38
}
39
39
}
+3
-4
packages/emitter/test/integration/lexicon-examples/input/sh/tangled/pipeline.tsp
+3
-4
packages/emitter/test/integration/lexicon-examples/input/sh/tangled/pipeline.tsp
···
18
18
model TriggerMetadata {
19
19
@required kind: TriggerKind;
20
20
@required repo: TriggerRepo;
21
-
22
21
push?: PushTriggerData;
23
22
pullRequest?: PullRequestTriggerData;
24
23
manual?: ManualTriggerData;
···
34
33
model PushTriggerData {
35
34
@required ref: string;
36
35
36
+
@required
37
37
@minLength(40)
38
38
@maxLength(40)
39
-
@required
40
39
newSha: string;
41
40
41
+
@required
42
42
@minLength(40)
43
43
@maxLength(40)
44
-
@required
45
44
oldSha: string;
46
45
}
47
46
···
49
48
@required sourceBranch: string;
50
49
@required targetBranch: string;
51
50
51
+
@required
52
52
@minLength(40)
53
53
@maxLength(40)
54
-
@required
55
54
sourceSha: string;
56
55
57
56
@required action: string;
+3
-3
packages/emitter/test/integration/lexicon-examples/input/sh/tangled/publicKey.tsp
+3
-3
packages/emitter/test/integration/lexicon-examples/input/sh/tangled/publicKey.tsp
···
3
3
namespace sh.tangled.publicKey {
4
4
@rec("tid")
5
5
model Main {
6
-
@doc("public key contents")
6
+
/** public key contents */
7
7
@maxLength(4096)
8
8
@required
9
9
key: string;
10
10
11
-
@doc("human-readable name for this key")
11
+
/** human-readable name for this key */
12
12
@required
13
13
name: string;
14
14
15
-
@doc("key upload timestamp")
15
+
/** key upload timestamp */
16
16
@required
17
17
createdAt: datetime;
18
18
}
+20
packages/emitter/test/integration/lexicon-examples/input/sh/tangled/repo/addSecret.tsp
+20
packages/emitter/test/integration/lexicon-examples/input/sh/tangled/repo/addSecret.tsp
···
1
+
import "@typelex/emitter";
2
+
3
+
namespace sh.tangled.repo.addSecret {
4
+
@procedure
5
+
@doc("Add a CI secret")
6
+
op main(input: {
7
+
@required
8
+
repo: atUri;
9
+
10
+
@required
11
+
@maxLength(50)
12
+
@minLength(1)
13
+
key: string;
14
+
15
+
@required
16
+
@maxLength(200)
17
+
@minLength(1)
18
+
value: string;
19
+
}): void;
20
+
}
+44
packages/emitter/test/integration/lexicon-examples/input/sh/tangled/repo/archive.tsp
+44
packages/emitter/test/integration/lexicon-examples/input/sh/tangled/repo/archive.tsp
···
1
+
import "@typelex/emitter";
2
+
3
+
namespace sh.tangled.repo.archive {
4
+
@query
5
+
@encoding("*/*")
6
+
@errors(RepoNotFound, RefNotFound, InvalidRequest, ArchiveError)
7
+
op main(
8
+
@doc("Repository identifier in format 'did:plc:.../repoName'")
9
+
@required
10
+
repo: string,
11
+
12
+
@doc("Git reference (branch, tag, or commit SHA)")
13
+
@required
14
+
ref: string,
15
+
16
+
@doc("Archive format")
17
+
format?: ArchiveFormat = "tar.gz",
18
+
19
+
@doc("Prefix for files in the archive")
20
+
prefix?: string
21
+
): never;
22
+
23
+
@closed
24
+
@inline
25
+
union ArchiveFormat {
26
+
"tar",
27
+
"zip",
28
+
"tar.gz",
29
+
"tar.bz2",
30
+
"tar.xz"
31
+
}
32
+
33
+
@doc("Repository not found or access denied")
34
+
model RepoNotFound {}
35
+
36
+
@doc("Git reference not found")
37
+
model RefNotFound {}
38
+
39
+
@doc("Invalid request parameters")
40
+
model InvalidRequest {}
41
+
42
+
@doc("Failed to create archive")
43
+
model ArchiveError {}
44
+
}
+28
packages/emitter/test/integration/lexicon-examples/input/sh/tangled/repo/artifact.tsp
+28
packages/emitter/test/integration/lexicon-examples/input/sh/tangled/repo/artifact.tsp
···
1
+
import "@typelex/emitter";
2
+
3
+
namespace sh.tangled.repo.artifact {
4
+
@rec("tid")
5
+
model Main {
6
+
@doc("name of the artifact")
7
+
@required
8
+
name: string;
9
+
10
+
@doc("repo that this artifact is being uploaded to")
11
+
@required
12
+
repo: atUri;
13
+
14
+
@doc("hash of the tag object that this artifact is attached to (only annotated tags are supported)")
15
+
@required
16
+
@minBytes(20)
17
+
@maxBytes(20)
18
+
tag: bytes;
19
+
20
+
@doc("time of creation of this artifact")
21
+
@required
22
+
createdAt: datetime;
23
+
24
+
@doc("the artifact")
25
+
@required
26
+
artifact: Blob<#["*/*"], 52428800>;
27
+
}
28
+
}
+100
packages/emitter/test/integration/lexicon-examples/input/sh/tangled/repo/blob.tsp
+100
packages/emitter/test/integration/lexicon-examples/input/sh/tangled/repo/blob.tsp
···
1
+
import "@typelex/emitter";
2
+
3
+
namespace sh.tangled.repo.blob {
4
+
@query
5
+
@errors(RepoNotFound, RefNotFound, FileNotFound, InvalidRequest)
6
+
op main(
7
+
@doc("Repository identifier in format 'did:plc:.../repoName'")
8
+
@required
9
+
repo: string,
10
+
11
+
@doc("Git reference (branch, tag, or commit SHA)")
12
+
@required
13
+
ref: string,
14
+
15
+
@doc("Path to the file within the repository")
16
+
@required
17
+
path: string,
18
+
19
+
@doc("Return raw file content instead of JSON response")
20
+
raw?: boolean = false
21
+
): {
22
+
@doc("The git reference used")
23
+
@required
24
+
ref: string;
25
+
26
+
@doc("The file path")
27
+
@required
28
+
path: string;
29
+
30
+
@doc("File content (base64 encoded for binary files)")
31
+
@required
32
+
content: string;
33
+
34
+
@doc("Content encoding")
35
+
encoding?: ContentEncoding;
36
+
37
+
@doc("File size in bytes")
38
+
size?: integer;
39
+
40
+
@doc("Whether the file is binary")
41
+
isBinary?: boolean;
42
+
43
+
@doc("MIME type of the file")
44
+
mimeType?: string;
45
+
46
+
lastCommit?: LastCommit;
47
+
};
48
+
49
+
@closed
50
+
@inline
51
+
union ContentEncoding {
52
+
"utf-8",
53
+
"base64"
54
+
}
55
+
56
+
model LastCommit {
57
+
@doc("Commit hash")
58
+
@required
59
+
hash: string;
60
+
61
+
@doc("Short commit hash")
62
+
shortHash?: string;
63
+
64
+
@doc("Commit message")
65
+
@required
66
+
message: string;
67
+
68
+
author?: Signature;
69
+
70
+
@doc("Commit timestamp")
71
+
@required
72
+
when: datetime;
73
+
}
74
+
75
+
model Signature {
76
+
@doc("Author name")
77
+
@required
78
+
name: string;
79
+
80
+
@doc("Author email")
81
+
@required
82
+
email: string;
83
+
84
+
@doc("Author timestamp")
85
+
@required
86
+
when: datetime;
87
+
}
88
+
89
+
@doc("Repository not found or access denied")
90
+
model RepoNotFound {}
91
+
92
+
@doc("Git reference not found")
93
+
model RefNotFound {}
94
+
95
+
@doc("File not found at the specified path")
96
+
model FileNotFound {}
97
+
98
+
@doc("Invalid request parameters")
99
+
model InvalidRequest {}
100
+
}
+61
packages/emitter/test/integration/lexicon-examples/input/sh/tangled/repo/branch.tsp
+61
packages/emitter/test/integration/lexicon-examples/input/sh/tangled/repo/branch.tsp
···
1
+
import "@typelex/emitter";
2
+
3
+
namespace sh.tangled.repo.branch {
4
+
@query
5
+
@errors(RepoNotFound, BranchNotFound, InvalidRequest)
6
+
op main(
7
+
@doc("Repository identifier in format 'did:plc:.../repoName'")
8
+
@required
9
+
repo: string,
10
+
11
+
@doc("Branch name to get information for")
12
+
@required
13
+
name: string
14
+
): {
15
+
@doc("Branch name")
16
+
@required
17
+
name: string;
18
+
19
+
@doc("Latest commit hash on this branch")
20
+
@required
21
+
hash: string;
22
+
23
+
@doc("Short commit hash")
24
+
shortHash?: string;
25
+
26
+
@doc("Timestamp of latest commit")
27
+
@required
28
+
when: datetime;
29
+
30
+
@doc("Latest commit message")
31
+
message?: string;
32
+
33
+
author?: Signature;
34
+
35
+
@doc("Whether this is the default branch")
36
+
isDefault?: boolean;
37
+
};
38
+
39
+
model Signature {
40
+
@doc("Author name")
41
+
@required
42
+
name: string;
43
+
44
+
@doc("Author email")
45
+
@required
46
+
email: string;
47
+
48
+
@doc("Author timestamp")
49
+
@required
50
+
when: datetime;
51
+
}
52
+
53
+
@doc("Repository not found or access denied")
54
+
model RepoNotFound {}
55
+
56
+
@doc("Branch not found")
57
+
model BranchNotFound {}
58
+
59
+
@doc("Invalid request parameters")
60
+
model InvalidRequest {}
61
+
}
+26
packages/emitter/test/integration/lexicon-examples/input/sh/tangled/repo/branches.tsp
+26
packages/emitter/test/integration/lexicon-examples/input/sh/tangled/repo/branches.tsp
···
1
+
import "@typelex/emitter";
2
+
3
+
namespace sh.tangled.repo.branches {
4
+
@query
5
+
@encoding("*/*")
6
+
@errors(RepoNotFound, InvalidRequest)
7
+
op main(
8
+
@doc("Repository identifier in format 'did:plc:.../repoName'")
9
+
@required
10
+
repo: string,
11
+
12
+
@doc("Maximum number of branches to return")
13
+
@minValue(1)
14
+
@maxValue(100)
15
+
limit?: integer = 50,
16
+
17
+
@doc("Pagination cursor")
18
+
cursor?: string
19
+
): never;
20
+
21
+
@doc("Repository not found or access denied")
22
+
model RepoNotFound {}
23
+
24
+
@doc("Invalid request parameters")
25
+
model InvalidRequest {}
26
+
}
+16
packages/emitter/test/integration/lexicon-examples/input/sh/tangled/repo/collaborator.tsp
+16
packages/emitter/test/integration/lexicon-examples/input/sh/tangled/repo/collaborator.tsp
+32
packages/emitter/test/integration/lexicon-examples/input/sh/tangled/repo/compare.tsp
+32
packages/emitter/test/integration/lexicon-examples/input/sh/tangled/repo/compare.tsp
···
1
+
import "@typelex/emitter";
2
+
3
+
namespace sh.tangled.repo.compare {
4
+
@query
5
+
@encoding("*/*")
6
+
@errors(RepoNotFound, RevisionNotFound, InvalidRequest, CompareError)
7
+
op main(
8
+
@doc("Repository identifier in format 'did:plc:.../repoName'")
9
+
@required
10
+
repo: string,
11
+
12
+
@doc("First revision (commit, branch, or tag)")
13
+
@required
14
+
rev1: string,
15
+
16
+
@doc("Second revision (commit, branch, or tag)")
17
+
@required
18
+
rev2: string
19
+
): never;
20
+
21
+
@doc("Repository not found or access denied")
22
+
model RepoNotFound {}
23
+
24
+
@doc("One or both revisions not found")
25
+
model RevisionNotFound {}
26
+
27
+
@doc("Invalid request parameters")
28
+
model InvalidRequest {}
29
+
30
+
@doc("Failed to compare revisions")
31
+
model CompareError {}
32
+
}
+17
packages/emitter/test/integration/lexicon-examples/input/sh/tangled/repo/create.tsp
+17
packages/emitter/test/integration/lexicon-examples/input/sh/tangled/repo/create.tsp
···
1
+
import "@typelex/emitter";
2
+
3
+
namespace sh.tangled.repo.create {
4
+
@procedure
5
+
@doc("Create a new repository")
6
+
op main(input: {
7
+
@doc("Rkey of the repository record")
8
+
@required
9
+
rkey: string;
10
+
11
+
@doc("Default branch to push to")
12
+
defaultBranch?: string;
13
+
14
+
@doc("A source URL to clone from, populate this when forking or importing a repository.")
15
+
source?: string;
16
+
}): void;
17
+
}
+19
packages/emitter/test/integration/lexicon-examples/input/sh/tangled/repo/delete.tsp
+19
packages/emitter/test/integration/lexicon-examples/input/sh/tangled/repo/delete.tsp
···
1
+
import "@typelex/emitter";
2
+
3
+
namespace sh.tangled.repo.delete {
4
+
@procedure
5
+
@doc("Delete a repository")
6
+
op main(input: {
7
+
@doc("DID of the repository owner")
8
+
@required
9
+
did: did;
10
+
11
+
@doc("Name of the repository to delete")
12
+
@required
13
+
name: string;
14
+
15
+
@doc("Rkey of the repository record")
16
+
@required
17
+
rkey: string;
18
+
}): void;
19
+
}
+25
packages/emitter/test/integration/lexicon-examples/input/sh/tangled/repo/diff.tsp
+25
packages/emitter/test/integration/lexicon-examples/input/sh/tangled/repo/diff.tsp
···
1
+
import "@typelex/emitter";
2
+
3
+
namespace sh.tangled.repo.diff {
4
+
@query
5
+
@encoding("*/*")
6
+
@errors(RepoNotFound, RefNotFound, InvalidRequest)
7
+
op main(
8
+
@doc("Repository identifier in format 'did:plc:.../repoName'")
9
+
@required
10
+
repo: string,
11
+
12
+
@doc("Git reference (branch, tag, or commit SHA)")
13
+
@required
14
+
ref: string
15
+
): never;
16
+
17
+
@doc("Repository not found or access denied")
18
+
model RepoNotFound {}
19
+
20
+
@doc("Git reference not found")
21
+
model RefNotFound {}
22
+
23
+
@doc("Invalid request parameters")
24
+
model InvalidRequest {}
25
+
}
+31
packages/emitter/test/integration/lexicon-examples/input/sh/tangled/repo/forkStatus.tsp
+31
packages/emitter/test/integration/lexicon-examples/input/sh/tangled/repo/forkStatus.tsp
···
1
+
import "@typelex/emitter";
2
+
3
+
namespace sh.tangled.repo.forkStatus {
4
+
@procedure
5
+
@doc("Check fork status relative to upstream source")
6
+
op main(input: {
7
+
@doc("DID of the fork owner")
8
+
@required
9
+
did: did;
10
+
11
+
@doc("Name of the forked repository")
12
+
@required
13
+
name: string;
14
+
15
+
@doc("Source repository URL")
16
+
@required
17
+
source: string;
18
+
19
+
@doc("Branch to check status for")
20
+
@required
21
+
branch: string;
22
+
23
+
@doc("Hidden ref to use for comparison")
24
+
@required
25
+
hiddenRef: string;
26
+
}): {
27
+
@doc("Fork status: 0=UpToDate, 1=FastForwardable, 2=Conflict, 3=MissingBranch")
28
+
@required
29
+
status: integer;
30
+
};
31
+
}
+23
packages/emitter/test/integration/lexicon-examples/input/sh/tangled/repo/forkSync.tsp
+23
packages/emitter/test/integration/lexicon-examples/input/sh/tangled/repo/forkSync.tsp
···
1
+
import "@typelex/emitter";
2
+
3
+
namespace sh.tangled.repo.forkSync {
4
+
@procedure
5
+
@doc("Sync a forked repository with its upstream source")
6
+
op main(input: {
7
+
@doc("DID of the fork owner")
8
+
@required
9
+
did: did;
10
+
11
+
@doc("AT-URI of the source repository")
12
+
@required
13
+
source: atUri;
14
+
15
+
@doc("Name of the forked repository")
16
+
@required
17
+
name: string;
18
+
19
+
@doc("Branch to sync")
20
+
@required
21
+
branch: string;
22
+
}): void;
23
+
}
+51
packages/emitter/test/integration/lexicon-examples/input/sh/tangled/repo/getDefaultBranch.tsp
+51
packages/emitter/test/integration/lexicon-examples/input/sh/tangled/repo/getDefaultBranch.tsp
···
1
+
import "@typelex/emitter";
2
+
3
+
namespace sh.tangled.repo.getDefaultBranch {
4
+
@query
5
+
@errors(RepoNotFound, InvalidRequest)
6
+
op main(
7
+
@doc("Repository identifier in format 'did:plc:.../repoName'")
8
+
@required
9
+
repo: string
10
+
): {
11
+
@doc("Default branch name")
12
+
@required
13
+
name: string;
14
+
15
+
@doc("Latest commit hash on default branch")
16
+
@required
17
+
hash: string;
18
+
19
+
@doc("Short commit hash")
20
+
shortHash?: string;
21
+
22
+
@doc("Timestamp of latest commit")
23
+
@required
24
+
when: datetime;
25
+
26
+
@doc("Latest commit message")
27
+
message?: string;
28
+
29
+
author?: Signature;
30
+
};
31
+
32
+
model Signature {
33
+
@doc("Author name")
34
+
@required
35
+
name: string;
36
+
37
+
@doc("Author email")
38
+
@required
39
+
email: string;
40
+
41
+
@doc("Author timestamp")
42
+
@required
43
+
when: datetime;
44
+
}
45
+
46
+
@doc("Repository not found or access denied")
47
+
model RepoNotFound {}
48
+
49
+
@doc("Invalid request parameters")
50
+
model InvalidRequest {}
51
+
}
-11
packages/emitter/test/integration/lexicon-examples/input/sh/tangled/repo/issue/issue.tsp
-11
packages/emitter/test/integration/lexicon-examples/input/sh/tangled/repo/issue/issue.tsp
+1
-1
packages/emitter/test/integration/lexicon-examples/input/sh/tangled/repo/issue/state/closed.tsp
+1
-1
packages/emitter/test/integration/lexicon-examples/input/sh/tangled/repo/issue/state/closed.tsp
+1
-1
packages/emitter/test/integration/lexicon-examples/input/sh/tangled/repo/issue/state/open.tsp
+1
-1
packages/emitter/test/integration/lexicon-examples/input/sh/tangled/repo/issue/state/open.tsp
+13
-1
packages/emitter/test/integration/lexicon-examples/input/sh/tangled/repo/issue/state.tsp
+13
-1
packages/emitter/test/integration/lexicon-examples/input/sh/tangled/repo/issue/state.tsp
···
5
5
model Main {
6
6
@required issue: atUri;
7
7
8
-
@doc("state of the issue")
8
+
/** state of the issue */
9
9
@required
10
10
state: "sh.tangled.repo.issue.state.open" | "sh.tangled.repo.issue.state.closed" | string = "sh.tangled.repo.issue.state.open";
11
11
}
12
12
}
13
+
14
+
// --- Externals ---
15
+
16
+
@external
17
+
namespace sh.tangled.repo.issue.state.open {
18
+
@token model Main { }
19
+
}
20
+
21
+
@external
22
+
namespace sh.tangled.repo.issue.state.closed {
23
+
@token model Main { }
24
+
}
+11
packages/emitter/test/integration/lexicon-examples/input/sh/tangled/repo/issue.tsp
+11
packages/emitter/test/integration/lexicon-examples/input/sh/tangled/repo/issue.tsp
+59
packages/emitter/test/integration/lexicon-examples/input/sh/tangled/repo/languages.tsp
+59
packages/emitter/test/integration/lexicon-examples/input/sh/tangled/repo/languages.tsp
···
1
+
import "@typelex/emitter";
2
+
3
+
namespace sh.tangled.repo.languages {
4
+
@query
5
+
@errors(RepoNotFound, RefNotFound, InvalidRequest)
6
+
op main(
7
+
@doc("Repository identifier in format 'did:plc:.../repoName'")
8
+
@required
9
+
repo: string,
10
+
11
+
@doc("Git reference (branch, tag, or commit SHA)")
12
+
ref?: string = "HEAD"
13
+
): {
14
+
@doc("The git reference used")
15
+
@required
16
+
ref: string;
17
+
18
+
@required
19
+
languages: Language[];
20
+
21
+
@doc("Total size of all analyzed files in bytes")
22
+
totalSize?: integer;
23
+
24
+
@doc("Total number of files analyzed")
25
+
totalFiles?: integer;
26
+
};
27
+
28
+
model Language {
29
+
@doc("Programming language name")
30
+
@required
31
+
name: string;
32
+
33
+
@doc("Total size of files in this language (bytes)")
34
+
@required
35
+
size: integer;
36
+
37
+
@doc("Percentage of total codebase (0-100)")
38
+
@required
39
+
percentage: integer;
40
+
41
+
@doc("Number of files in this language")
42
+
fileCount?: integer;
43
+
44
+
@doc("Hex color code for this language")
45
+
color?: string;
46
+
47
+
@doc("File extensions associated with this language")
48
+
extensions?: string[];
49
+
}
50
+
51
+
@doc("Repository not found or access denied")
52
+
model RepoNotFound {}
53
+
54
+
@doc("Git reference not found")
55
+
model RefNotFound {}
56
+
57
+
@doc("Invalid request parameters")
58
+
model InvalidRequest {}
59
+
}
+28
packages/emitter/test/integration/lexicon-examples/input/sh/tangled/repo/listSecrets.tsp
+28
packages/emitter/test/integration/lexicon-examples/input/sh/tangled/repo/listSecrets.tsp
···
1
+
import "@typelex/emitter";
2
+
3
+
namespace sh.tangled.repo.listSecrets {
4
+
@query
5
+
op main(
6
+
@required
7
+
repo: atUri
8
+
): {
9
+
@required
10
+
secrets: Secret[];
11
+
};
12
+
13
+
model Secret {
14
+
@required
15
+
repo: atUri;
16
+
17
+
@required
18
+
@maxLength(50)
19
+
@minLength(1)
20
+
key: string;
21
+
22
+
@required
23
+
createdAt: datetime;
24
+
25
+
@required
26
+
createdBy: did;
27
+
}
28
+
}
+39
packages/emitter/test/integration/lexicon-examples/input/sh/tangled/repo/log.tsp
+39
packages/emitter/test/integration/lexicon-examples/input/sh/tangled/repo/log.tsp
···
1
+
import "@typelex/emitter";
2
+
3
+
namespace sh.tangled.repo.log {
4
+
@query
5
+
@encoding("*/*")
6
+
@errors(RepoNotFound, RefNotFound, PathNotFound, InvalidRequest)
7
+
op main(
8
+
@doc("Repository identifier in format 'did:plc:.../repoName'")
9
+
@required
10
+
repo: string,
11
+
12
+
@doc("Git reference (branch, tag, or commit SHA)")
13
+
@required
14
+
ref: string,
15
+
16
+
@doc("Path to filter commits by")
17
+
path?: string = "",
18
+
19
+
@doc("Maximum number of commits to return")
20
+
@minValue(1)
21
+
@maxValue(100)
22
+
limit?: integer = 50,
23
+
24
+
@doc("Pagination cursor (commit SHA)")
25
+
cursor?: string
26
+
): never;
27
+
28
+
@doc("Repository not found or access denied")
29
+
model RepoNotFound {}
30
+
31
+
@doc("Git reference not found")
32
+
model RefNotFound {}
33
+
34
+
@doc("Path not found in repository")
35
+
model PathNotFound {}
36
+
37
+
@doc("Invalid request parameters")
38
+
model InvalidRequest {}
39
+
}
+35
packages/emitter/test/integration/lexicon-examples/input/sh/tangled/repo/merge.tsp
+35
packages/emitter/test/integration/lexicon-examples/input/sh/tangled/repo/merge.tsp
···
1
+
import "@typelex/emitter";
2
+
3
+
namespace sh.tangled.repo.merge {
4
+
@procedure
5
+
@doc("Merge a patch into a repository branch")
6
+
op main(input: {
7
+
@doc("DID of the repository owner")
8
+
@required
9
+
did: did;
10
+
11
+
@doc("Name of the repository")
12
+
@required
13
+
name: string;
14
+
15
+
@doc("Patch content to merge")
16
+
@required
17
+
patch: string;
18
+
19
+
@doc("Target branch to merge into")
20
+
@required
21
+
branch: string;
22
+
23
+
@doc("Author name for the merge commit")
24
+
authorName?: string;
25
+
26
+
@doc("Author email for the merge commit")
27
+
authorEmail?: string;
28
+
29
+
@doc("Additional commit message body")
30
+
commitBody?: string;
31
+
32
+
@doc("Merge commit message")
33
+
commitMessage?: string;
34
+
}): void;
35
+
}
+41
packages/emitter/test/integration/lexicon-examples/input/sh/tangled/repo/mergeCheck.tsp
+41
packages/emitter/test/integration/lexicon-examples/input/sh/tangled/repo/mergeCheck.tsp
···
1
+
import "@typelex/emitter";
2
+
3
+
namespace sh.tangled.repo.mergeCheck {
4
+
/** Check if a merge is possible between two branches */
5
+
@procedure
6
+
op main(
7
+
input: {
8
+
/** DID of the repository owner */
9
+
@required did: did,
10
+
11
+
/** Name of the repository */
12
+
@required name: string,
13
+
14
+
/** Patch or pull request to check for merge conflicts */
15
+
@required patch: string,
16
+
17
+
/** Target branch to merge into */
18
+
@required branch: string,
19
+
}
20
+
): {
21
+
/** Whether the merge has conflicts */
22
+
@required is_conflicted: boolean;
23
+
24
+
/** List of files with merge conflicts */
25
+
conflicts?: ConflictInfo[];
26
+
27
+
/** Additional message about the merge check */
28
+
message?: string;
29
+
30
+
/** Error message if check failed */
31
+
error?: string;
32
+
};
33
+
34
+
model ConflictInfo {
35
+
/** Name of the conflicted file */
36
+
@required filename: string;
37
+
38
+
/** Reason for the conflict */
39
+
@required reason: string;
40
+
}
41
+
}
-33
packages/emitter/test/integration/lexicon-examples/input/sh/tangled/repo/pull/pull.tsp
-33
packages/emitter/test/integration/lexicon-examples/input/sh/tangled/repo/pull/pull.tsp
···
1
-
import "@typelex/emitter";
2
-
3
-
namespace sh.tangled.repo.pull {
4
-
@rec("tid")
5
-
model Main {
6
-
@required target: Target;
7
-
@required title: string;
8
-
9
-
body?: string;
10
-
11
-
@required patch: string;
12
-
13
-
source?: Source;
14
-
15
-
@required createdAt: datetime;
16
-
}
17
-
18
-
model Target {
19
-
@required repo: atUri;
20
-
@required branch: string;
21
-
}
22
-
23
-
model Source {
24
-
@required branch: string;
25
-
26
-
@minLength(40)
27
-
@maxLength(40)
28
-
@required
29
-
sha: string;
30
-
31
-
repo?: atUri;
32
-
}
33
-
}
+1
-1
packages/emitter/test/integration/lexicon-examples/input/sh/tangled/repo/pull/status/closed.tsp
+1
-1
packages/emitter/test/integration/lexicon-examples/input/sh/tangled/repo/pull/status/closed.tsp
+1
-1
packages/emitter/test/integration/lexicon-examples/input/sh/tangled/repo/pull/status/merged.tsp
+1
-1
packages/emitter/test/integration/lexicon-examples/input/sh/tangled/repo/pull/status/merged.tsp
+1
-1
packages/emitter/test/integration/lexicon-examples/input/sh/tangled/repo/pull/status/open.tsp
+1
-1
packages/emitter/test/integration/lexicon-examples/input/sh/tangled/repo/pull/status/open.tsp
+18
-1
packages/emitter/test/integration/lexicon-examples/input/sh/tangled/repo/pull/status.tsp
+18
-1
packages/emitter/test/integration/lexicon-examples/input/sh/tangled/repo/pull/status.tsp
···
5
5
model Main {
6
6
@required pull: atUri;
7
7
8
-
@doc("status of the pull request")
8
+
/** status of the pull request */
9
9
@required
10
10
status: "sh.tangled.repo.pull.status.open" | "sh.tangled.repo.pull.status.closed" | "sh.tangled.repo.pull.status.merged" | string = "sh.tangled.repo.pull.status.open";
11
11
}
12
12
}
13
+
14
+
// --- Externals ---
15
+
16
+
@external
17
+
namespace sh.tangled.repo.pull.status.open {
18
+
@token model Main { }
19
+
}
20
+
21
+
@external
22
+
namespace sh.tangled.repo.pull.status.closed {
23
+
@token model Main { }
24
+
}
25
+
26
+
@external
27
+
namespace sh.tangled.repo.pull.status.merged {
28
+
@token model Main { }
29
+
}
+33
packages/emitter/test/integration/lexicon-examples/input/sh/tangled/repo/pull.tsp
+33
packages/emitter/test/integration/lexicon-examples/input/sh/tangled/repo/pull.tsp
···
1
+
import "@typelex/emitter";
2
+
3
+
namespace sh.tangled.repo.pull {
4
+
@rec("tid")
5
+
model Main {
6
+
@required target: Target;
7
+
@required title: string;
8
+
9
+
body?: string;
10
+
11
+
@required patch: string;
12
+
13
+
source?: Source;
14
+
15
+
@required createdAt: datetime;
16
+
}
17
+
18
+
model Target {
19
+
@required repo: atUri;
20
+
@required branch: string;
21
+
}
22
+
23
+
model Source {
24
+
@required branch: string;
25
+
26
+
@required
27
+
@minLength(40)
28
+
@maxLength(40)
29
+
sha: string;
30
+
31
+
repo?: atUri;
32
+
}
33
+
}
+16
packages/emitter/test/integration/lexicon-examples/input/sh/tangled/repo/removeSecret.tsp
+16
packages/emitter/test/integration/lexicon-examples/input/sh/tangled/repo/removeSecret.tsp
+13
packages/emitter/test/integration/lexicon-examples/input/sh/tangled/repo/setDefaultBranch.tsp
+13
packages/emitter/test/integration/lexicon-examples/input/sh/tangled/repo/setDefaultBranch.tsp
+80
packages/emitter/test/integration/lexicon-examples/input/sh/tangled/repo/tree.tsp
+80
packages/emitter/test/integration/lexicon-examples/input/sh/tangled/repo/tree.tsp
···
1
+
import "@typelex/emitter";
2
+
3
+
namespace sh.tangled.repo.tree {
4
+
@query
5
+
@errors(RepoNotFound, RefNotFound, PathNotFound, InvalidRequest)
6
+
op main(
7
+
/** Repository identifier in format 'did:plc:.../repoName' */
8
+
@required repo: string,
9
+
10
+
/** Git reference (branch, tag, or commit SHA) */
11
+
@required ref: string,
12
+
13
+
/** Path within the repository tree */
14
+
path?: string = "",
15
+
): {
16
+
/** The git reference used */
17
+
@required ref: string;
18
+
19
+
/** The parent path in the tree */
20
+
parent?: string;
21
+
22
+
/** Parent directory path */
23
+
dotdot?: string;
24
+
25
+
/** Readme for this file tree */
26
+
readme?: Readme;
27
+
28
+
@required files: TreeEntry[];
29
+
};
30
+
31
+
model Readme {
32
+
/** Name of the readme file */
33
+
@required filename: string;
34
+
35
+
/** Contents of the readme file */
36
+
@required contents: string;
37
+
}
38
+
39
+
model TreeEntry {
40
+
/** Relative file or directory name */
41
+
@required name: string;
42
+
43
+
/** File mode */
44
+
@required mode: string;
45
+
46
+
/** File size in bytes */
47
+
@required size: integer;
48
+
49
+
/** Whether this entry is a file */
50
+
@required is_file: boolean;
51
+
52
+
/** Whether this entry is a directory/subtree */
53
+
@required is_subtree: boolean;
54
+
55
+
last_commit?: LastCommit;
56
+
}
57
+
58
+
model LastCommit {
59
+
/** Commit hash */
60
+
@required hash: string;
61
+
62
+
/** Commit message */
63
+
@required message: string;
64
+
65
+
/** Commit timestamp */
66
+
@required when: datetime;
67
+
}
68
+
69
+
/** Repository not found or access denied */
70
+
model RepoNotFound {}
71
+
72
+
/** Git reference not found */
73
+
model RefNotFound {}
74
+
75
+
/** Path not found in repository tree */
76
+
model PathNotFound {}
77
+
78
+
/** Invalid request parameters */
79
+
model InvalidRequest {}
80
+
}
+30
packages/emitter/test/integration/lexicon-examples/input/sh/tangled/repo.tsp
+30
packages/emitter/test/integration/lexicon-examples/input/sh/tangled/repo.tsp
···
1
+
import "@typelex/emitter";
2
+
3
+
namespace sh.tangled.repo {
4
+
@rec("tid")
5
+
model Main {
6
+
@doc("name of the repo")
7
+
@required
8
+
name: string;
9
+
10
+
@doc("knot where the repo was created")
11
+
@required
12
+
knot: string;
13
+
14
+
@doc("CI runner to send jobs to and receive results from")
15
+
spindle?: string;
16
+
17
+
@minGraphemes(1)
18
+
@maxGraphemes(140)
19
+
description?: string;
20
+
21
+
@doc("source of the repo")
22
+
source?: uri;
23
+
24
+
@doc("List of labels that this repo subscribes to")
25
+
labels?: atUri[];
26
+
27
+
@required
28
+
createdAt: datetime;
29
+
}
30
+
}
+16
packages/emitter/test/integration/lexicon-examples/input/sh/tangled/spindle/member.tsp
+16
packages/emitter/test/integration/lexicon-examples/input/sh/tangled/spindle/member.tsp
···
1
+
import "@typelex/emitter";
2
+
3
+
namespace sh.tangled.spindle.member {
4
+
@rec("tid")
5
+
model Main {
6
+
@required
7
+
subject: did;
8
+
9
+
@doc("spindle instance that the subject is now a member of")
10
+
@required
11
+
instance: string;
12
+
13
+
@required
14
+
createdAt: datetime;
15
+
}
16
+
}
+8
packages/emitter/test/integration/lexicon-examples/input/sh/tangled/spindle.tsp
+8
packages/emitter/test/integration/lexicon-examples/input/sh/tangled/spindle.tsp
-10
packages/emitter/test/integration/lexicon-examples/output/sh/tangled/issue/closed.json
-10
packages/emitter/test/integration/lexicon-examples/output/sh/tangled/issue/closed.json
-35
packages/emitter/test/integration/lexicon-examples/output/sh/tangled/issue/comment.json
-35
packages/emitter/test/integration/lexicon-examples/output/sh/tangled/issue/comment.json
···
1
-
{
2
-
"lexicon": 1,
3
-
"id": "sh.tangled.repo.issue.comment",
4
-
"defs": {
5
-
"main": {
6
-
"type": "record",
7
-
"key": "tid",
8
-
"record": {
9
-
"type": "object",
10
-
"required": [
11
-
"issue",
12
-
"body",
13
-
"createdAt"
14
-
],
15
-
"properties": {
16
-
"issue": {
17
-
"type": "string",
18
-
"format": "at-uri"
19
-
},
20
-
"body": {
21
-
"type": "string"
22
-
},
23
-
"createdAt": {
24
-
"type": "string",
25
-
"format": "datetime"
26
-
},
27
-
"replyTo": {
28
-
"type": "string",
29
-
"format": "at-uri"
30
-
}
31
-
}
32
-
}
33
-
}
34
-
}
35
-
}
-30
packages/emitter/test/integration/lexicon-examples/output/sh/tangled/issue/issue.json
-30
packages/emitter/test/integration/lexicon-examples/output/sh/tangled/issue/issue.json
···
1
-
{
2
-
"lexicon": 1,
3
-
"id": "sh.tangled.repo.issue",
4
-
"defs": {
5
-
"main": {
6
-
"type": "record",
7
-
"key": "tid",
8
-
"record": {
9
-
"type": "object",
10
-
"required": ["repo", "title", "createdAt"],
11
-
"properties": {
12
-
"repo": {
13
-
"type": "string",
14
-
"format": "at-uri"
15
-
},
16
-
"title": {
17
-
"type": "string"
18
-
},
19
-
"body": {
20
-
"type": "string"
21
-
},
22
-
"createdAt": {
23
-
"type": "string",
24
-
"format": "datetime"
25
-
}
26
-
}
27
-
}
28
-
}
29
-
}
30
-
}
-10
packages/emitter/test/integration/lexicon-examples/output/sh/tangled/issue/open.json
-10
packages/emitter/test/integration/lexicon-examples/output/sh/tangled/issue/open.json
-32
packages/emitter/test/integration/lexicon-examples/output/sh/tangled/issue/state.json
-32
packages/emitter/test/integration/lexicon-examples/output/sh/tangled/issue/state.json
···
1
-
{
2
-
"lexicon": 1,
3
-
"id": "sh.tangled.repo.issue.state",
4
-
"defs": {
5
-
"main": {
6
-
"type": "record",
7
-
"key": "tid",
8
-
"record": {
9
-
"type": "object",
10
-
"required": [
11
-
"issue",
12
-
"state"
13
-
],
14
-
"properties": {
15
-
"issue": {
16
-
"type": "string",
17
-
"format": "at-uri"
18
-
},
19
-
"state": {
20
-
"type": "string",
21
-
"description": "state of the issue",
22
-
"knownValues": [
23
-
"sh.tangled.repo.issue.state.open",
24
-
"sh.tangled.repo.issue.state.closed"
25
-
],
26
-
"default": "sh.tangled.repo.issue.state.open"
27
-
}
28
-
}
29
-
}
30
-
}
31
-
}
32
-
}
-22
packages/emitter/test/integration/lexicon-examples/output/sh/tangled/knot/knot.json
-22
packages/emitter/test/integration/lexicon-examples/output/sh/tangled/knot/knot.json
···
1
-
{
2
-
"lexicon": 1,
3
-
"id": "sh.tangled.knot",
4
-
"defs": {
5
-
"main": {
6
-
"type": "record",
7
-
"key": "any",
8
-
"record": {
9
-
"type": "object",
10
-
"required": [
11
-
"createdAt"
12
-
],
13
-
"properties": {
14
-
"createdAt": {
15
-
"type": "string",
16
-
"format": "datetime"
17
-
}
18
-
}
19
-
}
20
-
}
21
-
}
22
-
}
+22
packages/emitter/test/integration/lexicon-examples/output/sh/tangled/knot.json
+22
packages/emitter/test/integration/lexicon-examples/output/sh/tangled/knot.json
···
1
+
{
2
+
"lexicon": 1,
3
+
"id": "sh.tangled.knot",
4
+
"defs": {
5
+
"main": {
6
+
"type": "record",
7
+
"key": "any",
8
+
"record": {
9
+
"type": "object",
10
+
"required": [
11
+
"createdAt"
12
+
],
13
+
"properties": {
14
+
"createdAt": {
15
+
"type": "string",
16
+
"format": "datetime"
17
+
}
18
+
}
19
+
}
20
+
}
21
+
}
22
+
}
-205
packages/emitter/test/integration/lexicon-examples/output/sh/tangled/pipeline/pipeline.json
-205
packages/emitter/test/integration/lexicon-examples/output/sh/tangled/pipeline/pipeline.json
···
1
-
{
2
-
"lexicon": 1,
3
-
"id": "sh.tangled.pipeline",
4
-
"defs": {
5
-
"main": {
6
-
"type": "record",
7
-
"key": "tid",
8
-
"record": {
9
-
"type": "object",
10
-
"required": [
11
-
"triggerMetadata",
12
-
"workflows"
13
-
],
14
-
"properties": {
15
-
"triggerMetadata": {
16
-
"type": "ref",
17
-
"ref": "#triggerMetadata"
18
-
},
19
-
"workflows": {
20
-
"type": "array",
21
-
"items": {
22
-
"type": "ref",
23
-
"ref": "#workflow"
24
-
}
25
-
}
26
-
}
27
-
}
28
-
},
29
-
"triggerMetadata": {
30
-
"type": "object",
31
-
"required": [
32
-
"kind",
33
-
"repo"
34
-
],
35
-
"properties": {
36
-
"kind": {
37
-
"type": "string",
38
-
"enum": [
39
-
"push",
40
-
"pull_request",
41
-
"manual"
42
-
]
43
-
},
44
-
"repo": {
45
-
"type": "ref",
46
-
"ref": "#triggerRepo"
47
-
},
48
-
"push": {
49
-
"type": "ref",
50
-
"ref": "#pushTriggerData"
51
-
},
52
-
"pullRequest": {
53
-
"type": "ref",
54
-
"ref": "#pullRequestTriggerData"
55
-
},
56
-
"manual": {
57
-
"type": "ref",
58
-
"ref": "#manualTriggerData"
59
-
}
60
-
}
61
-
},
62
-
"triggerRepo": {
63
-
"type": "object",
64
-
"required": [
65
-
"knot",
66
-
"did",
67
-
"repo",
68
-
"defaultBranch"
69
-
],
70
-
"properties": {
71
-
"knot": {
72
-
"type": "string"
73
-
},
74
-
"did": {
75
-
"type": "string",
76
-
"format": "did"
77
-
},
78
-
"repo": {
79
-
"type": "string"
80
-
},
81
-
"defaultBranch": {
82
-
"type": "string"
83
-
}
84
-
}
85
-
},
86
-
"pushTriggerData": {
87
-
"type": "object",
88
-
"required": [
89
-
"ref",
90
-
"newSha",
91
-
"oldSha"
92
-
],
93
-
"properties": {
94
-
"ref": {
95
-
"type": "string"
96
-
},
97
-
"newSha": {
98
-
"type": "string",
99
-
"minLength": 40,
100
-
"maxLength": 40
101
-
},
102
-
"oldSha": {
103
-
"type": "string",
104
-
"minLength": 40,
105
-
"maxLength": 40
106
-
}
107
-
}
108
-
},
109
-
"pullRequestTriggerData": {
110
-
"type": "object",
111
-
"required": [
112
-
"sourceBranch",
113
-
"targetBranch",
114
-
"sourceSha",
115
-
"action"
116
-
],
117
-
"properties": {
118
-
"sourceBranch": {
119
-
"type": "string"
120
-
},
121
-
"targetBranch": {
122
-
"type": "string"
123
-
},
124
-
"sourceSha": {
125
-
"type": "string",
126
-
"minLength": 40,
127
-
"maxLength": 40
128
-
},
129
-
"action": {
130
-
"type": "string"
131
-
}
132
-
}
133
-
},
134
-
"manualTriggerData": {
135
-
"type": "object",
136
-
"properties": {
137
-
"inputs": {
138
-
"type": "array",
139
-
"items": {
140
-
"type": "ref",
141
-
"ref": "#pair"
142
-
}
143
-
}
144
-
}
145
-
},
146
-
"workflow": {
147
-
"type": "object",
148
-
"required": [
149
-
"name",
150
-
"engine",
151
-
"clone",
152
-
"raw"
153
-
],
154
-
"properties": {
155
-
"name": {
156
-
"type": "string"
157
-
},
158
-
"engine": {
159
-
"type": "string"
160
-
},
161
-
"clone": {
162
-
"type": "ref",
163
-
"ref": "#cloneOpts"
164
-
},
165
-
"raw": {
166
-
"type": "string"
167
-
}
168
-
}
169
-
},
170
-
"cloneOpts": {
171
-
"type": "object",
172
-
"required": [
173
-
"skip",
174
-
"depth",
175
-
"submodules"
176
-
],
177
-
"properties": {
178
-
"skip": {
179
-
"type": "boolean"
180
-
},
181
-
"depth": {
182
-
"type": "integer"
183
-
},
184
-
"submodules": {
185
-
"type": "boolean"
186
-
}
187
-
}
188
-
},
189
-
"pair": {
190
-
"type": "object",
191
-
"required": [
192
-
"key",
193
-
"value"
194
-
],
195
-
"properties": {
196
-
"key": {
197
-
"type": "string"
198
-
},
199
-
"value": {
200
-
"type": "string"
201
-
}
202
-
}
203
-
}
204
-
}
205
-
}
+205
packages/emitter/test/integration/lexicon-examples/output/sh/tangled/pipeline.json
+205
packages/emitter/test/integration/lexicon-examples/output/sh/tangled/pipeline.json
···
1
+
{
2
+
"lexicon": 1,
3
+
"id": "sh.tangled.pipeline",
4
+
"defs": {
5
+
"main": {
6
+
"type": "record",
7
+
"key": "tid",
8
+
"record": {
9
+
"type": "object",
10
+
"required": [
11
+
"triggerMetadata",
12
+
"workflows"
13
+
],
14
+
"properties": {
15
+
"triggerMetadata": {
16
+
"type": "ref",
17
+
"ref": "#triggerMetadata"
18
+
},
19
+
"workflows": {
20
+
"type": "array",
21
+
"items": {
22
+
"type": "ref",
23
+
"ref": "#workflow"
24
+
}
25
+
}
26
+
}
27
+
}
28
+
},
29
+
"triggerMetadata": {
30
+
"type": "object",
31
+
"required": [
32
+
"kind",
33
+
"repo"
34
+
],
35
+
"properties": {
36
+
"kind": {
37
+
"type": "string",
38
+
"enum": [
39
+
"push",
40
+
"pull_request",
41
+
"manual"
42
+
]
43
+
},
44
+
"repo": {
45
+
"type": "ref",
46
+
"ref": "#triggerRepo"
47
+
},
48
+
"push": {
49
+
"type": "ref",
50
+
"ref": "#pushTriggerData"
51
+
},
52
+
"pullRequest": {
53
+
"type": "ref",
54
+
"ref": "#pullRequestTriggerData"
55
+
},
56
+
"manual": {
57
+
"type": "ref",
58
+
"ref": "#manualTriggerData"
59
+
}
60
+
}
61
+
},
62
+
"triggerRepo": {
63
+
"type": "object",
64
+
"required": [
65
+
"knot",
66
+
"did",
67
+
"repo",
68
+
"defaultBranch"
69
+
],
70
+
"properties": {
71
+
"knot": {
72
+
"type": "string"
73
+
},
74
+
"did": {
75
+
"type": "string",
76
+
"format": "did"
77
+
},
78
+
"repo": {
79
+
"type": "string"
80
+
},
81
+
"defaultBranch": {
82
+
"type": "string"
83
+
}
84
+
}
85
+
},
86
+
"pushTriggerData": {
87
+
"type": "object",
88
+
"required": [
89
+
"ref",
90
+
"newSha",
91
+
"oldSha"
92
+
],
93
+
"properties": {
94
+
"ref": {
95
+
"type": "string"
96
+
},
97
+
"newSha": {
98
+
"type": "string",
99
+
"minLength": 40,
100
+
"maxLength": 40
101
+
},
102
+
"oldSha": {
103
+
"type": "string",
104
+
"minLength": 40,
105
+
"maxLength": 40
106
+
}
107
+
}
108
+
},
109
+
"pullRequestTriggerData": {
110
+
"type": "object",
111
+
"required": [
112
+
"sourceBranch",
113
+
"targetBranch",
114
+
"sourceSha",
115
+
"action"
116
+
],
117
+
"properties": {
118
+
"sourceBranch": {
119
+
"type": "string"
120
+
},
121
+
"targetBranch": {
122
+
"type": "string"
123
+
},
124
+
"sourceSha": {
125
+
"type": "string",
126
+
"minLength": 40,
127
+
"maxLength": 40
128
+
},
129
+
"action": {
130
+
"type": "string"
131
+
}
132
+
}
133
+
},
134
+
"manualTriggerData": {
135
+
"type": "object",
136
+
"properties": {
137
+
"inputs": {
138
+
"type": "array",
139
+
"items": {
140
+
"type": "ref",
141
+
"ref": "#pair"
142
+
}
143
+
}
144
+
}
145
+
},
146
+
"workflow": {
147
+
"type": "object",
148
+
"required": [
149
+
"name",
150
+
"engine",
151
+
"clone",
152
+
"raw"
153
+
],
154
+
"properties": {
155
+
"name": {
156
+
"type": "string"
157
+
},
158
+
"engine": {
159
+
"type": "string"
160
+
},
161
+
"clone": {
162
+
"type": "ref",
163
+
"ref": "#cloneOpts"
164
+
},
165
+
"raw": {
166
+
"type": "string"
167
+
}
168
+
}
169
+
},
170
+
"cloneOpts": {
171
+
"type": "object",
172
+
"required": [
173
+
"skip",
174
+
"depth",
175
+
"submodules"
176
+
],
177
+
"properties": {
178
+
"skip": {
179
+
"type": "boolean"
180
+
},
181
+
"depth": {
182
+
"type": "integer"
183
+
},
184
+
"submodules": {
185
+
"type": "boolean"
186
+
}
187
+
}
188
+
},
189
+
"pair": {
190
+
"type": "object",
191
+
"required": [
192
+
"key",
193
+
"value"
194
+
],
195
+
"properties": {
196
+
"key": {
197
+
"type": "string"
198
+
},
199
+
"value": {
200
+
"type": "string"
201
+
}
202
+
}
203
+
}
204
+
}
205
+
}
-10
packages/emitter/test/integration/lexicon-examples/output/sh/tangled/pulls/closed.json
-10
packages/emitter/test/integration/lexicon-examples/output/sh/tangled/pulls/closed.json
-31
packages/emitter/test/integration/lexicon-examples/output/sh/tangled/pulls/comment.json
-31
packages/emitter/test/integration/lexicon-examples/output/sh/tangled/pulls/comment.json
···
1
-
{
2
-
"lexicon": 1,
3
-
"id": "sh.tangled.repo.pull.comment",
4
-
"defs": {
5
-
"main": {
6
-
"type": "record",
7
-
"key": "tid",
8
-
"record": {
9
-
"type": "object",
10
-
"required": [
11
-
"pull",
12
-
"body",
13
-
"createdAt"
14
-
],
15
-
"properties": {
16
-
"pull": {
17
-
"type": "string",
18
-
"format": "at-uri"
19
-
},
20
-
"body": {
21
-
"type": "string"
22
-
},
23
-
"createdAt": {
24
-
"type": "string",
25
-
"format": "datetime"
26
-
}
27
-
}
28
-
}
29
-
}
30
-
}
31
-
}
-10
packages/emitter/test/integration/lexicon-examples/output/sh/tangled/pulls/merged.json
-10
packages/emitter/test/integration/lexicon-examples/output/sh/tangled/pulls/merged.json
-10
packages/emitter/test/integration/lexicon-examples/output/sh/tangled/pulls/open.json
-10
packages/emitter/test/integration/lexicon-examples/output/sh/tangled/pulls/open.json
-79
packages/emitter/test/integration/lexicon-examples/output/sh/tangled/pulls/pull.json
-79
packages/emitter/test/integration/lexicon-examples/output/sh/tangled/pulls/pull.json
···
1
-
{
2
-
"lexicon": 1,
3
-
"id": "sh.tangled.repo.pull",
4
-
"defs": {
5
-
"main": {
6
-
"type": "record",
7
-
"key": "tid",
8
-
"record": {
9
-
"type": "object",
10
-
"required": [
11
-
"target",
12
-
"title",
13
-
"patch",
14
-
"createdAt"
15
-
],
16
-
"properties": {
17
-
"target": {
18
-
"type": "ref",
19
-
"ref": "#target"
20
-
},
21
-
"title": {
22
-
"type": "string"
23
-
},
24
-
"body": {
25
-
"type": "string"
26
-
},
27
-
"patch": {
28
-
"type": "string"
29
-
},
30
-
"source": {
31
-
"type": "ref",
32
-
"ref": "#source"
33
-
},
34
-
"createdAt": {
35
-
"type": "string",
36
-
"format": "datetime"
37
-
}
38
-
}
39
-
}
40
-
},
41
-
"target": {
42
-
"type": "object",
43
-
"required": [
44
-
"repo",
45
-
"branch"
46
-
],
47
-
"properties": {
48
-
"repo": {
49
-
"type": "string",
50
-
"format": "at-uri"
51
-
},
52
-
"branch": {
53
-
"type": "string"
54
-
}
55
-
}
56
-
},
57
-
"source": {
58
-
"type": "object",
59
-
"required": [
60
-
"branch",
61
-
"sha"
62
-
],
63
-
"properties": {
64
-
"branch": {
65
-
"type": "string"
66
-
},
67
-
"sha": {
68
-
"type": "string",
69
-
"minLength": 40,
70
-
"maxLength": 40
71
-
},
72
-
"repo": {
73
-
"type": "string",
74
-
"format": "at-uri"
75
-
}
76
-
}
77
-
}
78
-
}
79
-
}
-33
packages/emitter/test/integration/lexicon-examples/output/sh/tangled/pulls/state.json
-33
packages/emitter/test/integration/lexicon-examples/output/sh/tangled/pulls/state.json
···
1
-
{
2
-
"lexicon": 1,
3
-
"id": "sh.tangled.repo.pull.status",
4
-
"defs": {
5
-
"main": {
6
-
"type": "record",
7
-
"key": "tid",
8
-
"record": {
9
-
"type": "object",
10
-
"required": [
11
-
"pull",
12
-
"status"
13
-
],
14
-
"properties": {
15
-
"pull": {
16
-
"type": "string",
17
-
"format": "at-uri"
18
-
},
19
-
"status": {
20
-
"type": "string",
21
-
"description": "status of the pull request",
22
-
"knownValues": [
23
-
"sh.tangled.repo.pull.status.open",
24
-
"sh.tangled.repo.pull.status.closed",
25
-
"sh.tangled.repo.pull.status.merged"
26
-
],
27
-
"default": "sh.tangled.repo.pull.status.open"
28
-
}
29
-
}
30
-
}
31
-
}
32
-
}
33
-
}
+1
-2
packages/emitter/test/integration/lexicon-examples/output/sh/tangled/repo/archive.json
+1
-2
packages/emitter/test/integration/lexicon-examples/output/sh/tangled/repo/archive.json
+1
-2
packages/emitter/test/integration/lexicon-examples/output/sh/tangled/repo/compare.json
+1
-2
packages/emitter/test/integration/lexicon-examples/output/sh/tangled/repo/compare.json
-29
packages/emitter/test/integration/lexicon-examples/output/sh/tangled/repo/defaultBranch.json
-29
packages/emitter/test/integration/lexicon-examples/output/sh/tangled/repo/defaultBranch.json
···
1
-
{
2
-
"lexicon": 1,
3
-
"id": "sh.tangled.repo.setDefaultBranch",
4
-
"defs": {
5
-
"main": {
6
-
"type": "procedure",
7
-
"description": "Set the default branch for a repository",
8
-
"input": {
9
-
"encoding": "application/json",
10
-
"schema": {
11
-
"type": "object",
12
-
"required": [
13
-
"repo",
14
-
"defaultBranch"
15
-
],
16
-
"properties": {
17
-
"repo": {
18
-
"type": "string",
19
-
"format": "at-uri"
20
-
},
21
-
"defaultBranch": {
22
-
"type": "string"
23
-
}
24
-
}
25
-
}
26
-
}
27
-
}
28
-
}
29
-
}
+35
packages/emitter/test/integration/lexicon-examples/output/sh/tangled/repo/issue/comment.json
+35
packages/emitter/test/integration/lexicon-examples/output/sh/tangled/repo/issue/comment.json
···
1
+
{
2
+
"lexicon": 1,
3
+
"id": "sh.tangled.repo.issue.comment",
4
+
"defs": {
5
+
"main": {
6
+
"type": "record",
7
+
"key": "tid",
8
+
"record": {
9
+
"type": "object",
10
+
"required": [
11
+
"issue",
12
+
"body",
13
+
"createdAt"
14
+
],
15
+
"properties": {
16
+
"issue": {
17
+
"type": "string",
18
+
"format": "at-uri"
19
+
},
20
+
"body": {
21
+
"type": "string"
22
+
},
23
+
"createdAt": {
24
+
"type": "string",
25
+
"format": "datetime"
26
+
},
27
+
"replyTo": {
28
+
"type": "string",
29
+
"format": "at-uri"
30
+
}
31
+
}
32
+
}
33
+
}
34
+
}
35
+
}
+10
packages/emitter/test/integration/lexicon-examples/output/sh/tangled/repo/issue/state/closed.json
+10
packages/emitter/test/integration/lexicon-examples/output/sh/tangled/repo/issue/state/closed.json
+10
packages/emitter/test/integration/lexicon-examples/output/sh/tangled/repo/issue/state/open.json
+10
packages/emitter/test/integration/lexicon-examples/output/sh/tangled/repo/issue/state/open.json
+32
packages/emitter/test/integration/lexicon-examples/output/sh/tangled/repo/issue/state.json
+32
packages/emitter/test/integration/lexicon-examples/output/sh/tangled/repo/issue/state.json
···
1
+
{
2
+
"lexicon": 1,
3
+
"id": "sh.tangled.repo.issue.state",
4
+
"defs": {
5
+
"main": {
6
+
"type": "record",
7
+
"key": "tid",
8
+
"record": {
9
+
"type": "object",
10
+
"required": [
11
+
"issue",
12
+
"state"
13
+
],
14
+
"properties": {
15
+
"issue": {
16
+
"type": "string",
17
+
"format": "at-uri"
18
+
},
19
+
"state": {
20
+
"type": "string",
21
+
"description": "state of the issue",
22
+
"knownValues": [
23
+
"sh.tangled.repo.issue.state.open",
24
+
"sh.tangled.repo.issue.state.closed"
25
+
],
26
+
"default": "sh.tangled.repo.issue.state.open"
27
+
}
28
+
}
29
+
}
30
+
}
31
+
}
32
+
}
+30
packages/emitter/test/integration/lexicon-examples/output/sh/tangled/repo/issue.json
+30
packages/emitter/test/integration/lexicon-examples/output/sh/tangled/repo/issue.json
···
1
+
{
2
+
"lexicon": 1,
3
+
"id": "sh.tangled.repo.issue",
4
+
"defs": {
5
+
"main": {
6
+
"type": "record",
7
+
"key": "tid",
8
+
"record": {
9
+
"type": "object",
10
+
"required": ["repo", "title", "createdAt"],
11
+
"properties": {
12
+
"repo": {
13
+
"type": "string",
14
+
"format": "at-uri"
15
+
},
16
+
"title": {
17
+
"type": "string"
18
+
},
19
+
"body": {
20
+
"type": "string"
21
+
},
22
+
"createdAt": {
23
+
"type": "string",
24
+
"format": "datetime"
25
+
}
26
+
}
27
+
}
28
+
}
29
+
}
30
+
}
+31
packages/emitter/test/integration/lexicon-examples/output/sh/tangled/repo/pull/comment.json
+31
packages/emitter/test/integration/lexicon-examples/output/sh/tangled/repo/pull/comment.json
···
1
+
{
2
+
"lexicon": 1,
3
+
"id": "sh.tangled.repo.pull.comment",
4
+
"defs": {
5
+
"main": {
6
+
"type": "record",
7
+
"key": "tid",
8
+
"record": {
9
+
"type": "object",
10
+
"required": [
11
+
"pull",
12
+
"body",
13
+
"createdAt"
14
+
],
15
+
"properties": {
16
+
"pull": {
17
+
"type": "string",
18
+
"format": "at-uri"
19
+
},
20
+
"body": {
21
+
"type": "string"
22
+
},
23
+
"createdAt": {
24
+
"type": "string",
25
+
"format": "datetime"
26
+
}
27
+
}
28
+
}
29
+
}
30
+
}
31
+
}
+10
packages/emitter/test/integration/lexicon-examples/output/sh/tangled/repo/pull/status/closed.json
+10
packages/emitter/test/integration/lexicon-examples/output/sh/tangled/repo/pull/status/closed.json
+10
packages/emitter/test/integration/lexicon-examples/output/sh/tangled/repo/pull/status/merged.json
+10
packages/emitter/test/integration/lexicon-examples/output/sh/tangled/repo/pull/status/merged.json
+10
packages/emitter/test/integration/lexicon-examples/output/sh/tangled/repo/pull/status/open.json
+10
packages/emitter/test/integration/lexicon-examples/output/sh/tangled/repo/pull/status/open.json
+33
packages/emitter/test/integration/lexicon-examples/output/sh/tangled/repo/pull/status.json
+33
packages/emitter/test/integration/lexicon-examples/output/sh/tangled/repo/pull/status.json
···
1
+
{
2
+
"lexicon": 1,
3
+
"id": "sh.tangled.repo.pull.status",
4
+
"defs": {
5
+
"main": {
6
+
"type": "record",
7
+
"key": "tid",
8
+
"record": {
9
+
"type": "object",
10
+
"required": [
11
+
"pull",
12
+
"status"
13
+
],
14
+
"properties": {
15
+
"pull": {
16
+
"type": "string",
17
+
"format": "at-uri"
18
+
},
19
+
"status": {
20
+
"type": "string",
21
+
"description": "status of the pull request",
22
+
"knownValues": [
23
+
"sh.tangled.repo.pull.status.open",
24
+
"sh.tangled.repo.pull.status.closed",
25
+
"sh.tangled.repo.pull.status.merged"
26
+
],
27
+
"default": "sh.tangled.repo.pull.status.open"
28
+
}
29
+
}
30
+
}
31
+
}
32
+
}
33
+
}
+79
packages/emitter/test/integration/lexicon-examples/output/sh/tangled/repo/pull.json
+79
packages/emitter/test/integration/lexicon-examples/output/sh/tangled/repo/pull.json
···
1
+
{
2
+
"lexicon": 1,
3
+
"id": "sh.tangled.repo.pull",
4
+
"defs": {
5
+
"main": {
6
+
"type": "record",
7
+
"key": "tid",
8
+
"record": {
9
+
"type": "object",
10
+
"required": [
11
+
"target",
12
+
"title",
13
+
"patch",
14
+
"createdAt"
15
+
],
16
+
"properties": {
17
+
"target": {
18
+
"type": "ref",
19
+
"ref": "#target"
20
+
},
21
+
"title": {
22
+
"type": "string"
23
+
},
24
+
"body": {
25
+
"type": "string"
26
+
},
27
+
"patch": {
28
+
"type": "string"
29
+
},
30
+
"source": {
31
+
"type": "ref",
32
+
"ref": "#source"
33
+
},
34
+
"createdAt": {
35
+
"type": "string",
36
+
"format": "datetime"
37
+
}
38
+
}
39
+
}
40
+
},
41
+
"target": {
42
+
"type": "object",
43
+
"required": [
44
+
"repo",
45
+
"branch"
46
+
],
47
+
"properties": {
48
+
"repo": {
49
+
"type": "string",
50
+
"format": "at-uri"
51
+
},
52
+
"branch": {
53
+
"type": "string"
54
+
}
55
+
}
56
+
},
57
+
"source": {
58
+
"type": "object",
59
+
"required": [
60
+
"branch",
61
+
"sha"
62
+
],
63
+
"properties": {
64
+
"branch": {
65
+
"type": "string"
66
+
},
67
+
"sha": {
68
+
"type": "string",
69
+
"minLength": 40,
70
+
"maxLength": 40
71
+
},
72
+
"repo": {
73
+
"type": "string",
74
+
"format": "at-uri"
75
+
}
76
+
}
77
+
}
78
+
}
79
+
}
-54
packages/emitter/test/integration/lexicon-examples/output/sh/tangled/repo/repo.json
-54
packages/emitter/test/integration/lexicon-examples/output/sh/tangled/repo/repo.json
···
1
-
{
2
-
"lexicon": 1,
3
-
"id": "sh.tangled.repo",
4
-
"defs": {
5
-
"main": {
6
-
"type": "record",
7
-
"key": "tid",
8
-
"record": {
9
-
"type": "object",
10
-
"required": [
11
-
"name",
12
-
"knot",
13
-
"createdAt"
14
-
],
15
-
"properties": {
16
-
"name": {
17
-
"type": "string",
18
-
"description": "name of the repo"
19
-
},
20
-
"knot": {
21
-
"type": "string",
22
-
"description": "knot where the repo was created"
23
-
},
24
-
"spindle": {
25
-
"type": "string",
26
-
"description": "CI runner to send jobs to and receive results from"
27
-
},
28
-
"description": {
29
-
"type": "string",
30
-
"minGraphemes": 1,
31
-
"maxGraphemes": 140
32
-
},
33
-
"source": {
34
-
"type": "string",
35
-
"format": "uri",
36
-
"description": "source of the repo"
37
-
},
38
-
"labels": {
39
-
"type": "array",
40
-
"description": "List of labels that this repo subscribes to",
41
-
"items": {
42
-
"type": "string",
43
-
"format": "at-uri"
44
-
}
45
-
},
46
-
"createdAt": {
47
-
"type": "string",
48
-
"format": "datetime"
49
-
}
50
-
}
51
-
}
52
-
}
53
-
}
54
-
}
+29
packages/emitter/test/integration/lexicon-examples/output/sh/tangled/repo/setDefaultBranch.json
+29
packages/emitter/test/integration/lexicon-examples/output/sh/tangled/repo/setDefaultBranch.json
···
1
+
{
2
+
"lexicon": 1,
3
+
"id": "sh.tangled.repo.setDefaultBranch",
4
+
"defs": {
5
+
"main": {
6
+
"type": "procedure",
7
+
"description": "Set the default branch for a repository",
8
+
"input": {
9
+
"encoding": "application/json",
10
+
"schema": {
11
+
"type": "object",
12
+
"required": [
13
+
"repo",
14
+
"defaultBranch"
15
+
],
16
+
"properties": {
17
+
"repo": {
18
+
"type": "string",
19
+
"format": "at-uri"
20
+
},
21
+
"defaultBranch": {
22
+
"type": "string"
23
+
}
24
+
}
25
+
}
26
+
}
27
+
}
28
+
}
29
+
}
+54
packages/emitter/test/integration/lexicon-examples/output/sh/tangled/repo.json
+54
packages/emitter/test/integration/lexicon-examples/output/sh/tangled/repo.json
···
1
+
{
2
+
"lexicon": 1,
3
+
"id": "sh.tangled.repo",
4
+
"defs": {
5
+
"main": {
6
+
"type": "record",
7
+
"key": "tid",
8
+
"record": {
9
+
"type": "object",
10
+
"required": [
11
+
"name",
12
+
"knot",
13
+
"createdAt"
14
+
],
15
+
"properties": {
16
+
"name": {
17
+
"type": "string",
18
+
"description": "name of the repo"
19
+
},
20
+
"knot": {
21
+
"type": "string",
22
+
"description": "knot where the repo was created"
23
+
},
24
+
"spindle": {
25
+
"type": "string",
26
+
"description": "CI runner to send jobs to and receive results from"
27
+
},
28
+
"description": {
29
+
"type": "string",
30
+
"minGraphemes": 1,
31
+
"maxGraphemes": 140
32
+
},
33
+
"source": {
34
+
"type": "string",
35
+
"format": "uri",
36
+
"description": "source of the repo"
37
+
},
38
+
"labels": {
39
+
"type": "array",
40
+
"description": "List of labels that this repo subscribes to",
41
+
"items": {
42
+
"type": "string",
43
+
"format": "at-uri"
44
+
}
45
+
},
46
+
"createdAt": {
47
+
"type": "string",
48
+
"format": "datetime"
49
+
}
50
+
}
51
+
}
52
+
}
53
+
}
54
+
}
-23
packages/emitter/test/integration/lexicon-examples/output/sh/tangled/spindle/spindle.json
-23
packages/emitter/test/integration/lexicon-examples/output/sh/tangled/spindle/spindle.json
···
1
-
{
2
-
"lexicon": 1,
3
-
"id": "sh.tangled.spindle",
4
-
"defs": {
5
-
"main": {
6
-
"type": "record",
7
-
"key": "any",
8
-
"record": {
9
-
"type": "object",
10
-
"required": [
11
-
"createdAt"
12
-
],
13
-
"properties": {
14
-
"createdAt": {
15
-
"type": "string",
16
-
"format": "datetime"
17
-
}
18
-
}
19
-
}
20
-
}
21
-
}
22
-
}
23
-
+23
packages/emitter/test/integration/lexicon-examples/output/sh/tangled/spindle.json
+23
packages/emitter/test/integration/lexicon-examples/output/sh/tangled/spindle.json
···
1
+
{
2
+
"lexicon": 1,
3
+
"id": "sh.tangled.spindle",
4
+
"defs": {
5
+
"main": {
6
+
"type": "record",
7
+
"key": "any",
8
+
"record": {
9
+
"type": "object",
10
+
"required": [
11
+
"createdAt"
12
+
],
13
+
"properties": {
14
+
"createdAt": {
15
+
"type": "string",
16
+
"format": "datetime"
17
+
}
18
+
}
19
+
}
20
+
}
21
+
}
22
+
}
23
+
-38
packages/emitter/test/integration/lexicon-examples/output/sh/tangled/string/string.json
-38
packages/emitter/test/integration/lexicon-examples/output/sh/tangled/string/string.json
···
1
-
{
2
-
"lexicon": 1,
3
-
"id": "sh.tangled.string",
4
-
"defs": {
5
-
"main": {
6
-
"type": "record",
7
-
"key": "tid",
8
-
"record": {
9
-
"type": "object",
10
-
"required": [
11
-
"filename",
12
-
"description",
13
-
"createdAt",
14
-
"contents"
15
-
],
16
-
"properties": {
17
-
"filename": {
18
-
"type": "string",
19
-
"maxGraphemes": 140,
20
-
"minGraphemes": 1
21
-
},
22
-
"description": {
23
-
"type": "string",
24
-
"maxGraphemes": 280
25
-
},
26
-
"createdAt": {
27
-
"type": "string",
28
-
"format": "datetime"
29
-
},
30
-
"contents": {
31
-
"type": "string",
32
-
"minGraphemes": 1
33
-
}
34
-
}
35
-
}
36
-
}
37
-
}
38
-
}
+12
-20
packages/emitter/test/integration.test.ts
+12
-20
packages/emitter/test/integration.test.ts
···
54
54
path.join(scenario, "output"),
55
55
);
56
56
57
-
// Compile all inputs together (for cross-references)
58
-
const tspFiles = Object.keys(inputFiles).filter((f) =>
59
-
f.endsWith(".tsp"),
60
-
);
61
-
let emitResult: EmitResult;
62
-
63
-
if (tspFiles.length > 0) {
64
-
// Create a virtual main.tsp that imports all other files
65
-
const mainContent =
66
-
'import "@typelex/emitter";\n' +
67
-
tspFiles.map((f) => `import "./${f}";`).join("\n");
68
-
const filesWithMain = { ...inputFiles, "main.tsp": mainContent };
69
-
emitResult = await doEmit(filesWithMain, "main.tsp");
70
-
} else {
71
-
emitResult = { files: {}, diagnostics: [], inputFiles: {} };
72
-
}
73
-
74
57
// Generate a test for each expected output
75
58
for (const expectedPath of Object.keys(expectedFiles)) {
76
59
if (!expectedPath.endsWith(".json")) continue;
···
80
63
const hasInput = Object.keys(inputFiles).includes(inputPath);
81
64
82
65
if (hasInput) {
83
-
it(`should emit ${expectedPath}`, function () {
66
+
it(`should emit ${expectedPath}`, async function () {
67
+
// Compile each file in isolation
68
+
const emitResult = await doEmit({ [inputPath]: inputFiles[inputPath] }, inputPath);
69
+
84
70
// Check for compilation errors
85
71
if (emitResult.diagnostics.length > 0) {
86
72
const formattedDiagnostics = emitResult.diagnostics.map((diag) =>
···
91
77
);
92
78
}
93
79
80
+
const normalizedExpectedPath = normalizePathToPosix(expectedPath);
81
+
94
82
assert.ok(
95
83
Object.prototype.hasOwnProperty.call(
96
84
emitResult.files,
97
-
expectedPath,
85
+
normalizedExpectedPath,
98
86
),
99
87
`Expected file ${expectedPath} was not produced`,
100
88
);
101
89
102
-
const actual = JSON.parse(emitResult.files[expectedPath]);
90
+
const actual = JSON.parse(emitResult.files[normalizedExpectedPath]);
103
91
const expected = JSON.parse(expectedFiles[expectedPath]);
104
92
assert.deepStrictEqual(actual, expected);
105
93
});
···
180
168
await walk(dir, "");
181
169
return result;
182
170
}
171
+
172
+
function normalizePathToPosix(thePath: string): string {
173
+
return thePath.replaceAll(path.sep, path.posix.sep);
174
+
}
+2
-2
packages/emitter/test/spec/basic/input/com/example/allOptionalFields.tsp
+2
-2
packages/emitter/test/spec/basic/input/com/example/allOptionalFields.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace com.example.allOptionalFields {
4
-
@doc("Object with all optional fields (no required)")
4
+
/** Object with all optional fields (no required) */
5
5
model Main {
6
-
@doc("All fields are optional")
6
+
/** All fields are optional */
7
7
field1?: string;
8
8
9
9
field2?: integer;
+2
-2
packages/emitter/test/spec/basic/input/com/example/arrayOfUnions.tsp
+2
-2
packages/emitter/test/spec/basic/input/com/example/arrayOfUnions.tsp
···
2
2
3
3
namespace com.example.arrayOfUnions {
4
4
model Main {
5
-
@doc("Array of open union variants")
5
+
/** Array of open union variants */
6
6
@required
7
7
items: (ItemA | ItemB | ItemC | unknown)[];
8
8
9
-
@doc("Array of closed union variants")
9
+
/** Array of closed union variants */
10
10
@maxItems(10)
11
11
operations?: Operations[];
12
12
}
+5
-5
packages/emitter/test/spec/basic/input/com/example/arrays.tsp
+5
-5
packages/emitter/test/spec/basic/input/com/example/arrays.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace com.example.arrays {
4
-
@doc("Array container types")
4
+
/** Array container types */
5
5
model Main {
6
-
@doc("Array of strings")
6
+
/** Array of strings */
7
7
stringArray?: string[];
8
8
9
-
@doc("Array with size constraints")
9
+
/** Array with size constraints */
10
10
@minItems(1)
11
11
@maxItems(10)
12
12
arrayWithLength?: integer[];
13
13
14
-
@doc("Array of object references")
14
+
/** Array of object references */
15
15
arrayOfRefs?: Item[];
16
16
17
-
@doc("Array of union types")
17
+
/** Array of union types */
18
18
arrayOfUnion?: (TypeA | TypeB | unknown)[];
19
19
}
20
20
+6
-6
packages/emitter/test/spec/basic/input/com/example/blobs.tsp
+6
-6
packages/emitter/test/spec/basic/input/com/example/blobs.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace com.example.blobs {
4
-
@doc("Blob type examples")
4
+
/** Blob type examples */
5
5
model Main {
6
-
@doc("Basic blob with no constraints")
6
+
/** Basic blob with no constraints */
7
7
simpleBlob?: Blob;
8
8
9
-
@doc("Image blob up to 5MB")
9
+
/** Image blob up to 5MB */
10
10
imageBlob?: Blob<#["image/*"], 5000000>;
11
11
12
-
@doc("Specific image types up to 2MB")
12
+
/** Specific image types up to 2MB */
13
13
specificImages?: Blob<#["image/png", "image/jpeg", "image/gif"], 2000000>;
14
14
15
-
@doc("Video blob up to 100MB")
15
+
/** Video blob up to 100MB */
16
16
videoBlob?: Blob<#["video/mp4", "video/webm"], 100000000>;
17
17
18
-
@doc("Accept any MIME type")
18
+
/** Accept any MIME type */
19
19
anyBlob?: Blob<#["*/*"]>;
20
20
}
21
21
}
+5
-5
packages/emitter/test/spec/basic/input/com/example/booleanConstraints.tsp
+5
-5
packages/emitter/test/spec/basic/input/com/example/booleanConstraints.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace com.example.booleanConstraints {
4
-
@doc("Boolean field constraints")
4
+
/** Boolean field constraints */
5
5
model Main {
6
-
@doc("Boolean with default true")
6
+
/** Boolean with default true */
7
7
defaultTrue?: boolean = true;
8
8
9
-
@doc("Boolean with default false")
9
+
/** Boolean with default false */
10
10
defaultFalse?: boolean = false;
11
11
12
-
@doc("Constant true value")
12
+
/** Constant true value */
13
13
@readOnly
14
14
constTrue?: boolean = true;
15
15
16
-
@doc("Constant false value")
16
+
/** Constant false value */
17
17
@readOnly
18
18
constFalse?: boolean = false;
19
19
}
+5
-5
packages/emitter/test/spec/basic/input/com/example/bytesConstraints.tsp
+5
-5
packages/emitter/test/spec/basic/input/com/example/bytesConstraints.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace com.example.bytesConstraints {
4
-
@doc("Bytes field constraints")
4
+
/** Bytes field constraints */
5
5
model Main {
6
-
@doc("Basic bytes field")
6
+
/** Basic bytes field */
7
7
simpleBytes?: bytes;
8
8
9
-
@doc("Bytes with size constraints")
9
+
/** Bytes with size constraints */
10
10
@minBytes(1)
11
11
@maxBytes(1024)
12
12
withLength?: bytes;
13
13
14
-
@doc("Bytes with minimum size only")
14
+
/** Bytes with minimum size only */
15
15
@minBytes(32)
16
16
withMinOnly?: bytes;
17
17
18
-
@doc("Bytes with maximum size only (5MB)")
18
+
/** Bytes with maximum size only (5MB) */
19
19
@maxBytes(5000000)
20
20
withMaxOnly?: bytes;
21
21
}
+3
-3
packages/emitter/test/spec/basic/input/com/example/cidLinks.tsp
+3
-3
packages/emitter/test/spec/basic/input/com/example/cidLinks.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace com.example.cidLinks {
4
-
@doc("CID link examples")
4
+
/** CID link examples */
5
5
model Main {
6
-
@doc("A CID link to content")
6
+
/** A CID link to content */
7
7
contentCid?: cidLink;
8
8
9
-
@doc("Link to previous version")
9
+
/** Link to previous version */
10
10
previousVersion?: cidLink;
11
11
}
12
12
}
+7
-7
packages/emitter/test/spec/basic/input/com/example/constValues.tsp
+7
-7
packages/emitter/test/spec/basic/input/com/example/constValues.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace com.example.constValues {
4
-
@doc("Tests const values on all supported types")
4
+
/** Tests const values on all supported types */
5
5
model Main {
6
-
@doc("Constant string value")
6
+
/** Constant string value */
7
7
@readOnly
8
8
@required
9
9
stringConst: string = "fixed-value";
10
10
11
-
@doc("Constant boolean value (true)")
11
+
/** Constant boolean value (true) */
12
12
@readOnly
13
13
@required
14
14
boolConst: boolean = true;
15
15
16
-
@doc("Constant boolean value (false)")
16
+
/** Constant boolean value (false) */
17
17
@readOnly
18
18
falseConst?: boolean = false;
19
19
20
-
@doc("Constant integer value")
20
+
/** Constant integer value */
21
21
@readOnly
22
22
@required
23
23
intConst: integer = 42;
24
24
25
-
@doc("Constant zero")
25
+
/** Constant zero */
26
26
@readOnly
27
27
zeroConst?: integer = 0;
28
28
29
-
@doc("Constant negative integer")
29
+
/** Constant negative integer */
30
30
@readOnly
31
31
negativeConst?: integer = -100;
32
32
}
+3
-3
packages/emitter/test/spec/basic/input/com/example/createRecord.tsp
+3
-3
packages/emitter/test/spec/basic/input/com/example/createRecord.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace com.example.createRecord {
4
-
@doc("The provided text is invalid")
4
+
/** The provided text is invalid */
5
5
model InvalidText {}
6
6
7
-
@doc("Create a new record")
7
+
/** Create a new record */
8
8
@procedure
9
9
@errors(InvalidText)
10
10
op main(input: {
11
-
@doc("The text content")
11
+
/** The text content */
12
12
@required
13
13
text: string;
14
14
}): {
+4
-4
packages/emitter/test/spec/basic/input/com/example/datetimeExamples.tsp
+4
-4
packages/emitter/test/spec/basic/input/com/example/datetimeExamples.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace com.example.datetimeExamples {
4
-
@doc("Datetime format usage examples")
4
+
/** Datetime format usage examples */
5
5
model Main {
6
-
@doc("Required datetime field")
6
+
/** Required datetime field */
7
7
@required
8
8
createdAt: datetime;
9
9
10
-
@doc("Optional datetime field")
10
+
/** Optional datetime field */
11
11
updatedAt?: datetime;
12
12
13
-
@doc("Optional publish time")
13
+
/** Optional publish time */
14
14
publishedAt?: datetime;
15
15
}
16
16
}
+3
-3
packages/emitter/test/spec/basic/input/com/example/deeplyNested.tsp
+3
-3
packages/emitter/test/spec/basic/input/com/example/deeplyNested.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace com.example.deeplyNested {
4
-
@doc("Tests deeply nested object structures")
4
+
/** Tests deeply nested object structures */
5
5
model Main {
6
-
@doc("Three levels of nesting")
6
+
/** Three levels of nesting */
7
7
@required
8
8
level1: Level1;
9
9
}
···
21
21
model Level3 {
22
22
@required data: string;
23
23
24
-
@doc("Nullable field at deep level")
24
+
/** Nullable field at deep level */
25
25
metadata?: Metadata | null;
26
26
}
27
27
+1
-1
packages/emitter/test/spec/basic/input/com/example/defs.tsp
+1
-1
packages/emitter/test/spec/basic/input/com/example/defs.tsp
+1
-1
packages/emitter/test/spec/basic/input/com/example/deleteRecord.tsp
+1
-1
packages/emitter/test/spec/basic/input/com/example/deleteRecord.tsp
+2
-2
packages/emitter/test/spec/basic/input/com/example/eventStream.tsp
+2
-2
packages/emitter/test/spec/basic/input/com/example/eventStream.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace com.example.eventStream {
4
-
@doc("Cursor is in the future")
4
+
/** Cursor is in the future */
5
5
model FutureCursor {}
6
6
7
-
@doc("Subscription with union message schema")
7
+
/** Subscription with union message schema */
8
8
@subscription
9
9
@errors(FutureCursor)
10
10
op main(cursor?: integer): (Commit | Identity | Account | Handle | Tombstone);
+1
-1
packages/emitter/test/spec/basic/input/com/example/flexibleRecord.tsp
+1
-1
packages/emitter/test/spec/basic/input/com/example/flexibleRecord.tsp
+2
-2
packages/emitter/test/spec/basic/input/com/example/getRecord.tsp
+2
-2
packages/emitter/test/spec/basic/input/com/example/getRecord.tsp
+1
-1
packages/emitter/test/spec/basic/input/com/example/getStatus.tsp
+1
-1
packages/emitter/test/spec/basic/input/com/example/getStatus.tsp
+6
-6
packages/emitter/test/spec/basic/input/com/example/identifierExamples.tsp
+6
-6
packages/emitter/test/spec/basic/input/com/example/identifierExamples.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace com.example.identifierExamples {
4
-
@doc("Identifier format examples")
4
+
/** Identifier format examples */
5
5
model Main {
6
-
@doc("DID identifier (did:plc:, did:web:, etc)")
6
+
/** DID identifier (did:plc:, did:web:, etc) */
7
7
did?: did;
8
8
9
-
@doc("Handle identifier (username.bsky.social)")
9
+
/** Handle identifier (username.bsky.social) */
10
10
handle?: handle;
11
11
12
-
@doc("Either a DID or handle")
12
+
/** Either a DID or handle */
13
13
atIdentifier?: atIdentifier;
14
14
15
-
@doc("CID as string")
15
+
/** CID as string */
16
16
cidString?: cid;
17
17
18
-
@doc("BCP 47 language tag")
18
+
/** BCP 47 language tag */
19
19
languageCode?: language;
20
20
}
21
21
}
+5
-5
packages/emitter/test/spec/basic/input/com/example/integerConstraints.tsp
+5
-5
packages/emitter/test/spec/basic/input/com/example/integerConstraints.tsp
···
12
12
13,
13
13
}
14
14
15
-
@doc("Integer field constraints")
15
+
/** Integer field constraints */
16
16
model Main {
17
-
@doc("Integer between 1 and 100")
17
+
/** Integer between 1 and 100 */
18
18
@minValue(1)
19
19
@maxValue(100)
20
20
withMinMax?: integer;
21
21
22
-
@doc("Fibonacci numbers only")
22
+
/** Fibonacci numbers only */
23
23
withEnum?: FibonacciNumbers;
24
24
25
-
@doc("Integer with default value")
25
+
/** Integer with default value */
26
26
withDefault?: integer = 42;
27
27
28
-
@doc("Constant integer value")
28
+
/** Constant integer value */
29
29
@readOnly
30
30
withConst?: integer = 99;
31
31
}
+6
-6
packages/emitter/test/spec/basic/input/com/example/nestedUnions.tsp
+6
-6
packages/emitter/test/spec/basic/input/com/example/nestedUnions.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace com.example.nestedUnions {
4
-
@doc("Tests unions nested within objects and arrays")
4
+
/** Tests unions nested within objects and arrays */
5
5
model Main {
6
-
@doc("Object containing a union field")
6
+
/** Object containing a union field */
7
7
@required
8
8
container: Container;
9
9
10
-
@doc("Array of objects that contain unions")
10
+
/** Array of objects that contain unions */
11
11
items?: Item[];
12
12
}
13
13
14
14
model Container {
15
15
@required id: string;
16
16
17
-
@doc("Nested union within object")
17
+
/** Nested union within object */
18
18
@required
19
19
payload: (PayloadA | PayloadB | unknown);
20
20
21
-
@doc("Nullable ref within object")
21
+
/** Nullable ref within object */
22
22
metadata?: MetadataPublic | null;
23
23
}
24
24
25
25
model Item {
26
26
@required name: string;
27
27
28
-
@doc("Union in nested object")
28
+
/** Union in nested object */
29
29
content?: (TextContent | ImageContent | VideoContent | unknown);
30
30
}
31
31
+4
-4
packages/emitter/test/spec/basic/input/com/example/nullType.tsp
+4
-4
packages/emitter/test/spec/basic/input/com/example/nullType.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace com.example.nullType {
4
-
@doc("Demonstrates the null primitive type")
4
+
/** Demonstrates the null primitive type */
5
5
model Main {
6
-
@doc("Field with explicit null type - always null")
6
+
/** Field with explicit null type - always null */
7
7
@required
8
8
alwaysNull: null;
9
9
10
-
@doc("Optional field that can be string or omitted, but not null")
10
+
/** Optional field that can be string or omitted, but not null */
11
11
optionalString?: string;
12
12
13
-
@doc("Nullable string - can be omitted, string, or null")
13
+
/** Nullable string - can be omitted, string, or null */
14
14
nullableString?: string | null;
15
15
}
16
16
}
+5
-5
packages/emitter/test/spec/basic/input/com/example/nullableFields.tsp
+5
-5
packages/emitter/test/spec/basic/input/com/example/nullableFields.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace com.example.nullableFields {
4
-
@doc("Demonstrates nullable field semantics")
4
+
/** Demonstrates nullable field semantics */
5
5
model Main {
6
-
@doc("Required, cannot be null or omitted")
6
+
/** Required, cannot be null or omitted */
7
7
@required
8
8
requiredField: string;
9
9
10
-
@doc("Must be present, but can be null")
10
+
/** Must be present, but can be null */
11
11
nullableRequired?: string | null;
12
12
13
-
@doc("Can be omitted, present with value, or present as null")
13
+
/** Can be omitted, present with value, or present as null */
14
14
nullableOptional?: string | null;
15
15
16
-
@doc("Can be omitted or present with value, but not null")
16
+
/** Can be omitted or present with value, but not null */
17
17
optionalField?: string;
18
18
}
19
19
}
+4
-4
packages/emitter/test/spec/basic/input/com/example/objects.tsp
+4
-4
packages/emitter/test/spec/basic/input/com/example/objects.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace com.example.objects {
4
-
@doc("Object with various property configurations")
4
+
/** Object with various property configurations */
5
5
model Main {
6
-
@doc("This field is required")
6
+
/** This field is required */
7
7
@required
8
8
requiredField: string;
9
9
10
-
@doc("This field is optional")
10
+
/** This field is optional */
11
11
optionalField?: string;
12
12
13
-
@doc("This field can be null")
13
+
/** This field can be null */
14
14
nullableField?: string | null;
15
15
16
16
nestedObject?: Nested;
+1
-1
packages/emitter/test/spec/basic/input/com/example/outputWithoutSchema.tsp
+1
-1
packages/emitter/test/spec/basic/input/com/example/outputWithoutSchema.tsp
+5
-5
packages/emitter/test/spec/basic/input/com/example/paramsWithArrays.tsp
+5
-5
packages/emitter/test/spec/basic/input/com/example/paramsWithArrays.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace com.example.paramsWithArrays {
4
-
@doc("Tests query parameters with array types")
4
+
/** Tests query parameters with array types */
5
5
@query
6
6
op main(
7
-
@doc("Array of string values")
7
+
/** Array of string values */
8
8
tags?: string[],
9
9
10
-
@doc("Array of integers")
10
+
/** Array of integers */
11
11
@maxItems(10)
12
12
ids?: integer[],
13
13
14
-
@doc("Array of booleans")
14
+
/** Array of booleans */
15
15
flags?: boolean[],
16
16
17
-
@doc("Single string param for comparison")
17
+
/** Single string param for comparison */
18
18
cursor?: string
19
19
): {
20
20
@required count: integer;
+6
-6
packages/emitter/test/spec/basic/input/com/example/primitives.tsp
+6
-6
packages/emitter/test/spec/basic/input/com/example/primitives.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace com.example.primitives {
4
-
@doc("All primitive field types")
4
+
/** All primitive field types */
5
5
model Main {
6
-
@doc("A boolean field")
6
+
/** A boolean field */
7
7
boolField?: boolean;
8
8
9
-
@doc("An integer field")
9
+
/** An integer field */
10
10
intField?: integer;
11
11
12
-
@doc("A string field")
12
+
/** A string field */
13
13
stringField?: string;
14
14
15
-
@doc("A bytes field")
15
+
/** A bytes field */
16
16
bytesField?: bytes;
17
17
18
-
@doc("A CID link field")
18
+
/** A CID link field */
19
19
cidField?: cidLink;
20
20
}
21
21
}
+5
-5
packages/emitter/test/spec/basic/input/com/example/procedureWithBoth.tsp
+5
-5
packages/emitter/test/spec/basic/input/com/example/procedureWithBoth.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace com.example.procedureWithBoth {
4
-
@doc("Procedure with both input body and query parameters")
4
+
/** Procedure with both input body and query parameters */
5
5
@procedure
6
6
op main(
7
7
input: {
8
-
@doc("Data to create")
8
+
/** Data to create */
9
9
@required
10
10
data: string;
11
11
12
-
@doc("Optional metadata")
12
+
/** Optional metadata */
13
13
metadata?: Metadata;
14
14
},
15
15
parameters: {
16
-
@doc("Whether to validate before creating")
16
+
/** Whether to validate before creating */
17
17
validate?: boolean = true;
18
18
19
-
@doc("Target repository")
19
+
/** Target repository */
20
20
@required
21
21
repo: atIdentifier;
22
22
}
+1
-1
packages/emitter/test/spec/basic/input/com/example/profile.tsp
+1
-1
packages/emitter/test/spec/basic/input/com/example/profile.tsp
+7
-7
packages/emitter/test/spec/basic/input/com/example/queryParams.tsp
+7
-7
packages/emitter/test/spec/basic/input/com/example/queryParams.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace com.example.queryParams {
4
-
@doc("Query with various parameter types")
4
+
/** Query with various parameter types */
5
5
@query
6
6
op main(
7
-
@doc("A required query parameter")
7
+
/** A required query parameter */
8
8
@required
9
9
requiredParam: string,
10
10
11
-
@doc("Optional boolean parameter")
11
+
/** Optional boolean parameter */
12
12
boolParam?: boolean,
13
13
14
-
@doc("Optional integer parameter")
14
+
/** Optional integer parameter */
15
15
intParam?: integer,
16
16
17
-
@doc("Optional string parameter")
17
+
/** Optional string parameter */
18
18
@maxLength(100)
19
19
stringParam?: string,
20
20
21
-
@doc("Array of strings")
21
+
/** Array of strings */
22
22
arrayParam?: string[],
23
23
24
-
@doc("Unknown type parameter")
24
+
/** Unknown type parameter */
25
25
unknownParam?: unknown
26
26
): {
27
27
@required result: string;
+3
-3
packages/emitter/test/spec/basic/input/com/example/record.tsp
+3
-3
packages/emitter/test/spec/basic/input/com/example/record.tsp
···
2
2
3
3
namespace com.example.`record` {
4
4
@rec("tid")
5
-
@doc("A simple record with basic properties")
5
+
/** A simple record with basic properties */
6
6
model Main {
7
-
@doc("The text content")
7
+
/** The text content */
8
8
@required
9
9
text: string;
10
10
11
-
@doc("When the record was created")
11
+
/** When the record was created */
12
12
@required
13
13
createdAt: datetime;
14
14
}
+3
-3
packages/emitter/test/spec/basic/input/com/example/recordWithNsidKey.tsp
+3
-3
packages/emitter/test/spec/basic/input/com/example/recordWithNsidKey.tsp
···
2
2
3
3
namespace com.example.recordWithNsidKey {
4
4
@rec("nsid")
5
-
@doc("Record with NSID as the record key")
5
+
/** Record with NSID as the record key */
6
6
model Main {
7
-
@doc("The NSID of the associated lexicon")
7
+
/** The NSID of the associated lexicon */
8
8
@required
9
9
nsid: nsid;
10
10
11
-
@doc("Optional metadata")
11
+
/** Optional metadata */
12
12
metadata?: string;
13
13
}
14
14
}
+1
-1
packages/emitter/test/spec/basic/input/com/example/refInOutput.tsp
+1
-1
packages/emitter/test/spec/basic/input/com/example/refInOutput.tsp
+4
-4
packages/emitter/test/spec/basic/input/com/example/refs.tsp
+4
-4
packages/emitter/test/spec/basic/input/com/example/refs.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace com.example.refs {
4
-
@doc("Reference examples")
4
+
/** Reference examples */
5
5
model Main {
6
-
@doc("Reference to local definition")
6
+
/** Reference to local definition */
7
7
localRef?: LocalDef;
8
8
9
-
@doc("Reference to external definition")
9
+
/** Reference to external definition */
10
10
externalRef?: com.example.defs.Metadata;
11
11
12
-
@doc("Reference to main definition (no fragment)")
12
+
/** Reference to main definition (no fragment) */
13
13
mainRef?: com.example.`record`.Main;
14
14
}
15
15
+8
-8
packages/emitter/test/spec/basic/input/com/example/stringConstraints.tsp
+8
-8
packages/emitter/test/spec/basic/input/com/example/stringConstraints.tsp
···
9
9
"archived",
10
10
}
11
11
12
-
@doc("String field constraints")
12
+
/** String field constraints */
13
13
model Main {
14
-
@doc("String with byte length constraints")
14
+
/** String with byte length constraints */
15
15
@minLength(1)
16
16
@maxLength(100)
17
17
withLength?: string;
18
18
19
-
@doc("String with grapheme cluster length constraints")
19
+
/** String with grapheme cluster length constraints */
20
20
@minGraphemes(1)
21
21
@maxGraphemes(50)
22
22
withGraphemes?: string;
23
23
24
-
@doc("String with both byte and grapheme constraints")
24
+
/** String with both byte and grapheme constraints */
25
25
@minLength(1)
26
26
@maxLength(300)
27
27
@minGraphemes(1)
28
28
@maxGraphemes(100)
29
29
withBothLengths?: string;
30
30
31
-
@doc("Closed enum of allowed values")
31
+
/** Closed enum of allowed values */
32
32
withEnum?: StatusEnum;
33
33
34
-
@doc("Open set of suggested values")
34
+
/** Open set of suggested values */
35
35
withKnownValues?: "en" | "es" | "fr" | "de" | "ja" | string;
36
36
37
-
@doc("String with default value")
37
+
/** String with default value */
38
38
withDefault?: string = "hello";
39
39
40
-
@doc("Constant string value")
40
+
/** Constant string value */
41
41
@readOnly
42
42
withConst?: string = "fixed-value";
43
43
}
+12
-12
packages/emitter/test/spec/basic/input/com/example/stringFormats.tsp
+12
-12
packages/emitter/test/spec/basic/input/com/example/stringFormats.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace com.example.stringFormats {
4
-
@doc("All string format types")
4
+
/** All string format types */
5
5
model Main {
6
-
@doc("Handle or DID")
6
+
/** Handle or DID */
7
7
atIdentifier?: atIdentifier;
8
8
9
-
@doc("AT-URI format")
9
+
/** AT-URI format */
10
10
atUri?: atUri;
11
11
12
-
@doc("CID in string format")
12
+
/** CID in string format */
13
13
cid?: cid;
14
14
15
-
@doc("ISO 8601 datetime with timezone")
15
+
/** ISO 8601 datetime with timezone */
16
16
datetime?: datetime;
17
17
18
-
@doc("DID identifier")
18
+
/** DID identifier */
19
19
did?: did;
20
20
21
-
@doc("Handle identifier")
21
+
/** Handle identifier */
22
22
handle?: handle;
23
23
24
-
@doc("Namespaced identifier")
24
+
/** Namespaced identifier */
25
25
nsid?: nsid;
26
26
27
-
@doc("Timestamp identifier")
27
+
/** Timestamp identifier */
28
28
tid?: tid;
29
29
30
-
@doc("Record key (any syntax)")
30
+
/** Record key (any syntax) */
31
31
recordKey?: recordKey;
32
32
33
-
@doc("Generic URI (RFC 3986)")
33
+
/** Generic URI (RFC 3986) */
34
34
uri?: uri;
35
35
36
-
@doc("IETF BCP 47 language tag")
36
+
/** IETF BCP 47 language tag */
37
37
language?: language;
38
38
}
39
39
}
+2
-2
packages/emitter/test/spec/basic/input/com/example/subscribeRecords.tsp
+2
-2
packages/emitter/test/spec/basic/input/com/example/subscribeRecords.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace com.example.subscribeRecords {
4
-
@doc("Subscribe to record updates")
4
+
/** Subscribe to record updates */
5
5
@subscription
6
6
op main(
7
-
@doc("Optional cursor for resuming")
7
+
/** Optional cursor for resuming */
8
8
cursor?: integer
9
9
): (Record | Delete);
10
10
+4
-4
packages/emitter/test/spec/basic/input/com/example/subscriptionWithErrors.tsp
+4
-4
packages/emitter/test/spec/basic/input/com/example/subscriptionWithErrors.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace com.example.subscriptionWithErrors {
4
-
@doc("Subscription with error definitions")
4
+
/** Subscription with error definitions */
5
5
@subscription
6
6
@errors(ConsumerTooSlow, InvalidCursor)
7
7
op main(
8
-
@doc("Optional cursor for resuming")
8
+
/** Optional cursor for resuming */
9
9
cursor?: integer
10
10
): (Event | Status | Info);
11
11
···
25
25
message?: string;
26
26
}
27
27
28
-
@doc("Indicates the consumer is not keeping up with the event stream")
28
+
/** Indicates the consumer is not keeping up with the event stream */
29
29
model ConsumerTooSlow {}
30
30
31
-
@doc("The provided cursor is invalid or expired")
31
+
/** The provided cursor is invalid or expired */
32
32
model InvalidCursor {}
33
33
}
+1
-1
packages/emitter/test/spec/basic/input/com/example/tidRecord.tsp
+1
-1
packages/emitter/test/spec/basic/input/com/example/tidRecord.tsp
+4
-4
packages/emitter/test/spec/basic/input/com/example/tokens.tsp
+4
-4
packages/emitter/test/spec/basic/input/com/example/tokens.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace com.example.tokens {
4
-
@doc("Token usage example")
4
+
/** Token usage example */
5
5
model Main {
6
6
@required status: Active;
7
7
}
8
8
9
-
@doc("Indicates an active state")
9
+
/** Indicates an active state */
10
10
@token
11
11
model Active {}
12
12
13
-
@doc("Indicates an inactive state")
13
+
/** Indicates an inactive state */
14
14
@token
15
15
model Inactive {}
16
16
17
-
@doc("Indicates a pending state")
17
+
/** Indicates a pending state */
18
18
@token
19
19
model Pending {}
20
20
}
+2
-2
packages/emitter/test/spec/basic/input/com/example/unionClosed.tsp
+2
-2
packages/emitter/test/spec/basic/input/com/example/unionClosed.tsp
+2
-2
packages/emitter/test/spec/basic/input/com/example/unionEmpty.tsp
+2
-2
packages/emitter/test/spec/basic/input/com/example/unionEmpty.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace com.example.unionEmpty {
4
-
@doc("Empty open union (similar to unknown but requires $type)")
4
+
/** Empty open union (similar to unknown but requires $type) */
5
5
model Main {
6
-
@doc("Empty open union - any object with $type allowed")
6
+
/** Empty open union - any object with $type allowed */
7
7
data?: (never | unknown);
8
8
}
9
9
}
+2
-2
packages/emitter/test/spec/basic/input/com/example/unionOpen.tsp
+2
-2
packages/emitter/test/spec/basic/input/com/example/unionOpen.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace com.example.unionOpen {
4
-
@doc("Open union example (default)")
4
+
/** Open union example (default) */
5
5
model Main {
6
-
@doc("Open union - more variants can be added in future")
6
+
/** Open union - more variants can be added in future */
7
7
@required
8
8
item: TypeA | TypeB | TypeC | unknown;
9
9
}
-22
packages/emitter/test/spec/basic/input/com/example/unionWithTokens.tsp
-22
packages/emitter/test/spec/basic/input/com/example/unionWithTokens.tsp
···
1
-
import "@typelex/emitter";
2
-
3
-
namespace com.example.unionWithTokens {
4
-
@doc("Tests union with token references")
5
-
model Main {
6
-
@doc("Reason can be a known token or unknown type")
7
-
@required
8
-
reason: (ReasonSpam | ReasonViolation | ReasonMisleading | unknown);
9
-
}
10
-
11
-
@doc("Spam: frequent unwanted promotion")
12
-
@token
13
-
model ReasonSpam {}
14
-
15
-
@doc("Direct violation of rules")
16
-
@token
17
-
model ReasonViolation {}
18
-
19
-
@doc("Misleading or deceptive content")
20
-
@token
21
-
model ReasonMisleading {}
22
-
}
+3
-3
packages/emitter/test/spec/basic/input/com/example/unknown.tsp
+3
-3
packages/emitter/test/spec/basic/input/com/example/unknown.tsp
···
3
3
using TypeSpec.Reflection;
4
4
5
5
namespace com.example.`unknown` {
6
-
@doc("Unknown type usage")
6
+
/** Unknown type usage */
7
7
model Main {
8
-
@doc("Any object data without validation")
8
+
/** Any object data without validation */
9
9
metadata?: unknown;
10
10
11
-
@doc("Optional unknown field")
11
+
/** Optional unknown field */
12
12
optionalMetadata?: unknown;
13
13
}
14
14
}
+6
-6
packages/emitter/test/spec/basic/input/com/example/uriExamples.tsp
+6
-6
packages/emitter/test/spec/basic/input/com/example/uriExamples.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace com.example.uriExamples {
4
-
@doc("Various URI format examples")
4
+
/** Various URI format examples */
5
5
model Main {
6
-
@doc("AT protocol URI")
6
+
/** AT protocol URI */
7
7
atUri?: atUri;
8
8
9
-
@doc("Generic URI (https, did, ipfs, etc)")
9
+
/** Generic URI (https, did, ipfs, etc) */
10
10
genericUri?: uri;
11
11
12
-
@doc("Record key identifier")
12
+
/** Record key identifier */
13
13
recordKey?: recordKey;
14
14
15
-
@doc("Namespaced identifier")
15
+
/** Namespaced identifier */
16
16
nsid?: nsid;
17
17
18
-
@doc("Timestamp identifier")
18
+
/** Timestamp identifier */
19
19
tid?: tid;
20
20
}
21
21
}
+3
-3
packages/emitter/test/spec/basic/input/com/example/withErrors.tsp
+3
-3
packages/emitter/test/spec/basic/input/com/example/withErrors.tsp
···
1
1
import "@typelex/emitter";
2
2
3
3
namespace com.example.withErrors {
4
-
@doc("The provided value is invalid")
4
+
/** The provided value is invalid */
5
5
model InvalidValue {}
6
6
7
-
@doc("Too many requests")
7
+
/** Too many requests */
8
8
model RateLimitExceeded {}
9
9
10
10
model Unauthorized {}
11
11
12
-
@doc("Procedure with error definitions")
12
+
/** Procedure with error definitions */
13
13
@procedure
14
14
@errors(InvalidValue, RateLimitExceeded, Unauthorized)
15
15
op main(input: {
+21
packages/emitter/test/spec/basic/output/com/example/other.json
+21
packages/emitter/test/spec/basic/output/com/example/other.json
···
1
+
{
2
+
"lexicon": 1,
3
+
"id": "com.example.other",
4
+
"defs": {
5
+
"main": {
6
+
"type": "object",
7
+
"properties": {}
8
+
},
9
+
"someDef": {
10
+
"type": "object",
11
+
"required": [
12
+
"value"
13
+
],
14
+
"properties": {
15
+
"value": {
16
+
"type": "string"
17
+
}
18
+
}
19
+
}
20
+
}
21
+
}
-34
packages/emitter/test/spec/basic/output/com/example/unionWithTokens.json
-34
packages/emitter/test/spec/basic/output/com/example/unionWithTokens.json
···
1
-
{
2
-
"lexicon": 1,
3
-
"id": "com.example.unionWithTokens",
4
-
"defs": {
5
-
"main": {
6
-
"type": "object",
7
-
"description": "Tests union with token references",
8
-
"required": ["reason"],
9
-
"properties": {
10
-
"reason": {
11
-
"type": "union",
12
-
"description": "Reason can be a known token or unknown type",
13
-
"refs": [
14
-
"#reasonSpam",
15
-
"#reasonViolation",
16
-
"#reasonMisleading"
17
-
]
18
-
}
19
-
}
20
-
},
21
-
"reasonSpam": {
22
-
"type": "token",
23
-
"description": "Spam: frequent unwanted promotion"
24
-
},
25
-
"reasonViolation": {
26
-
"type": "token",
27
-
"description": "Direct violation of rules"
28
-
},
29
-
"reasonMisleading": {
30
-
"type": "token",
31
-
"description": "Misleading or deceptive content"
32
-
}
33
-
}
34
-
}
+8
packages/emitter/test/spec/external/input/test/external.tsp
+8
packages/emitter/test/spec/external/input/test/external.tsp
+7
packages/emitter/test/spec/external/input/test/normal.tsp
+7
packages/emitter/test/spec/external/input/test/normal.tsp
+14
packages/emitter/test/spec/external/output/test/normal.json
+14
packages/emitter/test/spec/external/output/test/normal.json
+32
-4
packages/emitter/test/spec.test.ts
+32
-4
packages/emitter/test/spec.test.ts
···
64
64
// Create a virtual main.tsp that imports all other files
65
65
const mainContent =
66
66
'import "@typelex/emitter";\n' +
67
-
tspFiles.map((f) => `import "./${f}";`).join("\n");
67
+
tspFiles.map((f) => `import "./${normalizePathToPosix(f)}";`).join("\n");
68
68
const filesWithMain = { ...inputFiles, "main.tsp": mainContent };
69
69
emitResult = await doEmit(filesWithMain, "main.tsp");
70
70
} else {
···
91
91
);
92
92
}
93
93
94
+
const normalizedExpectedPath = normalizePathToPosix(expectedPath);
95
+
94
96
assert.ok(
95
97
Object.prototype.hasOwnProperty.call(
96
98
emitResult.files,
97
-
expectedPath,
99
+
normalizedExpectedPath,
98
100
),
99
101
`Expected file ${expectedPath} was not produced`,
100
102
);
101
103
102
-
const actual = JSON.parse(emitResult.files[expectedPath]);
104
+
const actual = JSON.parse(emitResult.files[normalizedExpectedPath]);
103
105
const expected = JSON.parse(expectedFiles[expectedPath]);
104
106
assert.deepStrictEqual(actual, expected);
105
107
});
106
108
} else {
107
-
it.skip(`TODO: ${expectedPath} (add ${inputPath})`, function () {});
109
+
it(`should emit ${expectedPath}`, function () {
110
+
assert.fail(
111
+
`Expected output file ${expectedPath} has no corresponding input file ${inputPath}. ` +
112
+
`Either add the input file or remove the expected output.`
113
+
);
114
+
});
108
115
}
109
116
}
117
+
118
+
// Check for unexpected emitted files
119
+
it("should not emit unexpected files", function () {
120
+
const emittedFiles = Object.keys(emitResult.files).filter(f => f.endsWith(".json"));
121
+
const expectedPaths = Object.keys(expectedFiles)
122
+
.filter(f => f.endsWith(".json"))
123
+
.map(normalizePathToPosix);
124
+
125
+
const unexpected = emittedFiles.filter(f => !expectedPaths.includes(f));
126
+
127
+
if (unexpected.length > 0) {
128
+
assert.fail(
129
+
`Unexpected files were emitted: ${unexpected.join(", ")}. ` +
130
+
`Either add expected output files or ensure these should not be emitted.`
131
+
);
132
+
}
133
+
});
110
134
});
111
135
}
112
136
});
···
180
204
await walk(dir, "");
181
205
return result;
182
206
}
207
+
208
+
function normalizePathToPosix(thePath: string): string {
209
+
return thePath.replaceAll(path.sep, path.posix.sep);
210
+
}
+4
-4
packages/example/package.json
+4
-4
packages/example/package.json
···
4
4
"private": true,
5
5
"type": "module",
6
6
"scripts": {
7
-
"build": "pnpm run build:typelex && pnpm run build:codegen",
8
-
"build:typelex": "tsp compile typelex/main.tsp",
9
-
"build:codegen": "lex gen-server --yes ./src lexicon/app/example/*.json"
7
+
"build": "pnpm run build:lexicons && pnpm run build:codegen",
8
+
"build:lexicons": "typelex compile xyz.statusphere.*",
9
+
"build:codegen": "lex gen-server --yes ./src lexicons/xyz/statusphere/*.json"
10
10
},
11
11
"dependencies": {
12
12
"@atproto/lex-cli": "^0.9.5",
13
13
"@atproto/xrpc-server": "^0.9.5",
14
-
"@typespec/compiler": "^1.4.0",
14
+
"@typelex/cli": "workspace:*",
15
15
"@typelex/emitter": "workspace:*"
16
16
},
17
17
"devDependencies": {
+45
-6
packages/example/src/index.ts
+45
-6
packages/example/src/index.ts
···
10
10
createServer as createXrpcServer,
11
11
} from '@atproto/xrpc-server'
12
12
import { schemas } from './lexicons.js'
13
+
import * as XyzStatusphereGetStatuses from './types/xyz/statusphere/getStatuses.js'
14
+
import * as XyzStatusphereGetUser from './types/xyz/statusphere/getUser.js'
15
+
import * as XyzStatusphereSendStatus from './types/xyz/statusphere/sendStatus.js'
13
16
14
17
export function createServer(options?: XrpcOptions): Server {
15
18
return new Server(options)
···
17
20
18
21
export class Server {
19
22
xrpc: XrpcServer
20
-
app: AppNS
23
+
xyz: XyzNS
21
24
22
25
constructor(options?: XrpcOptions) {
23
26
this.xrpc = createXrpcServer(schemas, options)
24
-
this.app = new AppNS(this)
27
+
this.xyz = new XyzNS(this)
25
28
}
26
29
}
27
30
28
-
export class AppNS {
31
+
export class XyzNS {
29
32
_server: Server
30
-
example: AppExampleNS
33
+
statusphere: XyzStatusphereNS
31
34
32
35
constructor(server: Server) {
33
36
this._server = server
34
-
this.example = new AppExampleNS(server)
37
+
this.statusphere = new XyzStatusphereNS(server)
35
38
}
36
39
}
37
40
38
-
export class AppExampleNS {
41
+
export class XyzStatusphereNS {
39
42
_server: Server
40
43
41
44
constructor(server: Server) {
42
45
this._server = server
46
+
}
47
+
48
+
getStatuses<A extends Auth = void>(
49
+
cfg: MethodConfigOrHandler<
50
+
A,
51
+
XyzStatusphereGetStatuses.QueryParams,
52
+
XyzStatusphereGetStatuses.HandlerInput,
53
+
XyzStatusphereGetStatuses.HandlerOutput
54
+
>,
55
+
) {
56
+
const nsid = 'xyz.statusphere.getStatuses' // @ts-ignore
57
+
return this._server.xrpc.method(nsid, cfg)
58
+
}
59
+
60
+
getUser<A extends Auth = void>(
61
+
cfg: MethodConfigOrHandler<
62
+
A,
63
+
XyzStatusphereGetUser.QueryParams,
64
+
XyzStatusphereGetUser.HandlerInput,
65
+
XyzStatusphereGetUser.HandlerOutput
66
+
>,
67
+
) {
68
+
const nsid = 'xyz.statusphere.getUser' // @ts-ignore
69
+
return this._server.xrpc.method(nsid, cfg)
70
+
}
71
+
72
+
sendStatus<A extends Auth = void>(
73
+
cfg: MethodConfigOrHandler<
74
+
A,
75
+
XyzStatusphereSendStatus.QueryParams,
76
+
XyzStatusphereSendStatus.HandlerInput,
77
+
XyzStatusphereSendStatus.HandlerOutput
78
+
>,
79
+
) {
80
+
const nsid = 'xyz.statusphere.sendStatus' // @ts-ignore
81
+
return this._server.xrpc.method(nsid, cfg)
43
82
}
44
83
}
+100
-153
packages/example/src/lexicons.ts
+100
-153
packages/example/src/lexicons.ts
···
10
10
import { type $Typed, is$typed, maybe$typed } from './util.js'
11
11
12
12
export const schemaDict = {
13
-
AppExampleDefs: {
13
+
XyzStatusphereDefs: {
14
14
lexicon: 1,
15
-
id: 'app.example.defs',
15
+
id: 'xyz.statusphere.defs',
16
16
defs: {
17
-
postRef: {
17
+
statusView: {
18
18
type: 'object',
19
19
properties: {
20
20
uri: {
21
21
type: 'string',
22
-
description: 'AT URI of the post',
22
+
format: 'at-uri',
23
23
},
24
-
cid: {
24
+
status: {
25
25
type: 'string',
26
-
description: 'CID of the post',
26
+
maxLength: 32,
27
+
minLength: 1,
28
+
maxGraphemes: 1,
27
29
},
28
-
},
29
-
description: 'Reference to a post',
30
-
required: ['uri', 'cid'],
31
-
},
32
-
replyRef: {
33
-
type: 'object',
34
-
properties: {
35
-
root: {
36
-
type: 'ref',
37
-
ref: 'lex:app.example.defs#postRef',
38
-
description: 'Root post in the thread',
30
+
createdAt: {
31
+
type: 'string',
32
+
format: 'datetime',
39
33
},
40
-
parent: {
34
+
profile: {
41
35
type: 'ref',
42
-
ref: 'lex:app.example.defs#postRef',
43
-
description: 'Direct parent post being replied to',
36
+
ref: 'lex:xyz.statusphere.defs#profileView',
44
37
},
45
38
},
46
-
description: 'Reference to a parent post in a reply chain',
47
-
required: ['root', 'parent'],
39
+
required: ['uri', 'status', 'createdAt', 'profile'],
48
40
},
49
-
entity: {
41
+
profileView: {
50
42
type: 'object',
51
43
properties: {
52
-
start: {
53
-
type: 'integer',
54
-
description: 'Start index in text',
55
-
},
56
-
end: {
57
-
type: 'integer',
58
-
description: 'End index in text',
59
-
},
60
-
type: {
44
+
did: {
61
45
type: 'string',
62
-
description: 'Entity type',
46
+
format: 'did',
63
47
},
64
-
value: {
48
+
handle: {
65
49
type: 'string',
66
-
description: 'Entity value (handle, URL, or tag)',
50
+
format: 'handle',
67
51
},
68
52
},
69
-
description: 'Text entity (mention, link, or tag)',
70
-
required: ['start', 'end', 'type', 'value'],
71
-
},
72
-
notificationType: {
73
-
type: 'string',
74
-
knownValues: ['like', 'repost', 'follow', 'mention', 'reply'],
75
-
description: 'Type of notification',
53
+
required: ['did', 'handle'],
76
54
},
77
55
},
78
56
},
79
-
AppExampleFollow: {
57
+
XyzStatusphereGetStatuses: {
80
58
lexicon: 1,
81
-
id: 'app.example.follow',
59
+
id: 'xyz.statusphere.getStatuses',
82
60
defs: {
83
61
main: {
84
-
type: 'record',
85
-
key: 'tid',
86
-
record: {
87
-
type: 'object',
62
+
type: 'query',
63
+
description: 'Get a list of the most recent statuses on the network.',
64
+
parameters: {
65
+
type: 'params',
88
66
properties: {
89
-
subject: {
90
-
type: 'string',
91
-
description: 'DID of the account being followed',
92
-
},
93
-
createdAt: {
94
-
type: 'string',
95
-
format: 'datetime',
96
-
description: 'When the follow was created',
67
+
limit: {
68
+
type: 'integer',
69
+
minimum: 1,
70
+
maximum: 100,
71
+
default: 50,
97
72
},
98
73
},
99
-
required: ['subject', 'createdAt'],
100
74
},
101
-
description: 'A follow relationship',
102
-
},
103
-
},
104
-
},
105
-
AppExampleLike: {
106
-
lexicon: 1,
107
-
id: 'app.example.like',
108
-
defs: {
109
-
main: {
110
-
type: 'record',
111
-
key: 'tid',
112
-
record: {
113
-
type: 'object',
114
-
properties: {
115
-
subject: {
116
-
type: 'ref',
117
-
ref: 'lex:app.example.defs#postRef',
118
-
description: 'Post being liked',
75
+
output: {
76
+
encoding: 'application/json',
77
+
schema: {
78
+
type: 'object',
79
+
properties: {
80
+
statuses: {
81
+
type: 'array',
82
+
items: {
83
+
type: 'ref',
84
+
ref: 'lex:xyz.statusphere.defs#statusView',
85
+
},
86
+
},
119
87
},
120
-
createdAt: {
121
-
type: 'string',
122
-
format: 'datetime',
123
-
description: 'When the like was created',
124
-
},
88
+
required: ['statuses'],
125
89
},
126
-
required: ['subject', 'createdAt'],
127
90
},
128
-
description: 'A like on a post',
129
91
},
130
92
},
131
93
},
132
-
AppExamplePost: {
94
+
XyzStatusphereGetUser: {
133
95
lexicon: 1,
134
-
id: 'app.example.post',
96
+
id: 'xyz.statusphere.getUser',
135
97
defs: {
136
98
main: {
137
-
type: 'record',
138
-
key: 'tid',
139
-
record: {
140
-
type: 'object',
141
-
properties: {
142
-
text: {
143
-
type: 'string',
144
-
description: 'Post text content',
145
-
},
146
-
createdAt: {
147
-
type: 'string',
148
-
format: 'datetime',
149
-
description: 'Creation timestamp',
150
-
},
151
-
langs: {
152
-
type: 'array',
153
-
items: {
154
-
type: 'string',
99
+
type: 'query',
100
+
description: "Get the current user's profile and status.",
101
+
output: {
102
+
encoding: 'application/json',
103
+
schema: {
104
+
type: 'object',
105
+
properties: {
106
+
profile: {
107
+
type: 'ref',
108
+
ref: 'lex:app.bsky.actor.defs#profileView',
155
109
},
156
-
description: 'Languages the post is written in',
157
-
},
158
-
entities: {
159
-
type: 'array',
160
-
items: {
110
+
status: {
161
111
type: 'ref',
162
-
ref: 'lex:app.example.defs#entity',
112
+
ref: 'lex:xyz.statusphere.defs#statusView',
163
113
},
164
-
description: 'Referenced entities in the post',
165
114
},
166
-
reply: {
167
-
type: 'ref',
168
-
ref: 'lex:app.example.defs#replyRef',
169
-
description: 'Post the user is replying to',
170
-
},
115
+
required: ['profile'],
171
116
},
172
-
required: ['text', 'createdAt'],
173
117
},
174
-
description: 'A post in the feed',
175
118
},
176
119
},
177
120
},
178
-
AppExampleProfile: {
121
+
XyzStatusphereSendStatus: {
179
122
lexicon: 1,
180
-
id: 'app.example.profile',
123
+
id: 'xyz.statusphere.sendStatus',
181
124
defs: {
182
125
main: {
183
-
type: 'record',
184
-
key: 'self',
185
-
record: {
186
-
type: 'object',
187
-
properties: {
188
-
displayName: {
189
-
type: 'string',
190
-
description: 'Display name',
191
-
},
192
-
description: {
193
-
type: 'string',
194
-
description: 'Profile description',
126
+
type: 'procedure',
127
+
description: 'Send a status into the ATmosphere.',
128
+
input: {
129
+
encoding: 'application/json',
130
+
schema: {
131
+
type: 'object',
132
+
properties: {
133
+
status: {
134
+
type: 'string',
135
+
maxLength: 32,
136
+
minLength: 1,
137
+
maxGraphemes: 1,
138
+
},
195
139
},
196
-
avatar: {
197
-
type: 'string',
198
-
description: 'Profile avatar image',
140
+
required: ['status'],
141
+
},
142
+
},
143
+
output: {
144
+
encoding: 'application/json',
145
+
schema: {
146
+
type: 'object',
147
+
properties: {
148
+
status: {
149
+
type: 'ref',
150
+
ref: 'lex:xyz.statusphere.defs#statusView',
151
+
},
199
152
},
200
-
banner: {
201
-
type: 'string',
202
-
description: 'Profile banner image',
203
-
},
153
+
required: ['status'],
204
154
},
205
155
},
206
-
description: 'User profile information',
207
156
},
208
157
},
209
158
},
210
-
AppExampleRepost: {
159
+
XyzStatusphereStatus: {
211
160
lexicon: 1,
212
-
id: 'app.example.repost',
161
+
id: 'xyz.statusphere.status',
213
162
defs: {
214
163
main: {
215
164
type: 'record',
···
217
166
record: {
218
167
type: 'object',
219
168
properties: {
220
-
subject: {
221
-
type: 'ref',
222
-
ref: 'lex:app.example.defs#postRef',
223
-
description: 'Post being reposted',
169
+
status: {
170
+
type: 'string',
171
+
maxLength: 32,
172
+
minLength: 1,
173
+
maxGraphemes: 1,
224
174
},
225
175
createdAt: {
226
176
type: 'string',
227
177
format: 'datetime',
228
-
description: 'When the repost was created',
229
178
},
230
179
},
231
-
required: ['subject', 'createdAt'],
180
+
required: ['status', 'createdAt'],
232
181
},
233
-
description: 'A repost of another post',
234
182
},
235
183
},
236
184
},
···
267
215
}
268
216
269
217
export const ids = {
270
-
AppExampleDefs: 'app.example.defs',
271
-
AppExampleFollow: 'app.example.follow',
272
-
AppExampleLike: 'app.example.like',
273
-
AppExamplePost: 'app.example.post',
274
-
AppExampleProfile: 'app.example.profile',
275
-
AppExampleRepost: 'app.example.repost',
218
+
XyzStatusphereDefs: 'xyz.statusphere.defs',
219
+
XyzStatusphereGetStatuses: 'xyz.statusphere.getStatuses',
220
+
XyzStatusphereGetUser: 'xyz.statusphere.getUser',
221
+
XyzStatusphereSendStatus: 'xyz.statusphere.sendStatus',
222
+
XyzStatusphereStatus: 'xyz.statusphere.status',
276
223
} as const
-79
packages/example/src/types/app/example/defs.ts
-79
packages/example/src/types/app/example/defs.ts
···
1
-
/**
2
-
* GENERATED CODE - DO NOT MODIFY
3
-
*/
4
-
import { type ValidationResult, BlobRef } from '@atproto/lexicon'
5
-
import { CID } from 'multiformats/cid'
6
-
import { validate as _validate } from '../../../lexicons'
7
-
import { type $Typed, is$typed as _is$typed, type OmitKey } from '../../../util'
8
-
9
-
const is$typed = _is$typed,
10
-
validate = _validate
11
-
const id = 'app.example.defs'
12
-
13
-
/** Reference to a post */
14
-
export interface PostRef {
15
-
$type?: 'app.example.defs#postRef'
16
-
/** AT URI of the post */
17
-
uri: string
18
-
/** CID of the post */
19
-
cid: string
20
-
}
21
-
22
-
const hashPostRef = 'postRef'
23
-
24
-
export function isPostRef<V>(v: V) {
25
-
return is$typed(v, id, hashPostRef)
26
-
}
27
-
28
-
export function validatePostRef<V>(v: V) {
29
-
return validate<PostRef & V>(v, id, hashPostRef)
30
-
}
31
-
32
-
/** Reference to a parent post in a reply chain */
33
-
export interface ReplyRef {
34
-
$type?: 'app.example.defs#replyRef'
35
-
root: PostRef
36
-
parent: PostRef
37
-
}
38
-
39
-
const hashReplyRef = 'replyRef'
40
-
41
-
export function isReplyRef<V>(v: V) {
42
-
return is$typed(v, id, hashReplyRef)
43
-
}
44
-
45
-
export function validateReplyRef<V>(v: V) {
46
-
return validate<ReplyRef & V>(v, id, hashReplyRef)
47
-
}
48
-
49
-
/** Text entity (mention, link, or tag) */
50
-
export interface Entity {
51
-
$type?: 'app.example.defs#entity'
52
-
/** Start index in text */
53
-
start: number
54
-
/** End index in text */
55
-
end: number
56
-
/** Entity type */
57
-
type: string
58
-
/** Entity value (handle, URL, or tag) */
59
-
value: string
60
-
}
61
-
62
-
const hashEntity = 'entity'
63
-
64
-
export function isEntity<V>(v: V) {
65
-
return is$typed(v, id, hashEntity)
66
-
}
67
-
68
-
export function validateEntity<V>(v: V) {
69
-
return validate<Entity & V>(v, id, hashEntity)
70
-
}
71
-
72
-
/** Type of notification */
73
-
export type NotificationType =
74
-
| 'like'
75
-
| 'repost'
76
-
| 'follow'
77
-
| 'mention'
78
-
| 'reply'
79
-
| (string & {})
-30
packages/example/src/types/app/example/follow.ts
-30
packages/example/src/types/app/example/follow.ts
···
1
-
/**
2
-
* GENERATED CODE - DO NOT MODIFY
3
-
*/
4
-
import { type ValidationResult, BlobRef } from '@atproto/lexicon'
5
-
import { CID } from 'multiformats/cid'
6
-
import { validate as _validate } from '../../../lexicons'
7
-
import { type $Typed, is$typed as _is$typed, type OmitKey } from '../../../util'
8
-
9
-
const is$typed = _is$typed,
10
-
validate = _validate
11
-
const id = 'app.example.follow'
12
-
13
-
export interface Record {
14
-
$type: 'app.example.follow'
15
-
/** DID of the account being followed */
16
-
subject: string
17
-
/** When the follow was created */
18
-
createdAt: string
19
-
[k: string]: unknown
20
-
}
21
-
22
-
const hashRecord = 'main'
23
-
24
-
export function isRecord<V>(v: V) {
25
-
return is$typed(v, id, hashRecord)
26
-
}
27
-
28
-
export function validateRecord<V>(v: V) {
29
-
return validate<Record & V>(v, id, hashRecord, true)
30
-
}
-30
packages/example/src/types/app/example/like.ts
-30
packages/example/src/types/app/example/like.ts
···
1
-
/**
2
-
* GENERATED CODE - DO NOT MODIFY
3
-
*/
4
-
import { type ValidationResult, BlobRef } from '@atproto/lexicon'
5
-
import { CID } from 'multiformats/cid'
6
-
import { validate as _validate } from '../../../lexicons'
7
-
import { type $Typed, is$typed as _is$typed, type OmitKey } from '../../../util'
8
-
import type * as AppExampleDefs from './defs.js'
9
-
10
-
const is$typed = _is$typed,
11
-
validate = _validate
12
-
const id = 'app.example.like'
13
-
14
-
export interface Record {
15
-
$type: 'app.example.like'
16
-
subject: AppExampleDefs.PostRef
17
-
/** When the like was created */
18
-
createdAt: string
19
-
[k: string]: unknown
20
-
}
21
-
22
-
const hashRecord = 'main'
23
-
24
-
export function isRecord<V>(v: V) {
25
-
return is$typed(v, id, hashRecord)
26
-
}
27
-
28
-
export function validateRecord<V>(v: V) {
29
-
return validate<Record & V>(v, id, hashRecord, true)
30
-
}
-36
packages/example/src/types/app/example/post.ts
-36
packages/example/src/types/app/example/post.ts
···
1
-
/**
2
-
* GENERATED CODE - DO NOT MODIFY
3
-
*/
4
-
import { type ValidationResult, BlobRef } from '@atproto/lexicon'
5
-
import { CID } from 'multiformats/cid'
6
-
import { validate as _validate } from '../../../lexicons'
7
-
import { type $Typed, is$typed as _is$typed, type OmitKey } from '../../../util'
8
-
import type * as AppExampleDefs from './defs.js'
9
-
10
-
const is$typed = _is$typed,
11
-
validate = _validate
12
-
const id = 'app.example.post'
13
-
14
-
export interface Record {
15
-
$type: 'app.example.post'
16
-
/** Post text content */
17
-
text: string
18
-
/** Creation timestamp */
19
-
createdAt: string
20
-
/** Languages the post is written in */
21
-
langs?: string[]
22
-
/** Referenced entities in the post */
23
-
entities?: AppExampleDefs.Entity[]
24
-
reply?: AppExampleDefs.ReplyRef
25
-
[k: string]: unknown
26
-
}
27
-
28
-
const hashRecord = 'main'
29
-
30
-
export function isRecord<V>(v: V) {
31
-
return is$typed(v, id, hashRecord)
32
-
}
33
-
34
-
export function validateRecord<V>(v: V) {
35
-
return validate<Record & V>(v, id, hashRecord, true)
36
-
}
-34
packages/example/src/types/app/example/profile.ts
-34
packages/example/src/types/app/example/profile.ts
···
1
-
/**
2
-
* GENERATED CODE - DO NOT MODIFY
3
-
*/
4
-
import { type ValidationResult, BlobRef } from '@atproto/lexicon'
5
-
import { CID } from 'multiformats/cid'
6
-
import { validate as _validate } from '../../../lexicons'
7
-
import { type $Typed, is$typed as _is$typed, type OmitKey } from '../../../util'
8
-
9
-
const is$typed = _is$typed,
10
-
validate = _validate
11
-
const id = 'app.example.profile'
12
-
13
-
export interface Record {
14
-
$type: 'app.example.profile'
15
-
/** Display name */
16
-
displayName?: string
17
-
/** Profile description */
18
-
description?: string
19
-
/** Profile avatar image */
20
-
avatar?: string
21
-
/** Profile banner image */
22
-
banner?: string
23
-
[k: string]: unknown
24
-
}
25
-
26
-
const hashRecord = 'main'
27
-
28
-
export function isRecord<V>(v: V) {
29
-
return is$typed(v, id, hashRecord)
30
-
}
31
-
32
-
export function validateRecord<V>(v: V) {
33
-
return validate<Record & V>(v, id, hashRecord, true)
34
-
}
-30
packages/example/src/types/app/example/repost.ts
-30
packages/example/src/types/app/example/repost.ts
···
1
-
/**
2
-
* GENERATED CODE - DO NOT MODIFY
3
-
*/
4
-
import { type ValidationResult, BlobRef } from '@atproto/lexicon'
5
-
import { CID } from 'multiformats/cid'
6
-
import { validate as _validate } from '../../../lexicons'
7
-
import { type $Typed, is$typed as _is$typed, type OmitKey } from '../../../util'
8
-
import type * as AppExampleDefs from './defs.js'
9
-
10
-
const is$typed = _is$typed,
11
-
validate = _validate
12
-
const id = 'app.example.repost'
13
-
14
-
export interface Record {
15
-
$type: 'app.example.repost'
16
-
subject: AppExampleDefs.PostRef
17
-
/** When the repost was created */
18
-
createdAt: string
19
-
[k: string]: unknown
20
-
}
21
-
22
-
const hashRecord = 'main'
23
-
24
-
export function isRecord<V>(v: V) {
25
-
return is$typed(v, id, hashRecord)
26
-
}
27
-
28
-
export function validateRecord<V>(v: V) {
29
-
return validate<Record & V>(v, id, hashRecord, true)
30
-
}
+45
packages/example/src/types/xyz/statusphere/defs.ts
+45
packages/example/src/types/xyz/statusphere/defs.ts
···
1
+
/**
2
+
* GENERATED CODE - DO NOT MODIFY
3
+
*/
4
+
import { type ValidationResult, BlobRef } from '@atproto/lexicon'
5
+
import { CID } from 'multiformats/cid'
6
+
import { validate as _validate } from '../../../lexicons'
7
+
import { type $Typed, is$typed as _is$typed, type OmitKey } from '../../../util'
8
+
9
+
const is$typed = _is$typed,
10
+
validate = _validate
11
+
const id = 'xyz.statusphere.defs'
12
+
13
+
export interface StatusView {
14
+
$type?: 'xyz.statusphere.defs#statusView'
15
+
uri: string
16
+
status: string
17
+
createdAt: string
18
+
profile: ProfileView
19
+
}
20
+
21
+
const hashStatusView = 'statusView'
22
+
23
+
export function isStatusView<V>(v: V) {
24
+
return is$typed(v, id, hashStatusView)
25
+
}
26
+
27
+
export function validateStatusView<V>(v: V) {
28
+
return validate<StatusView & V>(v, id, hashStatusView)
29
+
}
30
+
31
+
export interface ProfileView {
32
+
$type?: 'xyz.statusphere.defs#profileView'
33
+
did: string
34
+
handle: string
35
+
}
36
+
37
+
const hashProfileView = 'profileView'
38
+
39
+
export function isProfileView<V>(v: V) {
40
+
return is$typed(v, id, hashProfileView)
41
+
}
42
+
43
+
export function validateProfileView<V>(v: V) {
44
+
return validate<ProfileView & V>(v, id, hashProfileView)
45
+
}
+36
packages/example/src/types/xyz/statusphere/getStatuses.ts
+36
packages/example/src/types/xyz/statusphere/getStatuses.ts
···
1
+
/**
2
+
* GENERATED CODE - DO NOT MODIFY
3
+
*/
4
+
import { type ValidationResult, BlobRef } from '@atproto/lexicon'
5
+
import { CID } from 'multiformats/cid'
6
+
import { validate as _validate } from '../../../lexicons'
7
+
import { type $Typed, is$typed as _is$typed, type OmitKey } from '../../../util'
8
+
import type * as XyzStatusphereDefs from './defs.js'
9
+
10
+
const is$typed = _is$typed,
11
+
validate = _validate
12
+
const id = 'xyz.statusphere.getStatuses'
13
+
14
+
export type QueryParams = {
15
+
limit: number
16
+
}
17
+
export type InputSchema = undefined
18
+
19
+
export interface OutputSchema {
20
+
statuses: XyzStatusphereDefs.StatusView[]
21
+
}
22
+
23
+
export type HandlerInput = void
24
+
25
+
export interface HandlerSuccess {
26
+
encoding: 'application/json'
27
+
body: OutputSchema
28
+
headers?: { [key: string]: string }
29
+
}
30
+
31
+
export interface HandlerError {
32
+
status: number
33
+
message?: string
34
+
}
35
+
36
+
export type HandlerOutput = HandlerError | HandlerSuccess
+36
packages/example/src/types/xyz/statusphere/getUser.ts
+36
packages/example/src/types/xyz/statusphere/getUser.ts
···
1
+
/**
2
+
* GENERATED CODE - DO NOT MODIFY
3
+
*/
4
+
import { type ValidationResult, BlobRef } from '@atproto/lexicon'
5
+
import { CID } from 'multiformats/cid'
6
+
import { validate as _validate } from '../../../lexicons'
7
+
import { type $Typed, is$typed as _is$typed, type OmitKey } from '../../../util'
8
+
import type * as AppBskyActorDefs from '../../app/bsky/actor/defs.js'
9
+
import type * as XyzStatusphereDefs from './defs.js'
10
+
11
+
const is$typed = _is$typed,
12
+
validate = _validate
13
+
const id = 'xyz.statusphere.getUser'
14
+
15
+
export type QueryParams = {}
16
+
export type InputSchema = undefined
17
+
18
+
export interface OutputSchema {
19
+
profile: AppBskyActorDefs.ProfileView
20
+
status?: XyzStatusphereDefs.StatusView
21
+
}
22
+
23
+
export type HandlerInput = void
24
+
25
+
export interface HandlerSuccess {
26
+
encoding: 'application/json'
27
+
body: OutputSchema
28
+
headers?: { [key: string]: string }
29
+
}
30
+
31
+
export interface HandlerError {
32
+
status: number
33
+
message?: string
34
+
}
35
+
36
+
export type HandlerOutput = HandlerError | HandlerSuccess
+40
packages/example/src/types/xyz/statusphere/sendStatus.ts
+40
packages/example/src/types/xyz/statusphere/sendStatus.ts
···
1
+
/**
2
+
* GENERATED CODE - DO NOT MODIFY
3
+
*/
4
+
import { type ValidationResult, BlobRef } from '@atproto/lexicon'
5
+
import { CID } from 'multiformats/cid'
6
+
import { validate as _validate } from '../../../lexicons'
7
+
import { type $Typed, is$typed as _is$typed, type OmitKey } from '../../../util'
8
+
import type * as XyzStatusphereDefs from './defs.js'
9
+
10
+
const is$typed = _is$typed,
11
+
validate = _validate
12
+
const id = 'xyz.statusphere.sendStatus'
13
+
14
+
export type QueryParams = {}
15
+
16
+
export interface InputSchema {
17
+
status: string
18
+
}
19
+
20
+
export interface OutputSchema {
21
+
status: XyzStatusphereDefs.StatusView
22
+
}
23
+
24
+
export interface HandlerInput {
25
+
encoding: 'application/json'
26
+
body: InputSchema
27
+
}
28
+
29
+
export interface HandlerSuccess {
30
+
encoding: 'application/json'
31
+
body: OutputSchema
32
+
headers?: { [key: string]: string }
33
+
}
34
+
35
+
export interface HandlerError {
36
+
status: number
37
+
message?: string
38
+
}
39
+
40
+
export type HandlerOutput = HandlerError | HandlerSuccess
+28
packages/example/src/types/xyz/statusphere/status.ts
+28
packages/example/src/types/xyz/statusphere/status.ts
···
1
+
/**
2
+
* GENERATED CODE - DO NOT MODIFY
3
+
*/
4
+
import { type ValidationResult, BlobRef } from '@atproto/lexicon'
5
+
import { CID } from 'multiformats/cid'
6
+
import { validate as _validate } from '../../../lexicons'
7
+
import { type $Typed, is$typed as _is$typed, type OmitKey } from '../../../util'
8
+
9
+
const is$typed = _is$typed,
10
+
validate = _validate
11
+
const id = 'xyz.statusphere.status'
12
+
13
+
export interface Record {
14
+
$type: 'xyz.statusphere.status'
15
+
status: string
16
+
createdAt: string
17
+
[k: string]: unknown
18
+
}
19
+
20
+
const hashRecord = 'main'
21
+
22
+
export function isRecord<V>(v: V) {
23
+
return is$typed(v, id, hashRecord)
24
+
}
25
+
26
+
export function validateRecord<V>(v: V) {
27
+
return validate<Record & V>(v, id, hashRecord, true)
28
+
}
-5
packages/example/tspconfig.yaml
-5
packages/example/tspconfig.yaml
+235
packages/example/typelex/externals.tsp
+235
packages/example/typelex/externals.tsp
···
1
+
import "@typelex/emitter";
2
+
3
+
// Generated by typelex
4
+
// This file is auto-generated. Do not edit manually.
5
+
6
+
@external
7
+
namespace app.bsky.actor.defs {
8
+
model AdultContentPref { }
9
+
model BskyAppProgressGuide { }
10
+
model BskyAppStatePref { }
11
+
model ContentLabelPref { }
12
+
model FeedViewPref { }
13
+
model HiddenPostsPref { }
14
+
model InterestsPref { }
15
+
model KnownFollowers { }
16
+
model LabelerPrefItem { }
17
+
model LabelersPref { }
18
+
model MutedWord { }
19
+
model MutedWordsPref { }
20
+
model MutedWordTarget { }
21
+
model Nux { }
22
+
model PersonalDetailsPref { }
23
+
model PostInteractionSettingsPref { }
24
+
model ProfileAssociated { }
25
+
model ProfileAssociatedChat { }
26
+
model ProfileView { }
27
+
model ProfileViewBasic { }
28
+
model ProfileViewDetailed { }
29
+
model SavedFeed { }
30
+
model SavedFeedsPref { }
31
+
model SavedFeedsPrefV2 { }
32
+
model ThreadViewPref { }
33
+
model ViewerState { }
34
+
}
35
+
36
+
@external
37
+
namespace app.bsky.actor.profile {
38
+
model Main { }
39
+
}
40
+
41
+
@external
42
+
namespace app.bsky.embed.defs {
43
+
model AspectRatio { }
44
+
}
45
+
46
+
@external
47
+
namespace app.bsky.embed.external {
48
+
model External { }
49
+
model Main { }
50
+
model View { }
51
+
model ViewExternal { }
52
+
}
53
+
54
+
@external
55
+
namespace app.bsky.embed.images {
56
+
model Image { }
57
+
model Main { }
58
+
model View { }
59
+
model ViewImage { }
60
+
}
61
+
62
+
@external
63
+
namespace app.bsky.embed.`record` {
64
+
model Main { }
65
+
model View { }
66
+
model ViewBlocked { }
67
+
model ViewDetached { }
68
+
model ViewNotFound { }
69
+
model ViewRecord { }
70
+
}
71
+
72
+
@external
73
+
namespace app.bsky.embed.recordWithMedia {
74
+
model Main { }
75
+
model View { }
76
+
}
77
+
78
+
@external
79
+
namespace app.bsky.embed.video {
80
+
model Caption { }
81
+
model Main { }
82
+
model View { }
83
+
}
84
+
85
+
@external
86
+
namespace app.bsky.feed.defs {
87
+
model BlockedAuthor { }
88
+
model BlockedPost { }
89
+
@token model ClickthroughAuthor { }
90
+
@token model ClickthroughEmbed { }
91
+
@token model ClickthroughItem { }
92
+
@token model ClickthroughReposter { }
93
+
@token model ContentModeUnspecified { }
94
+
@token model ContentModeVideo { }
95
+
model FeedViewPost { }
96
+
model GeneratorView { }
97
+
model GeneratorViewerState { }
98
+
model Interaction { }
99
+
@token model InteractionLike { }
100
+
@token model InteractionQuote { }
101
+
@token model InteractionReply { }
102
+
@token model InteractionRepost { }
103
+
@token model InteractionSeen { }
104
+
@token model InteractionShare { }
105
+
model NotFoundPost { }
106
+
model PostView { }
107
+
model ReasonPin { }
108
+
model ReasonRepost { }
109
+
model ReplyRef { }
110
+
@token model RequestLess { }
111
+
@token model RequestMore { }
112
+
model SkeletonFeedPost { }
113
+
model SkeletonReasonPin { }
114
+
model SkeletonReasonRepost { }
115
+
model ThreadContext { }
116
+
model ThreadgateView { }
117
+
model ThreadViewPost { }
118
+
model ViewerState { }
119
+
}
120
+
121
+
@external
122
+
namespace app.bsky.feed.postgate {
123
+
model DisableRule { }
124
+
model Main { }
125
+
}
126
+
127
+
@external
128
+
namespace app.bsky.feed.threadgate {
129
+
model FollowerRule { }
130
+
model FollowingRule { }
131
+
model ListRule { }
132
+
model Main { }
133
+
model MentionRule { }
134
+
}
135
+
136
+
@external
137
+
namespace app.bsky.graph.defs {
138
+
@token model Curatelist { }
139
+
model ListItemView { }
140
+
model ListPurpose { }
141
+
model ListView { }
142
+
model ListViewBasic { }
143
+
model ListViewerState { }
144
+
@token model Modlist { }
145
+
model NotFoundActor { }
146
+
@token model Referencelist { }
147
+
model Relationship { }
148
+
model StarterPackView { }
149
+
model StarterPackViewBasic { }
150
+
}
151
+
152
+
@external
153
+
namespace app.bsky.labeler.defs {
154
+
model LabelerPolicies { }
155
+
model LabelerView { }
156
+
model LabelerViewDetailed { }
157
+
model LabelerViewerState { }
158
+
}
159
+
160
+
@external
161
+
namespace app.bsky.richtext.facet {
162
+
model ByteSlice { }
163
+
model Link { }
164
+
model Main { }
165
+
model Mention { }
166
+
model Tag { }
167
+
}
168
+
169
+
@external
170
+
namespace com.atproto.label.defs {
171
+
model Label { }
172
+
model LabelValue { }
173
+
model LabelValueDefinition { }
174
+
model LabelValueDefinitionStrings { }
175
+
model SelfLabel { }
176
+
model SelfLabels { }
177
+
}
178
+
179
+
@external
180
+
namespace com.atproto.repo.applyWrites {
181
+
model Create { }
182
+
model CreateResult { }
183
+
model Delete { }
184
+
model DeleteResult { }
185
+
model Update { }
186
+
model UpdateResult { }
187
+
}
188
+
189
+
@external
190
+
namespace com.atproto.repo.createRecord {
191
+
}
192
+
193
+
@external
194
+
namespace com.atproto.repo.defs {
195
+
model CommitMeta { }
196
+
}
197
+
198
+
@external
199
+
namespace com.atproto.repo.deleteRecord {
200
+
}
201
+
202
+
@external
203
+
namespace com.atproto.repo.describeRepo {
204
+
}
205
+
206
+
@external
207
+
namespace com.atproto.repo.getRecord {
208
+
}
209
+
210
+
@external
211
+
namespace com.atproto.repo.importRepo {
212
+
}
213
+
214
+
@external
215
+
namespace com.atproto.repo.listMissingBlobs {
216
+
model RecordBlob { }
217
+
}
218
+
219
+
@external
220
+
namespace com.atproto.repo.listRecords {
221
+
model Record { }
222
+
}
223
+
224
+
@external
225
+
namespace com.atproto.repo.putRecord {
226
+
}
227
+
228
+
@external
229
+
namespace com.atproto.repo.strongRef {
230
+
model Main { }
231
+
}
232
+
233
+
@external
234
+
namespace com.atproto.repo.uploadBlob {
235
+
}
+46
-122
packages/example/typelex/main.tsp
+46
-122
packages/example/typelex/main.tsp
···
1
1
import "@typelex/emitter";
2
-
3
-
// Example showing typelex as source of truth for atproto lexicons
4
-
5
-
// ============ Common Types ============
6
-
7
-
namespace app.example.defs {
8
-
@doc("Type of notification")
9
-
union notificationType {
10
-
string,
11
-
12
-
Like: "like",
13
-
Repost: "repost",
14
-
Follow: "follow",
15
-
Mention: "mention",
16
-
Reply: "reply",
17
-
}
18
-
19
-
@doc("Reference to a post")
20
-
model PostRef {
21
-
@doc("AT URI of the post")
22
-
@required
23
-
uri: string;
24
-
25
-
@doc("CID of the post")
26
-
@required
27
-
cid: string;
28
-
}
29
-
30
-
@doc("Reference to a parent post in a reply chain")
31
-
model ReplyRef {
32
-
@doc("Root post in the thread")
33
-
@required
34
-
root: PostRef;
35
-
36
-
@doc("Direct parent post being replied to")
37
-
@required
38
-
parent: PostRef;
39
-
}
40
-
41
-
@doc("Text entity (mention, link, or tag)")
42
-
model Entity {
43
-
@doc("Start index in text")
44
-
@required
45
-
start: int32;
2
+
import "./externals.tsp";
46
3
47
-
@doc("End index in text")
48
-
@required
49
-
end: int32;
4
+
namespace xyz.statusphere.defs {
5
+
model StatusView {
6
+
@required uri: atUri;
50
7
51
-
@doc("Entity type")
52
8
@required
53
-
type: string;
9
+
@minLength(1)
10
+
@maxGraphemes(1)
11
+
@maxLength(32)
12
+
status: string;
54
13
55
-
@doc("Entity value (handle, URL, or tag)")
56
-
@required
57
-
value: string;
14
+
@required createdAt: datetime;
15
+
@required profile: ProfileView;
58
16
}
59
-
}
60
17
61
-
// ============ Records ============
62
-
63
-
namespace app.example.post {
64
-
@rec("tid")
65
-
@doc("A post in the feed")
66
-
model Main {
67
-
@doc("Post text content")
68
-
@required
69
-
text: string;
70
-
71
-
@doc("Creation timestamp")
72
-
@required
73
-
createdAt: datetime;
74
-
75
-
@doc("Languages the post is written in")
76
-
langs?: string[];
77
-
78
-
@doc("Referenced entities in the post")
79
-
entities?: app.example.defs.Entity[];
80
-
81
-
@doc("Post the user is replying to")
82
-
reply?: app.example.defs.ReplyRef;
18
+
model ProfileView {
19
+
@required did: did;
20
+
@required handle: handle;
83
21
}
84
22
}
85
23
86
-
namespace app.example.follow {
24
+
namespace xyz.statusphere.status {
87
25
@rec("tid")
88
-
@doc("A follow relationship")
89
26
model Main {
90
-
@doc("DID of the account being followed")
91
27
@required
92
-
subject: string;
28
+
@minLength(1)
29
+
@maxGraphemes(1)
30
+
@maxLength(32)
31
+
status: string;
93
32
94
-
@doc("When the follow was created")
95
-
@required
96
-
createdAt: datetime;
33
+
@required createdAt: datetime;
97
34
}
98
35
}
99
36
100
-
namespace app.example.like {
101
-
@rec("tid")
102
-
@doc("A like on a post")
103
-
model Main {
104
-
@doc("Post being liked")
105
-
@required
106
-
subject: app.example.defs.PostRef;
107
-
108
-
@doc("When the like was created")
109
-
@required
110
-
createdAt: datetime;
111
-
}
37
+
namespace xyz.statusphere.sendStatus {
38
+
@procedure
39
+
@doc("Send a status into the ATmosphere.")
40
+
op main(
41
+
input: {
42
+
@required
43
+
@minLength(1)
44
+
@maxGraphemes(1)
45
+
@maxLength(32)
46
+
status: string;
47
+
},
48
+
): {
49
+
@required status: xyz.statusphere.defs.StatusView;
50
+
};
112
51
}
113
52
114
-
namespace app.example.repost {
115
-
@rec("tid")
116
-
@doc("A repost of another post")
117
-
model Main {
118
-
@doc("Post being reposted")
119
-
@required
120
-
subject: app.example.defs.PostRef;
121
-
122
-
@doc("When the repost was created")
123
-
@required
124
-
createdAt: datetime;
125
-
}
53
+
namespace xyz.statusphere.getStatuses {
54
+
@query
55
+
@doc("Get a list of the most recent statuses on the network.")
56
+
op main(@minValue(1) @maxValue(100) limit?: integer = 50): {
57
+
@required statuses: xyz.statusphere.defs.StatusView[];
58
+
};
126
59
}
127
60
128
-
namespace app.example.profile {
129
-
@rec("self")
130
-
@doc("User profile information")
131
-
model Main {
132
-
@doc("Display name")
133
-
displayName?: string;
134
-
135
-
@doc("Profile description")
136
-
description?: string;
137
-
138
-
@doc("Profile avatar image")
139
-
avatar?: string;
140
-
141
-
@doc("Profile banner image")
142
-
banner?: string;
143
-
}
61
+
namespace xyz.statusphere.getUser {
62
+
@query
63
+
@doc("Get the current user's profile and status.")
64
+
op main(): {
65
+
@required profile: app.bsky.actor.defs.ProfileView;
66
+
status?: xyz.statusphere.defs.StatusView;
67
+
};
144
68
}
+2
-3
packages/playground/package.json
+2
-3
packages/playground/package.json
···
4
4
"private": true,
5
5
"type": "module",
6
6
"scripts": {
7
-
"build:samples": "node samples/build.js",
8
-
"dev": "npm run build:samples && vite",
9
-
"build": "npm run build:samples && vite build",
7
+
"dev": "vite",
8
+
"build": "vite build",
10
9
"preview": "vite preview"
11
10
},
12
11
"dependencies": {
-52
packages/playground/samples/build.js
-52
packages/playground/samples/build.js
···
1
-
// @ts-check
2
-
import { writeFileSync, mkdirSync } from "fs";
3
-
import { dirname, resolve, join } from "path";
4
-
import { fileURLToPath } from "url";
5
-
import { lexicons, bundleLexicon } from "./index.js";
6
-
7
-
const __dirname = dirname(fileURLToPath(import.meta.url));
8
-
const outputDir = resolve(__dirname, "dist");
9
-
10
-
// Create output directory
11
-
mkdirSync(outputDir, { recursive: true });
12
-
13
-
// Write each bundled lexicon to disk
14
-
const samplesList = {};
15
-
16
-
// Add the default sample first
17
-
const defaultSample = "app.bsky.feed.like";
18
-
if (lexicons.has(defaultSample)) {
19
-
const lexicon = lexicons.get(defaultSample);
20
-
const bundled = bundleLexicon(defaultSample);
21
-
const filename = `${defaultSample}.tsp`;
22
-
const filepath = join(outputDir, filename);
23
-
24
-
writeFileSync(filepath, bundled);
25
-
26
-
samplesList[defaultSample] = {
27
-
filename: `samples/dist/${filename}`,
28
-
preferredEmitter: "@typelex/emitter",
29
-
};
30
-
}
31
-
32
-
// Add the rest
33
-
for (const [namespace, lexicon] of lexicons) {
34
-
if (namespace === defaultSample) continue; // Already added
35
-
36
-
const bundled = bundleLexicon(namespace);
37
-
const filename = `${namespace}.tsp`;
38
-
const filepath = join(outputDir, filename);
39
-
40
-
writeFileSync(filepath, bundled);
41
-
42
-
samplesList[namespace] = {
43
-
filename: `samples/dist/${filename}`,
44
-
preferredEmitter: "@typelex/emitter",
45
-
};
46
-
}
47
-
48
-
// Write the samples index
49
-
const samplesIndex = `export default ${JSON.stringify(samplesList, null, 2)};`;
50
-
writeFileSync(join(outputDir, "samples.js"), samplesIndex);
51
-
52
-
console.log(`Wrote ${Object.keys(samplesList).length} bundled samples to disk`);
+28
-105
packages/playground/samples/index.js
+28
-105
packages/playground/samples/index.js
···
6
6
const __dirname = dirname(fileURLToPath(import.meta.url));
7
7
8
8
// Get all tsp files
9
-
function getAllTspFiles(dir, baseDir = dir) {
9
+
function getAllFiles(dir, baseDir = dir) {
10
10
const files = [];
11
11
const entries = readdirSync(dir);
12
12
···
15
15
const stat = statSync(fullPath);
16
16
17
17
if (stat.isDirectory()) {
18
-
files.push(...getAllTspFiles(fullPath, baseDir));
18
+
files.push(...getAllFiles(fullPath, baseDir));
19
19
} else if (entry.endsWith(".tsp")) {
20
20
files.push(relative(baseDir, fullPath));
21
21
}
···
24
24
return files.sort();
25
25
}
26
26
27
-
// Extract dependencies from a file
28
-
function extractDependencies(content) {
29
-
const deps = new Set();
30
-
// Match namespace references like "com.atproto.label.defs.Label" or "com.atproto.repo.strongRef.Main"
31
-
// Pattern: word.word.word... followed by dot and identifier starting with capital letter
32
-
const pattern =
33
-
/\b([a-z]+(?:\.[a-z]+)+(?:\.[a-z][a-zA-Z]*)*)\.[A-Z][a-zA-Z]*/g;
34
-
const withoutDeclaration = content.replace(/namespace\s+[a-z.]+\s*\{/, "");
27
+
const integrationDir = join(__dirname, "../../emitter/test/integration");
35
28
36
-
const matches = withoutDeclaration.matchAll(pattern);
37
-
for (const match of matches) {
38
-
deps.add(match[1]);
39
-
}
29
+
// Get all test suite directories
30
+
const testSuites = readdirSync(integrationDir).filter((name) => {
31
+
const fullPath = join(integrationDir, name);
32
+
return statSync(fullPath).isDirectory() && !name.startsWith(".");
33
+
});
40
34
41
-
return Array.from(deps);
42
-
}
35
+
// Load all lexicons from test suites
36
+
const lexicons = new Map(); // namespace -> { file, content, suite }
43
37
44
-
const atprotoInputDir = join(
45
-
__dirname,
46
-
"../../emitter/test/integration/atproto/input",
47
-
);
48
-
const lexiconExamplesDir = join(
49
-
__dirname,
50
-
"../../emitter/test/integration/lexicon-examples/input",
51
-
);
38
+
for (const suite of testSuites) {
39
+
const inputDir = join(integrationDir, suite, "input");
40
+
const inputFiles = getAllFiles(inputDir).filter((f) => f.endsWith(".tsp"));
52
41
53
-
const atprotoFiles = getAllTspFiles(atprotoInputDir);
54
-
const lexiconExampleFiles = getAllTspFiles(lexiconExamplesDir);
42
+
for (const file of inputFiles) {
43
+
const fullPath = join(inputDir, file);
44
+
const content = readFileSync(fullPath, "utf-8");
45
+
const namespace = file.replace(/\.tsp$/, "").replace(/\//g, ".");
55
46
56
-
// Build dependency graph
57
-
const lexicons = new Map(); // namespace -> { file, content, deps }
58
-
59
-
// Process atproto files
60
-
for (const file of atprotoFiles) {
61
-
const fullPath = join(atprotoInputDir, file);
62
-
const content = readFileSync(fullPath, "utf-8");
63
-
const namespace = file.replace(/\.tsp$/, "").replace(/\//g, ".");
64
-
const deps = extractDependencies(content);
65
-
66
-
lexicons.set(namespace, { file: `atproto/${file}`, content, deps });
67
-
}
68
-
69
-
// Process lexicon-examples files
70
-
for (const file of lexiconExampleFiles) {
71
-
const fullPath = join(lexiconExamplesDir, file);
72
-
const content = readFileSync(fullPath, "utf-8");
73
-
const namespace = file.replace(/\.tsp$/, "").replace(/\//g, ".");
74
-
const deps = extractDependencies(content);
75
-
76
-
lexicons.set(namespace, { file: `examples/${file}`, content, deps });
77
-
}
78
-
79
-
// Recursively collect all dependencies (topological sort)
80
-
function collectDependencies(
81
-
namespace,
82
-
collected = new Set(),
83
-
visiting = new Set(),
84
-
) {
85
-
if (collected.has(namespace)) return;
86
-
if (visiting.has(namespace)) return; // circular dependency
87
-
88
-
const lexicon = lexicons.get(namespace);
89
-
if (!lexicon) return;
90
-
91
-
visiting.add(namespace);
92
-
93
-
// First collect all dependencies
94
-
for (const dep of lexicon.deps) {
95
-
collectDependencies(dep, collected, visiting);
47
+
lexicons.set(namespace, { file, content, suite, fullPath });
96
48
}
97
-
98
-
visiting.delete(namespace);
99
-
collected.add(namespace);
100
49
}
101
50
102
-
// Bundle a lexicon with all its dependencies
103
-
function bundleLexicon(namespace) {
104
-
const collected = new Set();
105
-
collectDependencies(namespace, collected);
106
-
107
-
// Put the main lexicon FIRST, then its dependencies
108
-
const mainLexicon = lexicons.get(namespace);
109
-
const deps = Array.from(collected).filter((ns) => ns !== namespace);
110
-
111
-
let bundled = 'import "@typelex/emitter";\n\n';
112
-
113
-
// Main lexicon first (so it shows in the playground)
114
-
if (mainLexicon) {
115
-
const contentWithoutImport = mainLexicon.content.replace(
116
-
/^import "@typelex\/emitter";\s*\n/,
117
-
"",
118
-
);
119
-
bundled += `// ${mainLexicon.file}\n${contentWithoutImport}\n`;
120
-
}
121
-
122
-
// Then dependencies
123
-
for (const ns of deps) {
124
-
const lexicon = lexicons.get(ns);
125
-
if (!lexicon) continue;
126
-
127
-
const contentWithoutImport = lexicon.content.replace(
128
-
/^import "@typelex\/emitter";\s*\n/,
129
-
"",
130
-
);
131
-
bundled += `// ${lexicon.file}\n${contentWithoutImport}\n`;
132
-
}
133
-
134
-
return bundled;
51
+
// Build samples list for playground
52
+
const samplesList = {};
53
+
for (const [namespace, lexicon] of lexicons) {
54
+
samplesList[namespace] = {
55
+
filename: relative(join(__dirname, ".."), lexicon.fullPath),
56
+
preferredEmitter: "@typelex/emitter",
57
+
};
135
58
}
136
59
137
-
// Export for build script
138
-
export { lexicons, bundleLexicon };
60
+
export { lexicons };
61
+
export default samplesList;
139
62
140
-
console.log(`Loaded ${lexicons.size} lexicons for bundling`);
63
+
console.log(`Loaded ${lexicons.size} lexicons`);
+3
-2
packages/playground/vite.config.ts
+3
-2
packages/playground/vite.config.ts
···
1
1
import { definePlaygroundViteConfig } from "@typespec/playground/vite";
2
2
import { defineConfig } from "vite";
3
-
import samples from "./samples/dist/samples.js";
3
+
import samples from "./samples/index.js";
4
4
5
5
const playgroundConfig = definePlaygroundViteConfig({
6
6
defaultEmitter: "@typelex/emitter",
7
7
libraries: ["@typespec/compiler", "@typelex/emitter"],
8
8
samples,
9
9
links: {
10
-
documentationUrl: "https://tangled.org/@danabra.mov/typelex",
10
+
documentationUrl:
11
+
"https://tangled.org/@danabra.mov/typelex/blob/main/DOCS.md",
11
12
},
12
13
});
13
14
packages/website/public/og.png
packages/website/public/og.png
This is a binary file and will not be displayed.
+142
-51
packages/website/src/pages/index.astro
+142
-51
packages/website/src/pages/index.astro
···
1
1
---
2
-
import Playground from '../components/Playground';
3
2
import { highlightCode } from '../utils/shiki';
4
3
import { compileToJson } from '../utils/compile';
5
4
import { createPlaygroundUrl } from '../utils/playground-url';
···
130
129
<head>
131
130
<meta charset="utf-8" />
132
131
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
133
-
<meta name="viewport" content="width=device-width" />
132
+
<meta name="viewport" content="width=device-width, initial-scale=1" />
134
133
<meta name="generator" content={Astro.generator} />
135
134
<title>typelex โ An experimental TypeSpec syntax for Lexicon</title>
135
+
<meta name="description" content="An experimental TypeSpec syntax for AT Protocol Lexicons. Write Lexicons in a more readable syntax using TypeSpec." />
136
+
137
+
<!-- Open Graph / Facebook -->
138
+
<meta property="og:type" content="website" />
139
+
<meta property="og:url" content="https://typelex.org/" />
140
+
<meta property="og:title" content="typelex โ An experimental TypeSpec syntax for Lexicon" />
141
+
<meta property="og:description" content="An experimental TypeSpec syntax for AT Protocol Lexicons. Write Lexicons in a more readable syntax using TypeSpec." />
142
+
<meta property="og:image" content="https://typelex.org/og.png" />
143
+
144
+
<!-- Twitter -->
145
+
<meta property="twitter:card" content="summary_large_image" />
146
+
<meta property="twitter:url" content="https://typelex.org/" />
147
+
<meta property="twitter:title" content="typelex โ An experimental TypeSpec syntax for Lexicon" />
148
+
<meta property="twitter:description" content="An experimental TypeSpec syntax for AT Protocol Lexicons. Write Lexicons in a more readable syntax using TypeSpec." />
149
+
<meta property="twitter:image" content="https://typelex.org/og.png" />
136
150
</head>
137
151
<body>
138
-
<div class="container">
152
+
<main class="container">
139
153
<header>
140
154
<h1>typelex</h1>
141
155
<p class="tagline">An experimental <a href="https://typespec.io" target="_blank" rel="noopener noreferrer">TypeSpec</a> syntax for <a href="https://atproto.com/specs/lexicon" target="_blank" rel="noopener noreferrer">Lexicon</a></p>
142
156
143
-
<div class="hero-comparison">
157
+
<figure class="hero-comparison">
144
158
<div class="comparison-content">
145
159
<div class="hero-panel">
146
-
<h3 class="hero-header">
160
+
<p class="hero-header">
147
161
Typelex
148
162
<a href={createPlaygroundUrl(`import "@typelex/emitter";
149
163
···
164
178
<path d="M3 5.5C3 4.67157 3.67157 4 4.5 4H5C5.27614 4 5.5 4.22386 5.5 4.5C5.5 4.77614 5.27614 5 5 5H4.5C4.22386 5 4 5.22386 4 5.5V11.5C4 11.7761 4.22386 12 4.5 12H10.5C10.7761 12 11 11.7761 11 11.5V11C11 10.7239 11.2239 10.5 11.5 10.5C11.7761 10.5 12 10.7239 12 11V11.5C12 12.3284 11.3284 13 10.5 13H4.5C3.67157 13 3 12.3284 3 11.5V5.5Z" fill="currentColor"/>
165
179
</svg>
166
180
</a>
167
-
</h3>
181
+
</p>
168
182
<div class="hero-code" set:html={await highlightCode(`import "@typelex/emitter";
169
183
170
184
namespace app.bsky.actor.profile {
···
181
195
}`, 'typespec')} />
182
196
</div>
183
197
<div class="hero-panel">
184
-
<h3 class="hero-header">
198
+
<p class="hero-header">
185
199
Lexicon
186
-
</h3>
200
+
</p>
187
201
<div class="hero-code" set:html={await highlightCode(stringify({
188
202
"lexicon": 1,
189
203
"id": "app.bsky.actor.profile",
···
211
225
}, { maxLength: 50 }), 'json')} />
212
226
</div>
213
227
</div>
214
-
</div>
228
+
</figure>
215
229
216
230
<p class="hero-description">
217
231
Typelex lets you write AT <a target="_blank" href="https://atproto.com/specs/lexicon">Lexicons</a> in a more readable syntax. <br />
218
232
It uses <a target="_blank" href="https://typespec.io/">TypeSpec</a> for syntax, adding conventions for Lexicons.
219
233
</p>
220
234
221
-
<div class="hero-actions">
235
+
<nav class="hero-actions">
222
236
<a href="#install" class="install-cta">Try It</a>
223
-
<a href="https://tangled.org/@danabra.mov/typlex" target="_blank" rel="noopener noreferrer" class="star-btn">
224
-
Read Documentation
237
+
<a href="https://tangled.org/@danabra.mov/typelex/blob/main/DOCS.md" target="_blank" rel="noopener noreferrer" class="star-btn">
238
+
Read Docs
225
239
</a>
226
-
</div>
240
+
</nav>
227
241
</header>
228
242
229
-
<div class="separator"></div>
243
+
<hr class="separator" />
230
244
231
245
{highlighted.map(({ title, typelexHtml, lexiconHtml, playgroundUrl }) => (
232
246
<section>
233
247
<h2>{title}</h2>
234
-
<div class="comparison">
248
+
<figure class="comparison">
235
249
<div class="comparison-content">
236
250
<div class="code-panel">
237
-
<h3 class="code-header">
251
+
<p class="code-header">
238
252
Typelex
239
253
<a href={playgroundUrl} target="_blank" rel="noopener noreferrer" class="code-playground-link" aria-label="Open in playground">
240
254
<svg width="14" height="14" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg" aria-hidden="true">
···
242
256
<path d="M3 5.5C3 4.67157 3.67157 4 4.5 4H5C5.27614 4 5.5 4.22386 5.5 4.5C5.5 4.77614 5.27614 5 5 5H4.5C4.22386 5 4 5.22386 4 5.5V11.5C4 11.7761 4.22386 12 4.5 12H10.5C10.7761 12 11 11.7761 11 11.5V11C11 10.7239 11.2239 10.5 11.5 10.5C11.7761 10.5 12 10.7239 12 11V11.5C12 12.3284 11.3284 13 10.5 13H4.5C3.67157 13 3 12.3284 3 11.5V5.5Z" fill="currentColor"/>
243
257
</svg>
244
258
</a>
245
-
</h3>
259
+
</p>
246
260
<div class="code-block" set:html={typelexHtml} />
247
261
</div>
248
262
<div class="code-panel">
249
-
<h3 class="code-header">
263
+
<p class="code-header">
250
264
Lexicon
251
-
</h3>
265
+
</p>
252
266
<div class="code-block" set:html={lexiconHtml} />
253
267
</div>
254
268
</div>
255
-
</div>
269
+
</figure>
256
270
</section>
257
271
))}
258
272
259
-
<div class="separator"></div>
273
+
<hr class="separator" />
260
274
261
275
<section class="install-section" id="install">
262
276
<h2>Install</h2>
263
277
<div class="install-grid">
264
278
<div class="install-notice">
265
-
<p class="notice-text">This is an early-stage experiment. There are bugs. You must verify the output!</p>
279
+
<p class="notice-text">This is an early-stage experiment. Design and syntax may change.</p>
266
280
</div>
267
281
<div class="install-step playground-step">
268
282
<div class="step-number">0</div>
···
279
293
<div class="step-number">1</div>
280
294
<div class="step-content">
281
295
<h3>Install packages</h3>
282
-
<div class="install-box" set:html={await highlightCode('npm install -D @typespec/compiler @typelex/emitter', 'bash')} />
296
+
<figure class="install-box" set:html={await highlightCode('npm install -D @typespec/compiler @typelex/emitter', 'bash')} />
283
297
</div>
284
298
</div>
285
299
286
300
<div class="install-step">
287
301
<div class="step-number">2</div>
288
302
<div class="step-content">
289
-
<h3>Add <a href="https://typespec.io/docs/handbook/configuration/configuration/" target="_blank" rel="noopener noreferrer">tspconfig.yaml</a></h3>
290
-
<div class="install-box" set:html={await highlightCode(`emit:
303
+
<h3>Create <code>typelex/main.tsp</code></h3>
304
+
<figure class="install-box install-box-with-link">
305
+
<a href={createPlaygroundUrl(`import "@typelex/emitter";
306
+
307
+
namespace com.example.actor.profile {
308
+
/** My profile. */
309
+
@rec("literal:self")
310
+
model Main {
311
+
/** Free-form profile description.*/
312
+
@maxGraphemes(256)
313
+
description?: string;
314
+
}
315
+
}`)} target="_blank" rel="noopener noreferrer" class="install-playground-link" aria-label="Open in playground">
316
+
<svg width="14" height="14" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg" aria-hidden="true">
317
+
<path d="M6.5 3.5C6.5 3.22386 6.72386 3 7 3H13C13.2761 3 13.5 3.22386 13.5 3.5V9.5C13.5 9.77614 13.2761 10 13 10C12.7239 10 12.5 9.77614 12.5 9.5V4.70711L6.85355 10.3536C6.65829 10.5488 6.34171 10.5488 6.14645 10.3536C5.95118 10.1583 5.95118 9.84171 6.14645 9.64645L11.7929 4H7C6.72386 4 6.5 3.77614 6.5 3.5Z" fill="currentColor"/>
318
+
<path d="M3 5.5C3 4.67157 3.67157 4 4.5 4H5C5.27614 4 5.5 4.22386 5.5 4.5C5.5 4.77614 5.27614 5 5 5H4.5C4.22386 5 4 5.22386 4 5.5V11.5C4 11.7761 4.22386 12 4.5 12H10.5C10.7761 12 11 11.7761 11 11.5V11C11 10.7239 11.2239 10.5 11.5 10.5C11.7761 10.5 12 10.7239 12 11V11.5C12 12.3284 11.3284 13 10.5 13H4.5C3.67157 13 3 12.3284 3 11.5V5.5Z" fill="currentColor"/>
319
+
</svg>
320
+
</a>
321
+
<div set:html={await highlightCode(`import "@typelex/emitter";
322
+
323
+
namespace com.example.actor.profile {
324
+
/** My profile. */
325
+
@rec("literal:self")
326
+
model Main {
327
+
/** Free-form profile description.*/
328
+
@maxGraphemes(256)
329
+
description?: string;
330
+
}
331
+
}`, 'typespec')} />
332
+
</figure>
333
+
</div>
334
+
<p class="step-description">Or grab any example Lexicon <a target=_blank href="https://playground.typelex.org/">from the Playground</a>.</p>
335
+
</div>
336
+
337
+
<div class="install-step">
338
+
<div class="step-number">3</div>
339
+
<div class="step-content">
340
+
<h3>Create <code><a href="https://typespec.io/docs/handbook/configuration/configuration/" target="_blank" rel="noopener noreferrer">tspconfig.yaml</a></code></h3>
341
+
<figure class="install-box" set:html={await highlightCode(`emit:
291
342
- "@typelex/emitter"
292
343
options:
293
344
"@typelex/emitter":
294
-
output-dir: "./lexicon"`, 'yaml')} />
345
+
output-dir: "./lexicons"`, 'yaml')} />
295
346
</div>
296
347
</div>
297
348
298
349
<div class="install-step">
299
-
<div class="step-number">3</div>
350
+
<div class="step-number">4</div>
300
351
<div class="step-content">
301
-
<h3>Configure scripts</h3>
302
-
<div class="install-box" set:html={await highlightCode(`{
352
+
<h3>Add a build script to <code>package.json</code></h3>
353
+
<figure class="install-box" set:html={await highlightCode(`{
303
354
"scripts": {
304
-
"build": "npm run build:lexicon && npm run build:codegen",
305
-
"build:lexicon": "tsp compile . && tsp format **/*.tsp",
306
-
"build:codegen": "lex gen-api --yes ./src lexicon/app/example/*.json"
355
+
// ...
356
+
"build:lexicons": "tsp compile typelex/main.tsp"
307
357
}
308
358
}`, 'json')} />
309
359
</div>
310
360
</div>
311
361
312
362
<div class="install-step">
313
-
<div class="step-number">4</div>
363
+
<div class="step-number">5</div>
364
+
<div class="step-content">
365
+
<h3>Generate Lexicon files</h3>
366
+
<figure class="install-box" set:html={await highlightCode(`npm run build:lexicons`, 'bash')} />
367
+
<p class="step-description">Lexicon files will be generated in the <code>output-dir</code> from your <code>tspconfig.yaml</code> config.</p>
368
+
</div>
369
+
</div>
370
+
371
+
<div class="install-step">
372
+
<div class="step-number">6</div>
314
373
<div class="step-content">
315
374
<h3>Set up VS Code</h3>
316
375
<p class="step-description">Install the <a href="https://typespec.io/docs/introduction/editor/vscode/" target="_blank" rel="noopener noreferrer">TypeSpec for VS Code extension</a> for syntax highlighting and IntelliSense.</p>
···
318
377
</div>
319
378
320
379
<div class="install-step">
321
-
<div class="step-number">5</div>
380
+
<div class="step-number">7</div>
322
381
<div class="step-content">
323
382
<h3>Read the docs</h3>
324
-
<p class="step-description">Check out the <a href="https://tangled.org/@danabra.mov/typlex" target="_blank" rel="noopener noreferrer">documentation</a> to learn more about Typelex syntax and features.</p>
383
+
<p class="step-description">Check out the <a href="https://tangled.org/@danabra.mov/typelex/blob/main/DOCS.md" target="_blank" rel="noopener noreferrer">documentation</a> to learn more.</p>
325
384
</div>
326
385
</div>
327
386
</div>
328
387
</section>
329
-
330
-
<div class="separator"></div>
388
+
389
+
<hr class="separator" />
331
390
332
391
<footer>
333
392
<p>This is my personal hobby project and is not affiliated with AT or endorsed by anyone.</p>
334
393
<p>Who knows if this is a good idea?</p>
335
394
</footer>
336
-
</div>
395
+
</main>
337
396
338
397
<script>
339
398
document.addEventListener('DOMContentLoaded', () => {
···
438
497
439
498
header {
440
499
text-align: center;
441
-
padding: 3rem 1rem 2rem;
500
+
padding: 3rem 1rem 0.5rem;
442
501
margin: 0 auto;
443
502
}
444
503
···
589
648
590
649
.hero-actions {
591
650
display: flex;
592
-
flex-direction: column;
593
-
gap: 1rem;
651
+
flex-direction: row;
652
+
flex-wrap: wrap;
653
+
gap: 0.75rem;
594
654
margin-top: 2.5rem;
595
655
align-items: center;
656
+
justify-content: center;
596
657
}
597
658
598
659
@media (min-width: 640px) {
599
660
.hero-actions {
600
-
flex-direction: row;
601
-
justify-content: center;
602
661
gap: 1rem;
603
662
}
604
663
}
···
710
769
height: 1px;
711
770
background: linear-gradient(to right, transparent, #e2e8f0 20%, #e2e8f0 80%, transparent);
712
771
margin: 4rem 0;
772
+
border: none;
713
773
}
714
774
715
775
@media (min-width: 768px) {
···
736
796
737
797
.install-notice {
738
798
padding: 1rem 1.5rem;
739
-
background: #fef3c7;
740
-
border: 1px solid #fbbf24;
799
+
background: linear-gradient(135deg, #fefce8 0%, #fef3c7 100%);
800
+
border: 2px solid #f59e0b;
741
801
border-radius: 10px;
742
-
text-align: center;
802
+
text-align: left;
743
803
}
744
804
745
805
.notice-text {
746
806
margin: 0;
747
807
font-size: 1.0625rem;
748
808
line-height: 1.5;
749
-
font-weight: 600;
809
+
font-weight: 700;
750
810
color: #92400e;
751
811
}
752
812
···
842
902
background: #1e1b29;
843
903
border-radius: 8px;
844
904
overflow: hidden;
905
+
margin: 0;
906
+
}
907
+
908
+
.install-box-with-link {
909
+
position: relative;
910
+
}
911
+
912
+
.install-playground-link {
913
+
position: absolute;
914
+
top: 0.75rem;
915
+
right: 0.75rem;
916
+
z-index: 10;
917
+
display: inline-flex;
918
+
align-items: center;
919
+
justify-content: center;
920
+
color: #94a3b8;
921
+
transition: all 0.2s ease;
922
+
text-decoration: none;
923
+
opacity: 0.4;
924
+
padding: 0.125rem;
925
+
}
926
+
927
+
.install-playground-link:hover {
928
+
color: #c7d2fe;
929
+
opacity: 1;
930
+
}
931
+
932
+
.install-playground-link svg {
933
+
width: 1rem;
934
+
height: 1rem;
845
935
}
846
936
847
937
.install-box + .step-description {
···
857
947
858
948
.install-box code {
859
949
font-family: 'Monaco', 'Menlo', monospace;
860
-
font-size: 0.8125rem !important;
950
+
font-size: 0.75rem !important;
861
951
line-height: 1.6;
862
952
}
863
953
···
874
964
875
965
.install-notice {
876
966
padding: 1.5rem 2rem;
967
+
border-width: 2px;
877
968
}
878
969
879
970
.notice-text {
···
898
989
}
899
990
900
991
.install-box code {
901
-
font-size: 0.875rem !important;
992
+
font-size: 0.8125rem !important;
902
993
}
903
994
}
904
995
···
1070
1161
.code-block code,
1071
1162
.hero-code code {
1072
1163
font-family: 'Monaco', 'Menlo', monospace;
1073
-
font-size: 0.8125rem !important;
1164
+
font-size: 0.75rem !important;
1074
1165
line-height: 1.6;
1075
1166
white-space: pre;
1076
1167
text-align: left;
···
1079
1170
@media (min-width: 768px) {
1080
1171
.code-block code,
1081
1172
.hero-code code {
1082
-
font-size: 0.9375rem !important;
1173
+
font-size: 0.875rem !important;
1083
1174
}
1084
1175
}
1085
1176
+46
-3
pnpm-lock.yaml
+46
-3
pnpm-lock.yaml
···
12
12
specifier: ^5.0.0
13
13
version: 5.9.3
14
14
15
+
packages/cli:
16
+
dependencies:
17
+
'@typelex/emitter':
18
+
specifier: ^0.2.0
19
+
version: 0.2.0(@typespec/compiler@1.4.0(@types/node@20.19.19))
20
+
'@typespec/compiler':
21
+
specifier: ^1.4.0
22
+
version: 1.4.0(@types/node@20.19.19)
23
+
yargs:
24
+
specifier: ^18.0.0
25
+
version: 18.0.0
26
+
devDependencies:
27
+
'@types/node':
28
+
specifier: ^20.0.0
29
+
version: 20.19.19
30
+
'@types/yargs':
31
+
specifier: ^17.0.33
32
+
version: 17.0.33
33
+
typescript:
34
+
specifier: ^5.0.0
35
+
version: 5.9.3
36
+
15
37
packages/emitter:
16
38
dependencies:
17
39
'@typespec/compiler':
···
48
70
'@atproto/xrpc-server':
49
71
specifier: ^0.9.5
50
72
version: 0.9.5
73
+
'@typelex/cli':
74
+
specifier: workspace:*
75
+
version: link:../cli
51
76
'@typelex/emitter':
52
77
specifier: workspace:*
53
78
version: link:../emitter
54
-
'@typespec/compiler':
55
-
specifier: ^1.4.0
56
-
version: 1.4.0(@types/node@20.19.19)
57
79
devDependencies:
58
80
typescript:
59
81
specifier: ^5.0.0
···
1645
1667
'@ts-morph/common@0.25.0':
1646
1668
resolution: {integrity: sha512-kMnZz+vGGHi4GoHnLmMhGNjm44kGtKUXGnOvrKmMwAuvNjM/PgKVGfUnL7IDvK7Jb2QQ82jq3Zmp04Gy+r3Dkg==}
1647
1669
1670
+
'@typelex/emitter@0.2.0':
1671
+
resolution: {integrity: sha512-4Iw6VAnd9nCFGOkJcu9utWdmu9ZyPeAb1QX/B7KerGBmfc2FuIDqgZZ/mZ6c56atcZd62pb2oYF/3RgSFhEsoQ==}
1672
+
peerDependencies:
1673
+
'@typespec/compiler': ^1.4.0
1674
+
1648
1675
'@types/babel__core@7.20.5':
1649
1676
resolution: {integrity: sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==}
1650
1677
···
1705
1732
1706
1733
'@types/unist@3.0.3':
1707
1734
resolution: {integrity: sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==}
1735
+
1736
+
'@types/yargs-parser@21.0.3':
1737
+
resolution: {integrity: sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==}
1738
+
1739
+
'@types/yargs@17.0.33':
1740
+
resolution: {integrity: sha512-WpxBCKWPLr4xSsHgz511rFJAM+wS28w2zEO1QDNY5zM/S8ok70NNfztH0xwhqKyaK0OHCbN98LDAZuy1ctxDkA==}
1708
1741
1709
1742
'@typespec/asset-emitter@0.74.0':
1710
1743
resolution: {integrity: sha512-DWIdlSNhRgBeZ8exfqubfUn0H6mRg4gr0s7zLTdBMUEDHL3Yh0ljnRPkd8AXTZhoW3maTFT69loWTrqx09T5oQ==}
···
7411
7444
path-browserify: 1.0.1
7412
7445
tinyglobby: 0.2.15
7413
7446
7447
+
'@typelex/emitter@0.2.0(@typespec/compiler@1.4.0(@types/node@20.19.19))':
7448
+
dependencies:
7449
+
'@typespec/compiler': 1.4.0(@types/node@20.19.19)
7450
+
7414
7451
'@types/babel__core@7.20.5':
7415
7452
dependencies:
7416
7453
'@babel/parser': 7.28.4
···
7482
7519
csstype: 3.1.3
7483
7520
7484
7521
'@types/unist@3.0.3': {}
7522
+
7523
+
'@types/yargs-parser@21.0.3': {}
7524
+
7525
+
'@types/yargs@17.0.33':
7526
+
dependencies:
7527
+
'@types/yargs-parser': 21.0.3
7485
7528
7486
7529
'@typespec/asset-emitter@0.74.0(@typespec/compiler@1.4.0(@types/node@20.19.19))':
7487
7530
dependencies: