+1
.gitignore
+1
.gitignore
+2
-2
packages/cli/package.json
+2
-2
packages/cli/package.json
···
1
1
{
2
2
"name": "@typelex/cli",
3
-
"version": "0.2.13",
3
+
"version": "0.2.0",
4
+
"description": "CLI for typelex - TypeSpec-based IDL for ATProto Lexicons",
4
5
"main": "dist/index.js",
5
6
"type": "module",
6
7
"bin": {
···
26
27
"license": "MIT",
27
28
"dependencies": {
28
29
"@typespec/compiler": "^1.4.0",
29
-
"picocolors": "^1.1.1",
30
30
"yargs": "^18.0.0"
31
31
},
32
32
"devDependencies": {
+4
-53
packages/cli/src/cli.ts
+4
-53
packages/cli/src/cli.ts
···
2
2
import yargs from "yargs";
3
3
import { hideBin } from "yargs/helpers";
4
4
import { compileCommand } from "./commands/compile.js";
5
-
import { initCommand } from "./commands/init.js";
6
5
7
6
async function main() {
8
7
await yargs(hideBin(process.argv))
9
8
.scriptName("typelex")
10
-
.command(
11
-
"init",
12
-
"Initialize a new typelex project",
13
-
(yargs) => {
14
-
return yargs.option("setup", {
15
-
describe: "Internal: run setup after installation",
16
-
type: "boolean",
17
-
hidden: true,
18
-
default: false,
19
-
});
20
-
},
21
-
async (argv) => {
22
-
// Extract any unknown flags to pass through to package manager
23
-
const flags: string[] = [];
24
-
const knownFlags = new Set(["setup", "_", "$0"]);
25
-
26
-
for (const [key, value] of Object.entries(argv)) {
27
-
if (!knownFlags.has(key)) {
28
-
// Single letter = short flag, multiple letters = long flag
29
-
const prefix = key.length === 1 ? "-" : "--";
30
-
if (typeof value === "boolean" && value) {
31
-
flags.push(`${prefix}${key}`);
32
-
} else if (value !== false && value !== undefined) {
33
-
flags.push(`${prefix}${key}`, String(value));
34
-
}
35
-
}
36
-
}
37
-
38
-
await initCommand(argv.setup, flags);
39
-
}
40
-
)
9
+
.usage("$0 compile <namespace>")
41
10
.command(
42
11
"compile <namespace>",
43
12
"Compile TypeSpec files to Lexicon JSON",
44
13
(yargs) => {
45
14
return yargs
46
15
.positional("namespace", {
47
-
describe: "Primary namespace pattern (e.g., com.example.*)",
16
+
describe: "Primary namespace pattern (e.g., app.bsky.*)",
48
17
type: "string",
49
18
demandOption: true,
50
19
})
51
20
.option("out", {
52
-
describe: "Output directory for generated Lexicon files (must end with 'lexicons')",
21
+
describe: "Output directory for generated Lexicon files (relative to cwd)",
53
22
type: "string",
54
23
default: "./lexicons",
55
24
});
56
25
},
57
26
async (argv) => {
58
-
if (!argv.namespace) {
59
-
console.error("Error: namespace is required");
60
-
console.error("Usage: typelex compile <namespace>");
61
-
console.error("Example: typelex compile com.example.*");
62
-
process.exit(1);
63
-
}
64
-
65
-
if (!argv.namespace.endsWith(".*")) {
66
-
console.error("Error: namespace must end with .*");
67
-
console.error(`Got: ${argv.namespace}`);
68
-
console.error("Example: typelex compile com.example.*");
69
-
process.exit(1);
70
-
}
71
-
72
27
const options: Record<string, unknown> = {};
73
28
if (argv.watch) {
74
29
options.watch = true;
···
84
39
type: "boolean",
85
40
default: false,
86
41
})
87
-
.demandCommand(1)
42
+
.demandCommand(1, "You must specify a command")
88
43
.help()
89
44
.version()
90
45
.fail((msg, err) => {
91
46
if (err) {
92
47
console.error(err);
93
-
} else if (msg.includes("Not enough non-option arguments")) {
94
-
console.error("Error: namespace is required");
95
-
console.error("Usage: typelex compile <namespace>");
96
-
console.error("Example: typelex compile com.example.*");
97
48
} else {
98
49
console.error(msg);
99
50
}
+1
-5
packages/cli/src/commands/compile.ts
+1
-5
packages/cli/src/commands/compile.ts
···
33
33
34
34
// Compile TypeSpec using the TypeSpec CLI
35
35
const entrypoint = resolve(cwd, "typelex/main.tsp");
36
-
37
-
// Normalize path for TypeSpec (remove leading ./)
38
-
const normalizedOutDir = outDir.replace(/^\.\//, '');
39
-
40
36
const args = [
41
37
"compile",
42
38
entrypoint,
43
39
"--emit",
44
40
"@typelex/emitter",
45
41
"--option",
46
-
`@typelex/emitter.emitter-output-dir={project-root}/${normalizedOutDir}`,
42
+
`@typelex/emitter.emitter-output-dir={project-root}/${outDir}`,
47
43
];
48
44
49
45
if (options.watch) {
-277
packages/cli/src/commands/init.ts
-277
packages/cli/src/commands/init.ts
···
1
-
import { resolve, relative } from "path";
2
-
import { mkdir, writeFile, readFile, access, stat } from "fs/promises";
3
-
import { spawn } from "child_process";
4
-
import { createInterface } from "readline";
5
-
import pc from "picocolors";
6
-
7
-
function gradientText(text: string): string {
8
-
const colors = [
9
-
'\x1b[38;5;33m',
10
-
'\x1b[38;5;69m',
11
-
'\x1b[38;5;99m',
12
-
'\x1b[38;5;133m',
13
-
'\x1b[38;5;170m',
14
-
'\x1b[38;5;170m',
15
-
'\x1b[38;5;133m',
16
-
];
17
-
const reset = '\x1b[0m';
18
-
19
-
return text.split('').map((char, i) => {
20
-
const colorIndex = Math.floor((i / text.length) * colors.length);
21
-
return colors[colorIndex] + char;
22
-
}).join('') + reset;
23
-
}
24
-
25
-
function createMainTemplate(namespace: string): string {
26
-
return `import "@typelex/emitter";
27
-
import "./externals.tsp";
28
-
29
-
namespace ${namespace}.post {
30
-
@rec("tid")
31
-
model Main {
32
-
@required text: string;
33
-
@required createdAt: datetime;
34
-
}
35
-
}
36
-
`;
37
-
}
38
-
39
-
const EXTERNALS_TSP_TEMPLATE = `import "@typelex/emitter";
40
-
41
-
// Generated by typelex
42
-
// This file is auto-generated. Do not edit manually.
43
-
`;
44
-
45
-
async function promptNamespace(): Promise<string> {
46
-
const rl = createInterface({
47
-
input: process.stdin,
48
-
output: process.stdout,
49
-
});
50
-
51
-
return new Promise((resolve) => {
52
-
rl.question(`Enter your app's root namespace (e.g. ${pc.cyan("com.example.*")}): `, (answer) => {
53
-
rl.close();
54
-
resolve(answer.trim());
55
-
});
56
-
});
57
-
}
58
-
59
-
export async function initCommand(isSetup: boolean = false, flags: string[] = []): Promise<void> {
60
-
const originalCwd = process.cwd();
61
-
62
-
// Find nearest package.json upward
63
-
let projectRoot = originalCwd;
64
-
let dir = originalCwd;
65
-
while (dir !== resolve(dir, "..")) {
66
-
try {
67
-
await access(resolve(dir, "package.json"));
68
-
projectRoot = dir;
69
-
break;
70
-
} catch {
71
-
dir = resolve(dir, "..");
72
-
}
73
-
}
74
-
75
-
if (isSetup) {
76
-
return initSetup();
77
-
}
78
-
79
-
console.log(`Adding ${gradientText("typelex")}...\n`);
80
-
81
-
// Detect package manager
82
-
let packageManager = "npm";
83
-
dir = projectRoot;
84
-
while (dir !== resolve(dir, "..") && packageManager === "npm") {
85
-
try {
86
-
await access(resolve(dir, "pnpm-lock.yaml"));
87
-
packageManager = "pnpm";
88
-
break;
89
-
} catch {
90
-
// Not found
91
-
}
92
-
try {
93
-
await access(resolve(dir, "yarn.lock"));
94
-
packageManager = "yarn";
95
-
break;
96
-
} catch {
97
-
// Not found
98
-
}
99
-
dir = resolve(dir, "..");
100
-
}
101
-
102
-
// Install dependencies
103
-
await new Promise<void>((resolvePromise, reject) => {
104
-
const args = packageManager === "npm"
105
-
? ["install", "--save-dev", "@typelex/cli@latest", "@typelex/emitter@latest"]
106
-
: ["add", "-D", "@typelex/cli@latest", "@typelex/emitter@latest"];
107
-
108
-
// Add any additional flags
109
-
args.push(...flags);
110
-
111
-
const install = spawn(packageManager, args, {
112
-
cwd: projectRoot,
113
-
stdio: "inherit",
114
-
});
115
-
116
-
install.on("close", (code) => {
117
-
if (code === 0) {
118
-
console.log(`\n${pc.green("โ")} Installed ${pc.dim("@typelex/cli")} and ${pc.dim("@typelex/emitter")}\n`);
119
-
resolvePromise();
120
-
} else {
121
-
console.error(pc.red("โ Failed to install dependencies"));
122
-
process.exit(code ?? 1);
123
-
}
124
-
});
125
-
126
-
install.on("error", (err) => {
127
-
console.error(pc.red("โ Failed to install dependencies:"), err);
128
-
reject(err);
129
-
});
130
-
});
131
-
132
-
// Find node_modules
133
-
let nodeModulesDir = resolve(projectRoot, "node_modules");
134
-
let searchDir = projectRoot;
135
-
while (searchDir !== resolve(searchDir, "..")) {
136
-
try {
137
-
const candidatePath = resolve(searchDir, "node_modules/.bin/typelex");
138
-
await access(candidatePath);
139
-
nodeModulesDir = resolve(searchDir, "node_modules");
140
-
break;
141
-
} catch {
142
-
searchDir = resolve(searchDir, "..");
143
-
}
144
-
}
145
-
146
-
return new Promise((resolvePromise, reject) => {
147
-
const localCli = resolve(nodeModulesDir, ".bin/typelex");
148
-
const setup = spawn(localCli, ["init", "--setup"], {
149
-
cwd: projectRoot,
150
-
stdio: "inherit",
151
-
});
152
-
153
-
setup.on("close", (code) => {
154
-
if (code === 0) {
155
-
resolvePromise();
156
-
} else {
157
-
process.exit(code ?? 1);
158
-
}
159
-
});
160
-
161
-
setup.on("error", (err) => {
162
-
console.error(pc.red("โ Failed to run setup:"), err);
163
-
reject(err);
164
-
});
165
-
});
166
-
}
167
-
168
-
export async function initSetup(): Promise<void> {
169
-
const cwd = process.cwd();
170
-
const typelexDir = resolve(cwd, "typelex");
171
-
const mainTspPath = resolve(typelexDir, "main.tsp");
172
-
const externalsTspPath = resolve(typelexDir, "externals.tsp");
173
-
174
-
// Prompt for namespace
175
-
let namespace = await promptNamespace();
176
-
177
-
// Validate namespace format
178
-
while (!namespace.endsWith(".*")) {
179
-
console.error(pc.red(`Error: namespace must end with ${pc.bold(".*")}`));
180
-
console.error(pc.red(`Got: ${pc.bold(namespace)}\n`));
181
-
namespace = await promptNamespace();
182
-
}
183
-
184
-
// Remove the .* suffix for use in template
185
-
const namespacePrefix = namespace.slice(0, -2);
186
-
187
-
// Detect lexicons directory: check cwd first, then walk up parents
188
-
let lexiconsDir: string | null = null;
189
-
let hasLocalLexicons = false;
190
-
191
-
// Check current directory for lexicons/ (will use default, no --out flag needed)
192
-
try {
193
-
const localPath = resolve(cwd, "lexicons");
194
-
if ((await stat(localPath)).isDirectory()) {
195
-
hasLocalLexicons = true;
196
-
}
197
-
} catch {
198
-
// Not found in current directory, check parent directories
199
-
let dir = resolve(cwd, "..");
200
-
while (dir !== resolve(dir, "..")) {
201
-
try {
202
-
const lexPath = resolve(dir, "lexicons");
203
-
if ((await stat(lexPath)).isDirectory()) {
204
-
lexiconsDir = relative(cwd, lexPath);
205
-
break;
206
-
}
207
-
} catch {
208
-
// Not found, continue up
209
-
}
210
-
dir = resolve(dir, "..");
211
-
}
212
-
}
213
-
214
-
// Determine the actual lexicons path for display
215
-
const displayLexiconsPath = hasLocalLexicons
216
-
? "./lexicons"
217
-
: lexiconsDir || "./lexicons";
218
-
219
-
// Inform about external lexicons
220
-
console.log(`\nLexicons other than ${pc.cyan(namespace)} will be considered external.`);
221
-
console.log(`Put them into the ${pc.cyan(displayLexiconsPath)} folder as JSON.\n`);
222
-
223
-
// Create typelex directory
224
-
await mkdir(typelexDir, { recursive: true });
225
-
226
-
// Check if main.tsp exists and is non-empty
227
-
let shouldCreateMain = true;
228
-
try {
229
-
await access(mainTspPath);
230
-
const content = await readFile(mainTspPath, "utf-8");
231
-
if (content.trim().length > 0) {
232
-
console.log(`${pc.green("โ")} ${pc.cyan("typelex/main.tsp")} already exists, skipping`);
233
-
shouldCreateMain = false;
234
-
}
235
-
} catch {
236
-
// File doesn't exist, we'll create it
237
-
}
238
-
239
-
if (shouldCreateMain) {
240
-
await writeFile(mainTspPath, createMainTemplate(namespacePrefix), "utf-8");
241
-
console.log(`${pc.green("โ")} Created ${pc.cyan("typelex/main.tsp")}`);
242
-
}
243
-
244
-
// Always create/overwrite externals.tsp
245
-
await writeFile(externalsTspPath, EXTERNALS_TSP_TEMPLATE, "utf-8");
246
-
console.log(`${pc.green("โ")} Created ${pc.cyan("typelex/externals.tsp")}`);
247
-
248
-
// Add build script to package.json
249
-
const packageJsonPath = resolve(cwd, "package.json");
250
-
try {
251
-
const packageJson = JSON.parse(await readFile(packageJsonPath, "utf-8"));
252
-
if (!packageJson.scripts) {
253
-
packageJson.scripts = {};
254
-
}
255
-
if (!packageJson.scripts["build:typelex"]) {
256
-
const outFlag = lexiconsDir ? ` --out ${lexiconsDir}` : "";
257
-
packageJson.scripts["build:typelex"] = `typelex compile ${namespace}${outFlag}`;
258
-
await writeFile(packageJsonPath, JSON.stringify(packageJson, null, 2) + "\n", "utf-8");
259
-
console.log(`${pc.green("โ")} Added ${pc.cyan("build:typelex")} script to ${pc.cyan("package.json")}`);
260
-
if (hasLocalLexicons) {
261
-
console.log(pc.dim(` Using existing lexicons directory: ${pc.cyan("./lexicons")}`));
262
-
} else if (lexiconsDir) {
263
-
console.log(pc.dim(` Using existing lexicons directory: ${pc.cyan(lexiconsDir)}`));
264
-
}
265
-
} else {
266
-
console.log(`${pc.green("โ")} ${pc.cyan("build:typelex")} script already exists in ${pc.cyan("package.json")}`);
267
-
}
268
-
} catch (err) {
269
-
console.warn(pc.yellow(`โ Could not update ${pc.cyan("package.json")}:`), (err as Error).message);
270
-
}
271
-
272
-
console.log(`\n${pc.green("โ")} ${pc.bold("All set!")}`);
273
-
console.log(`\n${pc.bold("Next steps:")}`);
274
-
console.log(` ${pc.dim("1.")} Edit ${pc.cyan("typelex/main.tsp")} to define your lexicons`);
275
-
console.log(` ${pc.dim("2.")} Keep putting external lexicons into ${pc.cyan(displayLexiconsPath)}`);
276
-
console.log(` ${pc.dim("3.")} Run ${pc.cyan("npm run build:typelex")} to compile to JSON`);
277
-
}
+4
-4
packages/cli/src/utils/externals-generator.ts
+4
-4
packages/cli/src/utils/externals-generator.ts
···
22
22
/**
23
23
* Generate TypeSpec external definitions from lexicon documents
24
24
*/
25
-
function generateExternalsCode(lexicons: Map<string, LexiconDoc>, outDir: string, excludedPrefix: string): string {
25
+
function generateExternalsCode(lexicons: Map<string, LexiconDoc>): string {
26
26
const lines: string[] = [];
27
27
28
28
lines.push('import "@typelex/emitter";');
29
29
lines.push("");
30
-
lines.push(`// Generated by typelex from ${outDir} (excluding ${excludedPrefix}.*)`);
30
+
lines.push("// Generated by typelex");
31
31
lines.push("// This file is auto-generated. Do not edit manually.");
32
32
lines.push("");
33
33
···
89
89
await mkdir(resolve(cwd, "typelex"), { recursive: true });
90
90
await writeFile(
91
91
outputFile,
92
-
`import "@typelex/emitter";\n\n// Generated by typelex from ${outDir} (excluding ${prefix}.*)\n// No external lexicons found\n`,
92
+
'import "@typelex/emitter";\n\n// Generated by typelex\n// No external lexicons found\n',
93
93
"utf-8"
94
94
);
95
95
return;
96
96
}
97
97
98
-
const code = generateExternalsCode(externals, outDir, prefix);
98
+
const code = generateExternalsCode(externals);
99
99
await mkdir(resolve(cwd, "typelex"), { recursive: true });
100
100
await writeFile(outputFile, code, "utf-8");
101
101
} catch (error) {
+7
packages/example/.gitignore
+7
packages/example/.gitignore
-31
packages/example/lexicons/app/bsky/actor/defs.json
-31
packages/example/lexicons/app/bsky/actor/defs.json
···
1
-
{
2
-
"lexicon": 1,
3
-
"id": "app.bsky.actor.defs",
4
-
"defs": {
5
-
"profileView": {
6
-
"type": "object",
7
-
"required": ["did", "handle"],
8
-
"properties": {
9
-
"did": { "type": "string", "format": "did" },
10
-
"handle": { "type": "string", "format": "handle" },
11
-
"displayName": {
12
-
"type": "string",
13
-
"maxGraphemes": 64,
14
-
"maxLength": 640
15
-
},
16
-
"description": {
17
-
"type": "string",
18
-
"maxGraphemes": 256,
19
-
"maxLength": 2560
20
-
},
21
-
"avatar": { "type": "string", "format": "uri" },
22
-
"indexedAt": { "type": "string", "format": "datetime" },
23
-
"createdAt": { "type": "string", "format": "datetime" },
24
-
"labels": {
25
-
"type": "array",
26
-
"items": { "type": "ref", "ref": "com.atproto.label.defs#label" }
27
-
}
28
-
}
29
-
}
30
-
}
31
-
}
-53
packages/example/lexicons/app/bsky/actor/profile.json
-53
packages/example/lexicons/app/bsky/actor/profile.json
···
1
-
{
2
-
"lexicon": 1,
3
-
"id": "app.bsky.actor.profile",
4
-
"defs": {
5
-
"main": {
6
-
"type": "record",
7
-
"description": "A declaration of a Bluesky account profile.",
8
-
"key": "literal:self",
9
-
"record": {
10
-
"type": "object",
11
-
"properties": {
12
-
"displayName": {
13
-
"type": "string",
14
-
"maxGraphemes": 64,
15
-
"maxLength": 640
16
-
},
17
-
"description": {
18
-
"type": "string",
19
-
"description": "Free-form profile description text.",
20
-
"maxGraphemes": 256,
21
-
"maxLength": 2560
22
-
},
23
-
"avatar": {
24
-
"type": "blob",
25
-
"description": "Small image to be displayed next to posts from account. AKA, 'profile picture'",
26
-
"accept": ["image/png", "image/jpeg"],
27
-
"maxSize": 1000000
28
-
},
29
-
"banner": {
30
-
"type": "blob",
31
-
"description": "Larger horizontal image to display behind profile view.",
32
-
"accept": ["image/png", "image/jpeg"],
33
-
"maxSize": 1000000
34
-
},
35
-
"labels": {
36
-
"type": "union",
37
-
"description": "Self-label values, specific to the Bluesky application, on the overall account.",
38
-
"refs": ["com.atproto.label.defs#selfLabels"]
39
-
},
40
-
"joinedViaStarterPack": {
41
-
"type": "ref",
42
-
"ref": "com.atproto.repo.strongRef"
43
-
},
44
-
"pinnedPost": {
45
-
"type": "ref",
46
-
"ref": "com.atproto.repo.strongRef"
47
-
},
48
-
"createdAt": { "type": "string", "format": "datetime" }
49
-
}
50
-
}
51
-
}
52
-
}
53
-
}
-156
packages/example/lexicons/com/atproto/label/defs.json
-156
packages/example/lexicons/com/atproto/label/defs.json
···
1
-
{
2
-
"lexicon": 1,
3
-
"id": "com.atproto.label.defs",
4
-
"defs": {
5
-
"label": {
6
-
"type": "object",
7
-
"description": "Metadata tag on an atproto resource (eg, repo or record).",
8
-
"required": ["src", "uri", "val", "cts"],
9
-
"properties": {
10
-
"ver": {
11
-
"type": "integer",
12
-
"description": "The AT Protocol version of the label object."
13
-
},
14
-
"src": {
15
-
"type": "string",
16
-
"format": "did",
17
-
"description": "DID of the actor who created this label."
18
-
},
19
-
"uri": {
20
-
"type": "string",
21
-
"format": "uri",
22
-
"description": "AT URI of the record, repository (account), or other resource that this label applies to."
23
-
},
24
-
"cid": {
25
-
"type": "string",
26
-
"format": "cid",
27
-
"description": "Optionally, CID specifying the specific version of 'uri' resource this label applies to."
28
-
},
29
-
"val": {
30
-
"type": "string",
31
-
"maxLength": 128,
32
-
"description": "The short string name of the value or type of this label."
33
-
},
34
-
"neg": {
35
-
"type": "boolean",
36
-
"description": "If true, this is a negation label, overwriting a previous label."
37
-
},
38
-
"cts": {
39
-
"type": "string",
40
-
"format": "datetime",
41
-
"description": "Timestamp when this label was created."
42
-
},
43
-
"exp": {
44
-
"type": "string",
45
-
"format": "datetime",
46
-
"description": "Timestamp at which this label expires (no longer applies)."
47
-
},
48
-
"sig": {
49
-
"type": "bytes",
50
-
"description": "Signature of dag-cbor encoded label."
51
-
}
52
-
}
53
-
},
54
-
"selfLabels": {
55
-
"type": "object",
56
-
"description": "Metadata tags on an atproto record, published by the author within the record.",
57
-
"required": ["values"],
58
-
"properties": {
59
-
"values": {
60
-
"type": "array",
61
-
"items": { "type": "ref", "ref": "#selfLabel" },
62
-
"maxLength": 10
63
-
}
64
-
}
65
-
},
66
-
"selfLabel": {
67
-
"type": "object",
68
-
"description": "Metadata tag on an atproto record, published by the author within the record. Note that schemas should use #selfLabels, not #selfLabel.",
69
-
"required": ["val"],
70
-
"properties": {
71
-
"val": {
72
-
"type": "string",
73
-
"maxLength": 128,
74
-
"description": "The short string name of the value or type of this label."
75
-
}
76
-
}
77
-
},
78
-
"labelValueDefinition": {
79
-
"type": "object",
80
-
"description": "Declares a label value and its expected interpretations and behaviors.",
81
-
"required": ["identifier", "severity", "blurs", "locales"],
82
-
"properties": {
83
-
"identifier": {
84
-
"type": "string",
85
-
"description": "The value of the label being defined. Must only include lowercase ascii and the '-' character ([a-z-]+).",
86
-
"maxLength": 100,
87
-
"maxGraphemes": 100
88
-
},
89
-
"severity": {
90
-
"type": "string",
91
-
"description": "How should a client visually convey this label? 'inform' means neutral and informational; 'alert' means negative and warning; 'none' means show nothing.",
92
-
"knownValues": ["inform", "alert", "none"]
93
-
},
94
-
"blurs": {
95
-
"type": "string",
96
-
"description": "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.",
97
-
"knownValues": ["content", "media", "none"]
98
-
},
99
-
"defaultSetting": {
100
-
"type": "string",
101
-
"description": "The default setting for this label.",
102
-
"knownValues": ["ignore", "warn", "hide"],
103
-
"default": "warn"
104
-
},
105
-
"adultOnly": {
106
-
"type": "boolean",
107
-
"description": "Does the user need to have adult content enabled in order to configure this label?"
108
-
},
109
-
"locales": {
110
-
"type": "array",
111
-
"items": { "type": "ref", "ref": "#labelValueDefinitionStrings" }
112
-
}
113
-
}
114
-
},
115
-
"labelValueDefinitionStrings": {
116
-
"type": "object",
117
-
"description": "Strings which describe the label in the UI, localized into a specific language.",
118
-
"required": ["lang", "name", "description"],
119
-
"properties": {
120
-
"lang": {
121
-
"type": "string",
122
-
"description": "The code of the language these strings are written in.",
123
-
"format": "language"
124
-
},
125
-
"name": {
126
-
"type": "string",
127
-
"description": "A short human-readable name for the label.",
128
-
"maxGraphemes": 64,
129
-
"maxLength": 640
130
-
},
131
-
"description": {
132
-
"type": "string",
133
-
"description": "A longer description of what the label means and why it might be applied.",
134
-
"maxGraphemes": 10000,
135
-
"maxLength": 100000
136
-
}
137
-
}
138
-
},
139
-
"labelValue": {
140
-
"type": "string",
141
-
"knownValues": [
142
-
"!hide",
143
-
"!no-promote",
144
-
"!warn",
145
-
"!no-unauthenticated",
146
-
"dmca-violation",
147
-
"doxxing",
148
-
"porn",
149
-
"sexual",
150
-
"nudity",
151
-
"nsfl",
152
-
"gore"
153
-
]
154
-
}
155
-
}
156
-
}
-131
packages/example/lexicons/com/atproto/repo/applyWrites.json
-131
packages/example/lexicons/com/atproto/repo/applyWrites.json
···
1
-
{
2
-
"lexicon": 1,
3
-
"id": "com.atproto.repo.applyWrites",
4
-
"defs": {
5
-
"main": {
6
-
"type": "procedure",
7
-
"description": "Apply a batch transaction of repository creates, updates, and deletes. Requires auth, implemented by PDS.",
8
-
"input": {
9
-
"encoding": "application/json",
10
-
"schema": {
11
-
"type": "object",
12
-
"required": ["repo", "writes"],
13
-
"properties": {
14
-
"repo": {
15
-
"type": "string",
16
-
"format": "at-identifier",
17
-
"description": "The handle or DID of the repo (aka, current account)."
18
-
},
19
-
"validate": {
20
-
"type": "boolean",
21
-
"description": "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."
22
-
},
23
-
"writes": {
24
-
"type": "array",
25
-
"items": {
26
-
"type": "union",
27
-
"refs": ["#create", "#update", "#delete"],
28
-
"closed": true
29
-
}
30
-
},
31
-
"swapCommit": {
32
-
"type": "string",
33
-
"description": "If provided, the entire operation will fail if the current repo commit CID does not match this value. Used to prevent conflicting repo mutations.",
34
-
"format": "cid"
35
-
}
36
-
}
37
-
}
38
-
},
39
-
"output": {
40
-
"encoding": "application/json",
41
-
"schema": {
42
-
"type": "object",
43
-
"required": [],
44
-
"properties": {
45
-
"commit": {
46
-
"type": "ref",
47
-
"ref": "com.atproto.repo.defs#commitMeta"
48
-
},
49
-
"results": {
50
-
"type": "array",
51
-
"items": {
52
-
"type": "union",
53
-
"refs": ["#createResult", "#updateResult", "#deleteResult"],
54
-
"closed": true
55
-
}
56
-
}
57
-
}
58
-
}
59
-
},
60
-
"errors": [
61
-
{
62
-
"name": "InvalidSwap",
63
-
"description": "Indicates that the 'swapCommit' parameter did not match current commit."
64
-
}
65
-
]
66
-
},
67
-
"create": {
68
-
"type": "object",
69
-
"description": "Operation which creates a new record.",
70
-
"required": ["collection", "value"],
71
-
"properties": {
72
-
"collection": { "type": "string", "format": "nsid" },
73
-
"rkey": {
74
-
"type": "string",
75
-
"maxLength": 512,
76
-
"format": "record-key",
77
-
"description": "NOTE: maxLength is redundant with record-key format. Keeping it temporarily to ensure backwards compatibility."
78
-
},
79
-
"value": { "type": "unknown" }
80
-
}
81
-
},
82
-
"update": {
83
-
"type": "object",
84
-
"description": "Operation which updates an existing record.",
85
-
"required": ["collection", "rkey", "value"],
86
-
"properties": {
87
-
"collection": { "type": "string", "format": "nsid" },
88
-
"rkey": { "type": "string", "format": "record-key" },
89
-
"value": { "type": "unknown" }
90
-
}
91
-
},
92
-
"delete": {
93
-
"type": "object",
94
-
"description": "Operation which deletes an existing record.",
95
-
"required": ["collection", "rkey"],
96
-
"properties": {
97
-
"collection": { "type": "string", "format": "nsid" },
98
-
"rkey": { "type": "string", "format": "record-key" }
99
-
}
100
-
},
101
-
"createResult": {
102
-
"type": "object",
103
-
"required": ["uri", "cid"],
104
-
"properties": {
105
-
"uri": { "type": "string", "format": "at-uri" },
106
-
"cid": { "type": "string", "format": "cid" },
107
-
"validationStatus": {
108
-
"type": "string",
109
-
"knownValues": ["valid", "unknown"]
110
-
}
111
-
}
112
-
},
113
-
"updateResult": {
114
-
"type": "object",
115
-
"required": ["uri", "cid"],
116
-
"properties": {
117
-
"uri": { "type": "string", "format": "at-uri" },
118
-
"cid": { "type": "string", "format": "cid" },
119
-
"validationStatus": {
120
-
"type": "string",
121
-
"knownValues": ["valid", "unknown"]
122
-
}
123
-
}
124
-
},
125
-
"deleteResult": {
126
-
"type": "object",
127
-
"required": [],
128
-
"properties": {}
129
-
}
130
-
}
131
-
}
-73
packages/example/lexicons/com/atproto/repo/createRecord.json
-73
packages/example/lexicons/com/atproto/repo/createRecord.json
···
1
-
{
2
-
"lexicon": 1,
3
-
"id": "com.atproto.repo.createRecord",
4
-
"defs": {
5
-
"main": {
6
-
"type": "procedure",
7
-
"description": "Create a single new repository record. Requires auth, implemented by PDS.",
8
-
"input": {
9
-
"encoding": "application/json",
10
-
"schema": {
11
-
"type": "object",
12
-
"required": ["repo", "collection", "record"],
13
-
"properties": {
14
-
"repo": {
15
-
"type": "string",
16
-
"format": "at-identifier",
17
-
"description": "The handle or DID of the repo (aka, current account)."
18
-
},
19
-
"collection": {
20
-
"type": "string",
21
-
"format": "nsid",
22
-
"description": "The NSID of the record collection."
23
-
},
24
-
"rkey": {
25
-
"type": "string",
26
-
"format": "record-key",
27
-
"description": "The Record Key.",
28
-
"maxLength": 512
29
-
},
30
-
"validate": {
31
-
"type": "boolean",
32
-
"description": "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."
33
-
},
34
-
"record": {
35
-
"type": "unknown",
36
-
"description": "The record itself. Must contain a $type field."
37
-
},
38
-
"swapCommit": {
39
-
"type": "string",
40
-
"format": "cid",
41
-
"description": "Compare and swap with the previous commit by CID."
42
-
}
43
-
}
44
-
}
45
-
},
46
-
"output": {
47
-
"encoding": "application/json",
48
-
"schema": {
49
-
"type": "object",
50
-
"required": ["uri", "cid"],
51
-
"properties": {
52
-
"uri": { "type": "string", "format": "at-uri" },
53
-
"cid": { "type": "string", "format": "cid" },
54
-
"commit": {
55
-
"type": "ref",
56
-
"ref": "com.atproto.repo.defs#commitMeta"
57
-
},
58
-
"validationStatus": {
59
-
"type": "string",
60
-
"knownValues": ["valid", "unknown"]
61
-
}
62
-
}
63
-
}
64
-
},
65
-
"errors": [
66
-
{
67
-
"name": "InvalidSwap",
68
-
"description": "Indicates that 'swapCommit' didn't match current repo commit."
69
-
}
70
-
]
71
-
}
72
-
}
73
-
}
-14
packages/example/lexicons/com/atproto/repo/defs.json
-14
packages/example/lexicons/com/atproto/repo/defs.json
-57
packages/example/lexicons/com/atproto/repo/deleteRecord.json
-57
packages/example/lexicons/com/atproto/repo/deleteRecord.json
···
1
-
{
2
-
"lexicon": 1,
3
-
"id": "com.atproto.repo.deleteRecord",
4
-
"defs": {
5
-
"main": {
6
-
"type": "procedure",
7
-
"description": "Delete a repository record, or ensure it doesn't exist. Requires auth, implemented by PDS.",
8
-
"input": {
9
-
"encoding": "application/json",
10
-
"schema": {
11
-
"type": "object",
12
-
"required": ["repo", "collection", "rkey"],
13
-
"properties": {
14
-
"repo": {
15
-
"type": "string",
16
-
"format": "at-identifier",
17
-
"description": "The handle or DID of the repo (aka, current account)."
18
-
},
19
-
"collection": {
20
-
"type": "string",
21
-
"format": "nsid",
22
-
"description": "The NSID of the record collection."
23
-
},
24
-
"rkey": {
25
-
"type": "string",
26
-
"format": "record-key",
27
-
"description": "The Record Key."
28
-
},
29
-
"swapRecord": {
30
-
"type": "string",
31
-
"format": "cid",
32
-
"description": "Compare and swap with the previous record by CID."
33
-
},
34
-
"swapCommit": {
35
-
"type": "string",
36
-
"format": "cid",
37
-
"description": "Compare and swap with the previous commit by CID."
38
-
}
39
-
}
40
-
}
41
-
},
42
-
"output": {
43
-
"encoding": "application/json",
44
-
"schema": {
45
-
"type": "object",
46
-
"properties": {
47
-
"commit": {
48
-
"type": "ref",
49
-
"ref": "com.atproto.repo.defs#commitMeta"
50
-
}
51
-
}
52
-
}
53
-
},
54
-
"errors": [{ "name": "InvalidSwap" }]
55
-
}
56
-
}
57
-
}
-51
packages/example/lexicons/com/atproto/repo/describeRepo.json
-51
packages/example/lexicons/com/atproto/repo/describeRepo.json
···
1
-
{
2
-
"lexicon": 1,
3
-
"id": "com.atproto.repo.describeRepo",
4
-
"defs": {
5
-
"main": {
6
-
"type": "query",
7
-
"description": "Get information about an account and repository, including the list of collections. Does not require auth.",
8
-
"parameters": {
9
-
"type": "params",
10
-
"required": ["repo"],
11
-
"properties": {
12
-
"repo": {
13
-
"type": "string",
14
-
"format": "at-identifier",
15
-
"description": "The handle or DID of the repo."
16
-
}
17
-
}
18
-
},
19
-
"output": {
20
-
"encoding": "application/json",
21
-
"schema": {
22
-
"type": "object",
23
-
"required": [
24
-
"handle",
25
-
"did",
26
-
"didDoc",
27
-
"collections",
28
-
"handleIsCorrect"
29
-
],
30
-
"properties": {
31
-
"handle": { "type": "string", "format": "handle" },
32
-
"did": { "type": "string", "format": "did" },
33
-
"didDoc": {
34
-
"type": "unknown",
35
-
"description": "The complete DID document for this account."
36
-
},
37
-
"collections": {
38
-
"type": "array",
39
-
"description": "List of all the collections (NSIDs) for which this repo contains at least one record.",
40
-
"items": { "type": "string", "format": "nsid" }
41
-
},
42
-
"handleIsCorrect": {
43
-
"type": "boolean",
44
-
"description": "Indicates if handle is currently valid (resolves bi-directionally)"
45
-
}
46
-
}
47
-
}
48
-
}
49
-
}
50
-
}
51
-
}
-49
packages/example/lexicons/com/atproto/repo/getRecord.json
-49
packages/example/lexicons/com/atproto/repo/getRecord.json
···
1
-
{
2
-
"lexicon": 1,
3
-
"id": "com.atproto.repo.getRecord",
4
-
"defs": {
5
-
"main": {
6
-
"type": "query",
7
-
"description": "Get a single record from a repository. Does not require auth.",
8
-
"parameters": {
9
-
"type": "params",
10
-
"required": ["repo", "collection", "rkey"],
11
-
"properties": {
12
-
"repo": {
13
-
"type": "string",
14
-
"format": "at-identifier",
15
-
"description": "The handle or DID of the repo."
16
-
},
17
-
"collection": {
18
-
"type": "string",
19
-
"format": "nsid",
20
-
"description": "The NSID of the record collection."
21
-
},
22
-
"rkey": {
23
-
"type": "string",
24
-
"description": "The Record Key.",
25
-
"format": "record-key"
26
-
},
27
-
"cid": {
28
-
"type": "string",
29
-
"format": "cid",
30
-
"description": "The CID of the version of the record. If not specified, then return the most recent version."
31
-
}
32
-
}
33
-
},
34
-
"output": {
35
-
"encoding": "application/json",
36
-
"schema": {
37
-
"type": "object",
38
-
"required": ["uri", "value"],
39
-
"properties": {
40
-
"uri": { "type": "string", "format": "at-uri" },
41
-
"cid": { "type": "string", "format": "cid" },
42
-
"value": { "type": "unknown" }
43
-
}
44
-
}
45
-
},
46
-
"errors": [{ "name": "RecordNotFound" }]
47
-
}
48
-
}
49
-
}
-13
packages/example/lexicons/com/atproto/repo/importRepo.json
-13
packages/example/lexicons/com/atproto/repo/importRepo.json
···
1
-
{
2
-
"lexicon": 1,
3
-
"id": "com.atproto.repo.importRepo",
4
-
"defs": {
5
-
"main": {
6
-
"type": "procedure",
7
-
"description": "Import a repo in the form of a CAR file. Requires Content-Length HTTP header to be set.",
8
-
"input": {
9
-
"encoding": "application/vnd.ipld.car"
10
-
}
11
-
}
12
-
}
13
-
}
-44
packages/example/lexicons/com/atproto/repo/listMissingBlobs.json
-44
packages/example/lexicons/com/atproto/repo/listMissingBlobs.json
···
1
-
{
2
-
"lexicon": 1,
3
-
"id": "com.atproto.repo.listMissingBlobs",
4
-
"defs": {
5
-
"main": {
6
-
"type": "query",
7
-
"description": "Returns a list of missing blobs for the requesting account. Intended to be used in the account migration flow.",
8
-
"parameters": {
9
-
"type": "params",
10
-
"properties": {
11
-
"limit": {
12
-
"type": "integer",
13
-
"minimum": 1,
14
-
"maximum": 1000,
15
-
"default": 500
16
-
},
17
-
"cursor": { "type": "string" }
18
-
}
19
-
},
20
-
"output": {
21
-
"encoding": "application/json",
22
-
"schema": {
23
-
"type": "object",
24
-
"required": ["blobs"],
25
-
"properties": {
26
-
"cursor": { "type": "string" },
27
-
"blobs": {
28
-
"type": "array",
29
-
"items": { "type": "ref", "ref": "#recordBlob" }
30
-
}
31
-
}
32
-
}
33
-
}
34
-
},
35
-
"recordBlob": {
36
-
"type": "object",
37
-
"required": ["cid", "recordUri"],
38
-
"properties": {
39
-
"cid": { "type": "string", "format": "cid" },
40
-
"recordUri": { "type": "string", "format": "at-uri" }
41
-
}
42
-
}
43
-
}
44
-
}
-69
packages/example/lexicons/com/atproto/repo/listRecords.json
-69
packages/example/lexicons/com/atproto/repo/listRecords.json
···
1
-
{
2
-
"lexicon": 1,
3
-
"id": "com.atproto.repo.listRecords",
4
-
"defs": {
5
-
"main": {
6
-
"type": "query",
7
-
"description": "List a range of records in a repository, matching a specific collection. Does not require auth.",
8
-
"parameters": {
9
-
"type": "params",
10
-
"required": ["repo", "collection"],
11
-
"properties": {
12
-
"repo": {
13
-
"type": "string",
14
-
"format": "at-identifier",
15
-
"description": "The handle or DID of the repo."
16
-
},
17
-
"collection": {
18
-
"type": "string",
19
-
"format": "nsid",
20
-
"description": "The NSID of the record type."
21
-
},
22
-
"limit": {
23
-
"type": "integer",
24
-
"minimum": 1,
25
-
"maximum": 100,
26
-
"default": 50,
27
-
"description": "The number of records to return."
28
-
},
29
-
"cursor": { "type": "string" },
30
-
"rkeyStart": {
31
-
"type": "string",
32
-
"description": "DEPRECATED: The lowest sort-ordered rkey to start from (exclusive)"
33
-
},
34
-
"rkeyEnd": {
35
-
"type": "string",
36
-
"description": "DEPRECATED: The highest sort-ordered rkey to stop at (exclusive)"
37
-
},
38
-
"reverse": {
39
-
"type": "boolean",
40
-
"description": "Flag to reverse the order of the returned records."
41
-
}
42
-
}
43
-
},
44
-
"output": {
45
-
"encoding": "application/json",
46
-
"schema": {
47
-
"type": "object",
48
-
"required": ["records"],
49
-
"properties": {
50
-
"cursor": { "type": "string" },
51
-
"records": {
52
-
"type": "array",
53
-
"items": { "type": "ref", "ref": "#record" }
54
-
}
55
-
}
56
-
}
57
-
}
58
-
},
59
-
"record": {
60
-
"type": "object",
61
-
"required": ["uri", "cid", "value"],
62
-
"properties": {
63
-
"uri": { "type": "string", "format": "at-uri" },
64
-
"cid": { "type": "string", "format": "cid" },
65
-
"value": { "type": "unknown" }
66
-
}
67
-
}
68
-
}
69
-
}
-74
packages/example/lexicons/com/atproto/repo/putRecord.json
-74
packages/example/lexicons/com/atproto/repo/putRecord.json
···
1
-
{
2
-
"lexicon": 1,
3
-
"id": "com.atproto.repo.putRecord",
4
-
"defs": {
5
-
"main": {
6
-
"type": "procedure",
7
-
"description": "Write a repository record, creating or updating it as needed. Requires auth, implemented by PDS.",
8
-
"input": {
9
-
"encoding": "application/json",
10
-
"schema": {
11
-
"type": "object",
12
-
"required": ["repo", "collection", "rkey", "record"],
13
-
"nullable": ["swapRecord"],
14
-
"properties": {
15
-
"repo": {
16
-
"type": "string",
17
-
"format": "at-identifier",
18
-
"description": "The handle or DID of the repo (aka, current account)."
19
-
},
20
-
"collection": {
21
-
"type": "string",
22
-
"format": "nsid",
23
-
"description": "The NSID of the record collection."
24
-
},
25
-
"rkey": {
26
-
"type": "string",
27
-
"format": "record-key",
28
-
"description": "The Record Key.",
29
-
"maxLength": 512
30
-
},
31
-
"validate": {
32
-
"type": "boolean",
33
-
"description": "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."
34
-
},
35
-
"record": {
36
-
"type": "unknown",
37
-
"description": "The record to write."
38
-
},
39
-
"swapRecord": {
40
-
"type": "string",
41
-
"format": "cid",
42
-
"description": "Compare and swap with the previous record by CID. WARNING: nullable and optional field; may cause problems with golang implementation"
43
-
},
44
-
"swapCommit": {
45
-
"type": "string",
46
-
"format": "cid",
47
-
"description": "Compare and swap with the previous commit by CID."
48
-
}
49
-
}
50
-
}
51
-
},
52
-
"output": {
53
-
"encoding": "application/json",
54
-
"schema": {
55
-
"type": "object",
56
-
"required": ["uri", "cid"],
57
-
"properties": {
58
-
"uri": { "type": "string", "format": "at-uri" },
59
-
"cid": { "type": "string", "format": "cid" },
60
-
"commit": {
61
-
"type": "ref",
62
-
"ref": "com.atproto.repo.defs#commitMeta"
63
-
},
64
-
"validationStatus": {
65
-
"type": "string",
66
-
"knownValues": ["valid", "unknown"]
67
-
}
68
-
}
69
-
}
70
-
},
71
-
"errors": [{ "name": "InvalidSwap" }]
72
-
}
73
-
}
74
-
}
-15
packages/example/lexicons/com/atproto/repo/strongRef.json
-15
packages/example/lexicons/com/atproto/repo/strongRef.json
···
1
-
{
2
-
"lexicon": 1,
3
-
"id": "com.atproto.repo.strongRef",
4
-
"description": "A URI with a content-hash fingerprint.",
5
-
"defs": {
6
-
"main": {
7
-
"type": "object",
8
-
"required": ["uri", "cid"],
9
-
"properties": {
10
-
"uri": { "type": "string", "format": "at-uri" },
11
-
"cid": { "type": "string", "format": "cid" }
12
-
}
13
-
}
14
-
}
15
-
}
-23
packages/example/lexicons/com/atproto/repo/uploadBlob.json
-23
packages/example/lexicons/com/atproto/repo/uploadBlob.json
···
1
-
{
2
-
"lexicon": 1,
3
-
"id": "com.atproto.repo.uploadBlob",
4
-
"defs": {
5
-
"main": {
6
-
"type": "procedure",
7
-
"description": "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.",
8
-
"input": {
9
-
"encoding": "*/*"
10
-
},
11
-
"output": {
12
-
"encoding": "application/json",
13
-
"schema": {
14
-
"type": "object",
15
-
"required": ["blob"],
16
-
"properties": {
17
-
"blob": { "type": "blob" }
18
-
}
19
-
}
20
-
}
21
-
}
22
-
}
23
-
}
-52
packages/example/lexicons/xyz/statusphere/defs.json
-52
packages/example/lexicons/xyz/statusphere/defs.json
···
1
-
{
2
-
"lexicon": 1,
3
-
"id": "xyz.statusphere.defs",
4
-
"defs": {
5
-
"statusView": {
6
-
"type": "object",
7
-
"properties": {
8
-
"uri": {
9
-
"type": "string",
10
-
"format": "at-uri"
11
-
},
12
-
"status": {
13
-
"type": "string",
14
-
"maxLength": 32,
15
-
"minLength": 1,
16
-
"maxGraphemes": 1
17
-
},
18
-
"createdAt": {
19
-
"type": "string",
20
-
"format": "datetime"
21
-
},
22
-
"profile": {
23
-
"type": "ref",
24
-
"ref": "#profileView"
25
-
}
26
-
},
27
-
"required": [
28
-
"uri",
29
-
"status",
30
-
"createdAt",
31
-
"profile"
32
-
]
33
-
},
34
-
"profileView": {
35
-
"type": "object",
36
-
"properties": {
37
-
"did": {
38
-
"type": "string",
39
-
"format": "did"
40
-
},
41
-
"handle": {
42
-
"type": "string",
43
-
"format": "handle"
44
-
}
45
-
},
46
-
"required": [
47
-
"did",
48
-
"handle"
49
-
]
50
-
}
51
-
}
52
-
}
-39
packages/example/lexicons/xyz/statusphere/getStatuses.json
-39
packages/example/lexicons/xyz/statusphere/getStatuses.json
···
1
-
{
2
-
"lexicon": 1,
3
-
"id": "xyz.statusphere.getStatuses",
4
-
"defs": {
5
-
"main": {
6
-
"type": "query",
7
-
"description": "Get a list of the most recent statuses on the network.",
8
-
"parameters": {
9
-
"type": "params",
10
-
"properties": {
11
-
"limit": {
12
-
"type": "integer",
13
-
"minimum": 1,
14
-
"maximum": 100,
15
-
"default": 50
16
-
}
17
-
}
18
-
},
19
-
"output": {
20
-
"encoding": "application/json",
21
-
"schema": {
22
-
"type": "object",
23
-
"properties": {
24
-
"statuses": {
25
-
"type": "array",
26
-
"items": {
27
-
"type": "ref",
28
-
"ref": "xyz.statusphere.defs#statusView"
29
-
}
30
-
}
31
-
},
32
-
"required": [
33
-
"statuses"
34
-
]
35
-
}
36
-
}
37
-
}
38
-
}
39
-
}
-29
packages/example/lexicons/xyz/statusphere/getUser.json
-29
packages/example/lexicons/xyz/statusphere/getUser.json
···
1
-
{
2
-
"lexicon": 1,
3
-
"id": "xyz.statusphere.getUser",
4
-
"defs": {
5
-
"main": {
6
-
"type": "query",
7
-
"description": "Get the current user's profile and status.",
8
-
"output": {
9
-
"encoding": "application/json",
10
-
"schema": {
11
-
"type": "object",
12
-
"properties": {
13
-
"profile": {
14
-
"type": "ref",
15
-
"ref": "app.bsky.actor.defs#profileView"
16
-
},
17
-
"status": {
18
-
"type": "ref",
19
-
"ref": "xyz.statusphere.defs#statusView"
20
-
}
21
-
},
22
-
"required": [
23
-
"profile"
24
-
]
25
-
}
26
-
}
27
-
}
28
-
}
29
-
}
-42
packages/example/lexicons/xyz/statusphere/sendStatus.json
-42
packages/example/lexicons/xyz/statusphere/sendStatus.json
···
1
-
{
2
-
"lexicon": 1,
3
-
"id": "xyz.statusphere.sendStatus",
4
-
"defs": {
5
-
"main": {
6
-
"type": "procedure",
7
-
"description": "Send a status into the ATmosphere.",
8
-
"input": {
9
-
"encoding": "application/json",
10
-
"schema": {
11
-
"type": "object",
12
-
"properties": {
13
-
"status": {
14
-
"type": "string",
15
-
"maxLength": 32,
16
-
"minLength": 1,
17
-
"maxGraphemes": 1
18
-
}
19
-
},
20
-
"required": [
21
-
"status"
22
-
]
23
-
}
24
-
},
25
-
"output": {
26
-
"encoding": "application/json",
27
-
"schema": {
28
-
"type": "object",
29
-
"properties": {
30
-
"status": {
31
-
"type": "ref",
32
-
"ref": "xyz.statusphere.defs#statusView"
33
-
}
34
-
},
35
-
"required": [
36
-
"status"
37
-
]
38
-
}
39
-
}
40
-
}
41
-
}
42
-
}
-29
packages/example/lexicons/xyz/statusphere/status.json
-29
packages/example/lexicons/xyz/statusphere/status.json
···
1
-
{
2
-
"lexicon": 1,
3
-
"id": "xyz.statusphere.status",
4
-
"defs": {
5
-
"main": {
6
-
"type": "record",
7
-
"key": "tid",
8
-
"record": {
9
-
"type": "object",
10
-
"properties": {
11
-
"status": {
12
-
"type": "string",
13
-
"maxLength": 32,
14
-
"minLength": 1,
15
-
"maxGraphemes": 1
16
-
},
17
-
"createdAt": {
18
-
"type": "string",
19
-
"format": "datetime"
20
-
}
21
-
},
22
-
"required": [
23
-
"status",
24
-
"createdAt"
25
-
]
26
-
}
27
-
}
28
-
}
29
-
}
+2
-2
packages/example/package.json
+2
-2
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": "typelex compile xyz.statusphere.*",
7
+
"build": "pnpm run build:lexicons && pnpm run build:codegen",
8
+
"build:lexicons": "typelex compile xyz.statusphere.*",
9
9
"build:codegen": "lex gen-server --yes ./src lexicons/xyz/statusphere/*.json"
10
10
},
11
11
"dependencies": {
+154
-1
packages/example/typelex/externals.tsp
+154
-1
packages/example/typelex/externals.tsp
···
1
1
import "@typelex/emitter";
2
2
3
-
// Generated by typelex from ./lexicons (excluding xyz.statusphere.*)
3
+
// Generated by typelex
4
4
// This file is auto-generated. Do not edit manually.
5
5
6
6
@external
7
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 { }
8
26
model ProfileView { }
27
+
model ProfileViewBasic { }
28
+
model ProfileViewDetailed { }
29
+
model SavedFeed { }
30
+
model SavedFeedsPref { }
31
+
model SavedFeedsPrefV2 { }
32
+
model ThreadViewPref { }
33
+
model ViewerState { }
9
34
}
10
35
11
36
@external
12
37
namespace app.bsky.actor.profile {
13
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 { }
14
167
}
15
168
16
169
@external