@atcute/lex-cli 2.5.2 → 2.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/codegen.d.ts +1 -7
- package/dist/codegen.d.ts.map +1 -1
- package/dist/codegen.js +20 -42
- package/dist/codegen.js.map +1 -1
- package/dist/commands/export.d.ts +2 -6
- package/dist/commands/export.d.ts.map +1 -1
- package/dist/commands/export.js +5 -17
- package/dist/commands/export.js.map +1 -1
- package/dist/commands/generate.d.ts +2 -6
- package/dist/commands/generate.d.ts.map +1 -1
- package/dist/commands/generate.js +12 -10
- package/dist/commands/generate.js.map +1 -1
- package/dist/commands/pull.d.ts +2 -6
- package/dist/commands/pull.d.ts.map +1 -1
- package/dist/commands/pull.js +12 -17
- package/dist/commands/pull.js.map +1 -1
- package/dist/config.d.ts +17 -2
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +21 -3
- package/dist/config.js.map +1 -1
- package/dist/formatter.d.ts +19 -0
- package/dist/formatter.d.ts.map +1 -0
- package/dist/formatter.js +111 -0
- package/dist/formatter.js.map +1 -0
- package/dist/git.d.ts.map +1 -1
- package/dist/git.js.map +1 -1
- package/dist/index.d.ts +2 -66
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/lexicon-loader.d.ts.map +1 -1
- package/dist/lexicon-loader.js +9 -1
- package/dist/lexicon-loader.js.map +1 -1
- package/dist/lexicon-metadata.d.ts.map +1 -1
- package/dist/lexicon-metadata.js +1 -1
- package/dist/lexicon-metadata.js.map +1 -1
- package/dist/pull-sources/atproto.d.ts +3 -11
- package/dist/pull-sources/atproto.d.ts.map +1 -1
- package/dist/pull-sources/atproto.js.map +1 -1
- package/dist/pull-sources/git.d.ts +3 -7
- package/dist/pull-sources/git.d.ts.map +1 -1
- package/dist/pull-sources/git.js.map +1 -1
- package/dist/shared-options.d.ts +1 -1
- package/package.json +18 -15
- package/src/cli.ts +3 -3
- package/src/codegen.ts +47 -72
- package/src/commands/export.ts +9 -20
- package/src/commands/generate.ts +21 -17
- package/src/commands/pull.ts +18 -23
- package/src/config.ts +19 -4
- package/src/formatter.ts +145 -0
- package/src/index.ts +1 -1
- package/src/lexicon-metadata.ts +2 -2
- package/src/pull-sources/atproto.ts +4 -2
- package/src/pull-sources/git.ts +5 -3
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"git.js","sourceRoot":"","sources":["../../src/pull-sources/git.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,kBAAkB,CAAC;AACvC,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"git.js","sourceRoot":"","sources":["../../src/pull-sources/git.ts"],"names":[],"mappings":"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"}
|
package/dist/shared-options.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export declare const sharedOptions: import("@optique/core/parser").Parser<{
|
|
1
|
+
export declare const sharedOptions: import("@optique/core/parser").Parser<"sync", {
|
|
2
2
|
readonly config: string | undefined;
|
|
3
3
|
}, {
|
|
4
4
|
readonly config: [import("@optique/core/valueparser").ValueParserResult<string> | undefined] | undefined;
|
package/package.json
CHANGED
|
@@ -1,39 +1,42 @@
|
|
|
1
1
|
{
|
|
2
|
-
"type": "module",
|
|
3
2
|
"name": "@atcute/lex-cli",
|
|
4
|
-
"version": "2.
|
|
3
|
+
"version": "2.6.0",
|
|
5
4
|
"description": "cli tool to generate type definitions for atcute",
|
|
6
5
|
"license": "0BSD",
|
|
7
6
|
"repository": {
|
|
8
7
|
"url": "https://github.com/mary-ext/atcute",
|
|
9
8
|
"directory": "packages/lexicons/lex-cli"
|
|
10
9
|
},
|
|
10
|
+
"bin": "./cli.mjs",
|
|
11
11
|
"files": [
|
|
12
|
+
"cli.mjs",
|
|
12
13
|
"dist/",
|
|
14
|
+
"schema/",
|
|
13
15
|
"src/",
|
|
14
16
|
"!src/**/*.bench.ts",
|
|
15
|
-
"!src/**/*.test.ts"
|
|
16
|
-
"cli.mjs",
|
|
17
|
-
"schema/"
|
|
17
|
+
"!src/**/*.test.ts"
|
|
18
18
|
],
|
|
19
|
-
"
|
|
19
|
+
"type": "module",
|
|
20
20
|
"exports": {
|
|
21
21
|
".": "./dist/index.js"
|
|
22
22
|
},
|
|
23
|
+
"publishConfig": {
|
|
24
|
+
"access": "public"
|
|
25
|
+
},
|
|
23
26
|
"dependencies": {
|
|
24
27
|
"@badrap/valita": "^0.4.6",
|
|
25
|
-
"@optique/core": "^0.
|
|
26
|
-
"@optique/run": "^0.
|
|
28
|
+
"@optique/core": "^0.10.7",
|
|
29
|
+
"@optique/run": "^0.10.7",
|
|
27
30
|
"picocolors": "^1.1.1",
|
|
28
|
-
"prettier": "^3.
|
|
29
|
-
"@atcute/identity": "^1.1.
|
|
30
|
-
"@atcute/identity-resolver": "^1.2.
|
|
31
|
-
"@atcute/lexicon-
|
|
32
|
-
"@atcute/lexicon-
|
|
33
|
-
"@atcute/lexicons": "^1.2.
|
|
31
|
+
"prettier": "^3.8.1",
|
|
32
|
+
"@atcute/identity": "^1.1.4",
|
|
33
|
+
"@atcute/identity-resolver": "^1.2.2",
|
|
34
|
+
"@atcute/lexicon-doc": "^2.1.2",
|
|
35
|
+
"@atcute/lexicon-resolver": "^0.1.6",
|
|
36
|
+
"@atcute/lexicons": "^1.2.9"
|
|
34
37
|
},
|
|
35
38
|
"devDependencies": {
|
|
36
|
-
"@types/node": "^
|
|
39
|
+
"@types/node": "^25.5.2",
|
|
37
40
|
"tschema": "^3.2.0"
|
|
38
41
|
},
|
|
39
42
|
"scripts": {
|
package/src/cli.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { or } from '@optique/core/constructs';
|
|
2
2
|
import { run } from '@optique/run';
|
|
3
3
|
|
|
4
|
-
import { exportCommandSchema, runExport } from './commands/export.
|
|
5
|
-
import { generateCommandSchema, runGenerate } from './commands/generate.
|
|
6
|
-
import { pullCommandSchema, runPull } from './commands/pull.
|
|
4
|
+
import { exportCommandSchema, runExport } from './commands/export.ts';
|
|
5
|
+
import { generateCommandSchema, runGenerate } from './commands/generate.ts';
|
|
6
|
+
import { pullCommandSchema, runPull } from './commands/pull.ts';
|
|
7
7
|
|
|
8
8
|
const parser = or(generateCommandSchema, pullCommandSchema, exportCommandSchema);
|
|
9
9
|
|
package/src/codegen.ts
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
import { dirname as getDirname, relative as getRelativePath } from 'node:path/posix';
|
|
2
2
|
|
|
3
|
-
import * as prettier from 'prettier';
|
|
4
|
-
|
|
5
3
|
import type {
|
|
6
4
|
LexDefinableField,
|
|
7
5
|
LexiconDoc,
|
|
@@ -16,6 +14,7 @@ import type {
|
|
|
16
14
|
LexXrpcQuery,
|
|
17
15
|
LexXrpcSubscription,
|
|
18
16
|
} from '@atcute/lexicon-doc';
|
|
17
|
+
import { formatLexiconRef, parseLexiconRef, type ParsedLexiconRef } from '@atcute/lexicon-doc';
|
|
19
18
|
|
|
20
19
|
export interface SourceFile {
|
|
21
20
|
filename: string;
|
|
@@ -33,13 +32,6 @@ export interface LexiconApiOptions {
|
|
|
33
32
|
modules: {
|
|
34
33
|
importSuffix: string;
|
|
35
34
|
};
|
|
36
|
-
prettier: {
|
|
37
|
-
cwd: string;
|
|
38
|
-
};
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
export interface LexiconApiResult {
|
|
42
|
-
files: SourceFile[];
|
|
43
35
|
}
|
|
44
36
|
|
|
45
37
|
type DocumentMap = Map<string, LexiconDoc>;
|
|
@@ -49,31 +41,8 @@ type Literal = string | number | boolean;
|
|
|
49
41
|
|
|
50
42
|
const lit: (val: Literal | Literal[]) => string = JSON.stringify;
|
|
51
43
|
|
|
52
|
-
|
|
53
|
-
nsid
|
|
54
|
-
defId: string;
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
const toLexUri = (path: LexPath): string => {
|
|
58
|
-
const { nsid, defId } = path;
|
|
59
|
-
return defId === 'main' ? nsid : `${nsid}#${defId}`;
|
|
60
|
-
};
|
|
61
|
-
|
|
62
|
-
const resolvePath = (from: LexPath, ref: string): LexPath => {
|
|
63
|
-
const index = ref.indexOf('#');
|
|
64
|
-
|
|
65
|
-
// nsid (no hash)
|
|
66
|
-
if (index === -1) {
|
|
67
|
-
return { nsid: ref, defId: 'main' };
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
// #defId (local ref)
|
|
71
|
-
if (index === 0) {
|
|
72
|
-
return { nsid: from.nsid, defId: ref.slice(1) };
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
// nsid#defId (full ref)
|
|
76
|
-
return { nsid: ref.slice(0, index), defId: ref.slice(index + 1) };
|
|
44
|
+
const resolvePath = (from: ParsedLexiconRef, ref: string): ParsedLexiconRef => {
|
|
45
|
+
return parseLexiconRef(ref, from.nsid);
|
|
77
46
|
};
|
|
78
47
|
|
|
79
48
|
const resolveExternalImport = (nsid: string, mappings: ImportMapping[]): ImportMapping | undefined => {
|
|
@@ -90,7 +59,7 @@ const resolveExternalImport = (nsid: string, mappings: ImportMapping[]): ImportM
|
|
|
90
59
|
|
|
91
60
|
const PURE = `/*#__PURE__*/`;
|
|
92
61
|
|
|
93
|
-
export
|
|
62
|
+
export function* generateLexiconApi(opts: LexiconApiOptions): Generator<SourceFile> {
|
|
94
63
|
const importExt = opts.modules?.importSuffix;
|
|
95
64
|
|
|
96
65
|
const documents = opts.documents.toSorted((a, b) => {
|
|
@@ -105,7 +74,6 @@ export const generateLexiconApi = async (opts: LexiconApiOptions): Promise<Lexic
|
|
|
105
74
|
});
|
|
106
75
|
|
|
107
76
|
const map: DocumentMap = new Map(documents.map((doc) => [doc.id, doc]));
|
|
108
|
-
const files: SourceFile[] = [];
|
|
109
77
|
const generatedIds = new Set<string>();
|
|
110
78
|
|
|
111
79
|
for (const doc of documents) {
|
|
@@ -139,7 +107,7 @@ export const generateLexiconApi = async (opts: LexiconApiOptions): Promise<Lexic
|
|
|
139
107
|
|
|
140
108
|
for (const defId of sortedDefIds) {
|
|
141
109
|
const def = doc.defs[defId];
|
|
142
|
-
const path:
|
|
110
|
+
const path: ParsedLexiconRef = { nsid: doc.id, defId };
|
|
143
111
|
|
|
144
112
|
const camelcased = toCamelCase(defId);
|
|
145
113
|
const varname = `${camelcased}Schema`;
|
|
@@ -153,7 +121,7 @@ export const generateLexiconApi = async (opts: LexiconApiOptions): Promise<Lexic
|
|
|
153
121
|
|
|
154
122
|
file.ambients += `declare module '@atcute/lexicons/ambient' {\n`;
|
|
155
123
|
file.ambients += ` interface XRPCQueries {\n`;
|
|
156
|
-
file.ambients += ` ${lit(
|
|
124
|
+
file.ambients += ` ${lit(formatLexiconRef(path))}: ${camelcased}Schema;\n`;
|
|
157
125
|
file.ambients += ` }\n`;
|
|
158
126
|
file.ambients += `}`;
|
|
159
127
|
break;
|
|
@@ -165,7 +133,7 @@ export const generateLexiconApi = async (opts: LexiconApiOptions): Promise<Lexic
|
|
|
165
133
|
|
|
166
134
|
file.ambients += `declare module '@atcute/lexicons/ambient' {\n`;
|
|
167
135
|
file.ambients += ` interface XRPCProcedures {\n`;
|
|
168
|
-
file.ambients += ` ${lit(
|
|
136
|
+
file.ambients += ` ${lit(formatLexiconRef(path))}: ${camelcased}Schema;\n`;
|
|
169
137
|
file.ambients += ` }\n`;
|
|
170
138
|
file.ambients += `}`;
|
|
171
139
|
break;
|
|
@@ -177,7 +145,7 @@ export const generateLexiconApi = async (opts: LexiconApiOptions): Promise<Lexic
|
|
|
177
145
|
|
|
178
146
|
file.ambients += `declare module '@atcute/lexicons/ambient' {\n`;
|
|
179
147
|
file.ambients += ` interface XRPCSubscriptions {\n`;
|
|
180
|
-
file.ambients += ` ${lit(
|
|
148
|
+
file.ambients += ` ${lit(formatLexiconRef(path))}: ${camelcased}Schema;\n`;
|
|
181
149
|
file.ambients += ` }\n`;
|
|
182
150
|
file.ambients += `}`;
|
|
183
151
|
break;
|
|
@@ -193,13 +161,13 @@ export const generateLexiconApi = async (opts: LexiconApiOptions): Promise<Lexic
|
|
|
193
161
|
|
|
194
162
|
file.ambients += `declare module '@atcute/lexicons/ambient' {\n`;
|
|
195
163
|
file.ambients += ` interface Records {\n`;
|
|
196
|
-
file.ambients += ` ${lit(
|
|
164
|
+
file.ambients += ` ${lit(formatLexiconRef(path))}: ${camelcased}Schema;\n`;
|
|
197
165
|
file.ambients += ` }\n`;
|
|
198
166
|
file.ambients += `}`;
|
|
199
167
|
break;
|
|
200
168
|
}
|
|
201
169
|
case 'token': {
|
|
202
|
-
result = `${PURE} v.literal(${lit(
|
|
170
|
+
result = `${PURE} v.literal(${lit(formatLexiconRef(path))})`;
|
|
203
171
|
break;
|
|
204
172
|
}
|
|
205
173
|
case 'permission-set': {
|
|
@@ -358,7 +326,7 @@ export const generateLexiconApi = async (opts: LexiconApiOptions): Promise<Lexic
|
|
|
358
326
|
if (file.exports) {
|
|
359
327
|
generatedIds.add(doc.id);
|
|
360
328
|
|
|
361
|
-
|
|
329
|
+
yield {
|
|
362
330
|
filename: filename,
|
|
363
331
|
code:
|
|
364
332
|
file.imports +
|
|
@@ -376,7 +344,7 @@ export const generateLexiconApi = async (opts: LexiconApiOptions): Promise<Lexic
|
|
|
376
344
|
file.sinterfaces +
|
|
377
345
|
`\n\n` +
|
|
378
346
|
file.ambients,
|
|
379
|
-
}
|
|
347
|
+
};
|
|
380
348
|
}
|
|
381
349
|
}
|
|
382
350
|
|
|
@@ -391,40 +359,37 @@ export const generateLexiconApi = async (opts: LexiconApiOptions): Promise<Lexic
|
|
|
391
359
|
code += `export * as ${toTitleCase(doc.id)} from ${lit(`./types/${doc.id.replaceAll('.', '/')}${importExt}`)};\n`;
|
|
392
360
|
}
|
|
393
361
|
|
|
394
|
-
|
|
362
|
+
yield {
|
|
395
363
|
filename: 'index.ts',
|
|
396
364
|
code: code,
|
|
397
|
-
}
|
|
398
|
-
}
|
|
399
|
-
|
|
400
|
-
if (opts.prettier) {
|
|
401
|
-
const config = await prettier.resolveConfig(opts.prettier.cwd, { editorconfig: true });
|
|
402
|
-
|
|
403
|
-
for (const file of files) {
|
|
404
|
-
const formatted = await prettier.format(file.code, { ...config, parser: 'typescript' });
|
|
405
|
-
file.code = formatted;
|
|
406
|
-
}
|
|
365
|
+
};
|
|
407
366
|
}
|
|
367
|
+
}
|
|
408
368
|
|
|
409
|
-
|
|
410
|
-
};
|
|
411
|
-
|
|
412
|
-
const generateXrpcQuery = (imports: ImportSet, path: LexPath, spec: LexXrpcQuery): string => {
|
|
369
|
+
const generateXrpcQuery = (imports: ImportSet, path: ParsedLexiconRef, spec: LexXrpcQuery): string => {
|
|
413
370
|
const params = generateXrpcParameters(imports, path, spec.parameters);
|
|
414
371
|
const output = generateXrpcBody(imports, path, spec.output);
|
|
415
372
|
|
|
416
|
-
return `${PURE} v.query(${lit(
|
|
373
|
+
return `${PURE} v.query(${lit(formatLexiconRef(path))}, {\n"params": ${params}, "output": ${output} })`;
|
|
417
374
|
};
|
|
418
375
|
|
|
419
|
-
const generateXrpcProcedure = (
|
|
376
|
+
const generateXrpcProcedure = (
|
|
377
|
+
imports: ImportSet,
|
|
378
|
+
path: ParsedLexiconRef,
|
|
379
|
+
spec: LexXrpcProcedure,
|
|
380
|
+
): string => {
|
|
420
381
|
const params = generateXrpcParameters(imports, path, spec.parameters);
|
|
421
382
|
const input = generateXrpcBody(imports, path, spec.input);
|
|
422
383
|
const output = generateXrpcBody(imports, path, spec.output);
|
|
423
384
|
|
|
424
|
-
return `${PURE} v.procedure(${lit(
|
|
385
|
+
return `${PURE} v.procedure(${lit(formatLexiconRef(path))}, {\n"params": ${params}, "input": ${input}, "output": ${output} })`;
|
|
425
386
|
};
|
|
426
387
|
|
|
427
|
-
const generateXrpcSubscription = (
|
|
388
|
+
const generateXrpcSubscription = (
|
|
389
|
+
imports: ImportSet,
|
|
390
|
+
path: ParsedLexiconRef,
|
|
391
|
+
spec: LexXrpcSubscription,
|
|
392
|
+
): string => {
|
|
428
393
|
const schema = spec.message?.schema;
|
|
429
394
|
|
|
430
395
|
const params = generateXrpcParameters(imports, path, spec.parameters);
|
|
@@ -441,10 +406,14 @@ const generateXrpcSubscription = (imports: ImportSet, path: LexPath, spec: LexXr
|
|
|
441
406
|
inner += `"message": null,`;
|
|
442
407
|
}
|
|
443
408
|
|
|
444
|
-
return `${PURE} v.subscription(${lit(
|
|
409
|
+
return `${PURE} v.subscription(${lit(formatLexiconRef(path))}, {\n${inner}})`;
|
|
445
410
|
};
|
|
446
411
|
|
|
447
|
-
const generateXrpcBody = (
|
|
412
|
+
const generateXrpcBody = (
|
|
413
|
+
imports: ImportSet,
|
|
414
|
+
path: ParsedLexiconRef,
|
|
415
|
+
spec: LexXrpcBody | undefined,
|
|
416
|
+
): string => {
|
|
448
417
|
if (spec === undefined) {
|
|
449
418
|
return `null`;
|
|
450
419
|
}
|
|
@@ -489,7 +458,7 @@ const generateXrpcBody = (imports: ImportSet, path: LexPath, spec: LexXrpcBody |
|
|
|
489
458
|
|
|
490
459
|
const generateXrpcParameters = (
|
|
491
460
|
imports: ImportSet,
|
|
492
|
-
path:
|
|
461
|
+
path: ParsedLexiconRef,
|
|
493
462
|
spec: LexXrpcParameters | undefined,
|
|
494
463
|
): string => {
|
|
495
464
|
if (spec === undefined) {
|
|
@@ -529,7 +498,7 @@ const generateXrpcParameters = (
|
|
|
529
498
|
return generateObject(imports, path, mask, 'none');
|
|
530
499
|
};
|
|
531
500
|
|
|
532
|
-
const generateRecord = (imports: ImportSet, path:
|
|
501
|
+
const generateRecord = (imports: ImportSet, path: ParsedLexiconRef, spec: LexRecord): string => {
|
|
533
502
|
const schema = generateObject(imports, path, spec.record, 'required');
|
|
534
503
|
|
|
535
504
|
let key = `${PURE} v.string()`;
|
|
@@ -548,7 +517,7 @@ const generateRecord = (imports: ImportSet, path: LexPath, spec: LexRecord): str
|
|
|
548
517
|
|
|
549
518
|
const generateObject = (
|
|
550
519
|
imports: ImportSet,
|
|
551
|
-
path:
|
|
520
|
+
path: ParsedLexiconRef,
|
|
552
521
|
spec: LexObject,
|
|
553
522
|
writeType: 'required' | 'optional' | 'none' = 'optional',
|
|
554
523
|
): string => {
|
|
@@ -559,11 +528,11 @@ const generateObject = (
|
|
|
559
528
|
|
|
560
529
|
switch (writeType) {
|
|
561
530
|
case 'optional': {
|
|
562
|
-
inner += `"$type": ${PURE} v.optional(${PURE} v.literal(${lit(
|
|
531
|
+
inner += `"$type": ${PURE} v.optional(${PURE} v.literal(${lit(formatLexiconRef(path))})),`;
|
|
563
532
|
break;
|
|
564
533
|
}
|
|
565
534
|
case 'required': {
|
|
566
|
-
inner += `"$type": ${PURE} v.literal(${lit(
|
|
535
|
+
inner += `"$type": ${PURE} v.literal(${lit(formatLexiconRef(path))}),`;
|
|
567
536
|
break;
|
|
568
537
|
}
|
|
569
538
|
}
|
|
@@ -715,7 +684,12 @@ const generateJsdocField = (spec: LexUserType | LexRefVariant | LexUnknown) => {
|
|
|
715
684
|
return res;
|
|
716
685
|
};
|
|
717
686
|
|
|
718
|
-
const generateType = (
|
|
687
|
+
const generateType = (
|
|
688
|
+
imports: ImportSet,
|
|
689
|
+
path: ParsedLexiconRef,
|
|
690
|
+
spec: LexDefinableField,
|
|
691
|
+
lazy = false,
|
|
692
|
+
): string => {
|
|
719
693
|
switch (spec.type) {
|
|
720
694
|
// LexRefVariant
|
|
721
695
|
case 'ref': {
|
|
@@ -732,8 +706,9 @@ const generateType = (imports: ImportSet, path: LexPath, spec: LexDefinableField
|
|
|
732
706
|
const refs = spec.refs
|
|
733
707
|
.map((ref) => {
|
|
734
708
|
const refPath = resolvePath(path, ref);
|
|
735
|
-
return { path: refPath, uri:
|
|
709
|
+
return { path: refPath, uri: formatLexiconRef(refPath) };
|
|
736
710
|
})
|
|
711
|
+
// oxlint-disable-next-line unicorn/no-array-sort -- map already clones
|
|
737
712
|
.sort((a, b) => {
|
|
738
713
|
if (a.uri < b.uri) {
|
|
739
714
|
return -1;
|
package/src/commands/export.ts
CHANGED
|
@@ -2,16 +2,17 @@ import * as fs from 'node:fs/promises';
|
|
|
2
2
|
import * as path from 'node:path';
|
|
3
3
|
|
|
4
4
|
import type { LexiconDoc } from '@atcute/lexicon-doc';
|
|
5
|
+
|
|
5
6
|
import { merge, object } from '@optique/core/constructs';
|
|
6
7
|
import { message } from '@optique/core/message';
|
|
7
8
|
import { type InferValue } from '@optique/core/parser';
|
|
8
9
|
import { command, constant } from '@optique/core/primitives';
|
|
9
10
|
import pc from 'picocolors';
|
|
10
|
-
import prettier from 'prettier';
|
|
11
11
|
|
|
12
|
-
import { loadConfig, type ExportConfig, type NormalizedConfig } from '../config.
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
12
|
+
import { loadConfig, type ExportConfig, type NormalizedConfig } from '../config.ts';
|
|
13
|
+
import { createFormatter, type Formatter } from '../formatter.ts';
|
|
14
|
+
import { loadLexicons } from '../lexicon-loader.ts';
|
|
15
|
+
import { sharedOptions } from '../shared-options.ts';
|
|
15
16
|
|
|
16
17
|
export const exportCommandSchema = command(
|
|
17
18
|
'export',
|
|
@@ -43,27 +44,17 @@ const ensureExportConfig = (config: NormalizedConfig): ExportConfig => {
|
|
|
43
44
|
return config.export;
|
|
44
45
|
};
|
|
45
46
|
|
|
46
|
-
/**
|
|
47
|
-
* writes a lexicon document to disk as formatted JSON
|
|
48
|
-
* @param outdir output directory
|
|
49
|
-
* @param nsid the NSID of the lexicon
|
|
50
|
-
* @param doc the lexicon document
|
|
51
|
-
* @param prettierConfig prettier configuration
|
|
52
|
-
*/
|
|
53
47
|
const writeLexicon = async (
|
|
54
48
|
outdir: string,
|
|
55
49
|
nsid: string,
|
|
56
50
|
doc: LexiconDoc,
|
|
57
|
-
|
|
51
|
+
formatter: Formatter,
|
|
58
52
|
): Promise<void> => {
|
|
59
53
|
const nsidPath = nsid.replaceAll('.', '/');
|
|
60
54
|
const target = path.join(outdir, `${nsidPath}.json`);
|
|
61
55
|
const dirname = path.dirname(target);
|
|
62
56
|
|
|
63
|
-
const code = await
|
|
64
|
-
...(prettierConfig ?? {}),
|
|
65
|
-
parser: 'json',
|
|
66
|
-
});
|
|
57
|
+
const code = await formatter.format(JSON.stringify(doc, null, 2), target);
|
|
67
58
|
|
|
68
59
|
await fs.mkdir(dirname, { recursive: true });
|
|
69
60
|
await fs.writeFile(target, code);
|
|
@@ -80,7 +71,7 @@ export const runExport = async (args: ExportCommand): Promise<void> => {
|
|
|
80
71
|
// use export.files if specified, otherwise fall back to root files config
|
|
81
72
|
const files = exportConfig.files ?? config.files;
|
|
82
73
|
const outdir = path.resolve(config.root, exportConfig.outdir);
|
|
83
|
-
const
|
|
74
|
+
const formatter = await createFormatter(config.formatter, config.root);
|
|
84
75
|
|
|
85
76
|
// load lexicons from files
|
|
86
77
|
const loaded = await loadLexicons(files, config.root);
|
|
@@ -98,9 +89,7 @@ export const runExport = async (args: ExportCommand): Promise<void> => {
|
|
|
98
89
|
await fs.mkdir(outdir, { recursive: true });
|
|
99
90
|
|
|
100
91
|
// write each lexicon as JSON
|
|
101
|
-
|
|
102
|
-
await writeLexicon(outdir, nsid, doc, prettierConfig);
|
|
103
|
-
}
|
|
92
|
+
await Promise.all(loaded.map(({ nsid, doc }) => writeLexicon(outdir, nsid, doc, formatter)));
|
|
104
93
|
|
|
105
94
|
console.log(pc.green(`exported ${loaded.length} lexicon(s) to ${outdir}`));
|
|
106
95
|
};
|
package/src/commands/generate.ts
CHANGED
|
@@ -7,11 +7,12 @@ import { type InferValue } from '@optique/core/parser';
|
|
|
7
7
|
import { command, constant } from '@optique/core/primitives';
|
|
8
8
|
import pc from 'picocolors';
|
|
9
9
|
|
|
10
|
-
import { generateLexiconApi, type ImportMapping } from '../codegen.
|
|
11
|
-
import { loadConfig } from '../config.
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
10
|
+
import { generateLexiconApi, type ImportMapping } from '../codegen.ts';
|
|
11
|
+
import { loadConfig } from '../config.ts';
|
|
12
|
+
import { createFormatter } from '../formatter.ts';
|
|
13
|
+
import { loadLexicons } from '../lexicon-loader.ts';
|
|
14
|
+
import { packageJsonSchema } from '../lexicon-metadata.ts';
|
|
15
|
+
import { sharedOptions } from '../shared-options.ts';
|
|
15
16
|
|
|
16
17
|
/**
|
|
17
18
|
* resolves package imports to ImportMapping[]
|
|
@@ -147,24 +148,27 @@ export const runGenerate = async (args: GenerateCommand): Promise<void> => {
|
|
|
147
148
|
const loaded = await loadLexicons(config.files, config.root);
|
|
148
149
|
const documents = loaded.map((l) => l.doc);
|
|
149
150
|
|
|
150
|
-
const
|
|
151
|
+
const outdir = path.join(config.root, config.outdir);
|
|
152
|
+
const formatter = await createFormatter(config.formatter, config.root);
|
|
153
|
+
const pending: Promise<void>[] = [];
|
|
154
|
+
|
|
155
|
+
for (const file of generateLexiconApi({
|
|
151
156
|
documents: documents,
|
|
152
157
|
mappings: allMappings,
|
|
153
158
|
modules: {
|
|
154
159
|
importSuffix: config.modules?.importSuffix ?? '.js',
|
|
155
160
|
},
|
|
156
|
-
|
|
157
|
-
cwd: process.cwd(),
|
|
158
|
-
},
|
|
159
|
-
});
|
|
160
|
-
|
|
161
|
-
const outdir = path.join(config.root, config.outdir);
|
|
162
|
-
|
|
163
|
-
for (const file of generationResult.files) {
|
|
161
|
+
})) {
|
|
164
162
|
const filename = path.join(outdir, file.filename);
|
|
165
|
-
const dirname = path.dirname(filename);
|
|
166
163
|
|
|
167
|
-
|
|
168
|
-
|
|
164
|
+
pending.push(
|
|
165
|
+
(async () => {
|
|
166
|
+
const formatted = await formatter.format(file.code, filename);
|
|
167
|
+
await fs.mkdir(path.dirname(filename), { recursive: true });
|
|
168
|
+
await fs.writeFile(filename, formatted);
|
|
169
|
+
})(),
|
|
170
|
+
);
|
|
169
171
|
}
|
|
172
|
+
|
|
173
|
+
await Promise.all(pending);
|
|
170
174
|
};
|
package/src/commands/pull.ts
CHANGED
|
@@ -2,18 +2,19 @@ import * as fs from 'node:fs/promises';
|
|
|
2
2
|
import * as path from 'node:path';
|
|
3
3
|
|
|
4
4
|
import { lexiconDoc, refineLexiconDoc, type LexiconDoc } from '@atcute/lexicon-doc';
|
|
5
|
+
|
|
5
6
|
import { merge, object } from '@optique/core/constructs';
|
|
6
7
|
import { message } from '@optique/core/message';
|
|
7
8
|
import { type InferValue } from '@optique/core/parser';
|
|
8
9
|
import { command, constant } from '@optique/core/primitives';
|
|
9
10
|
import pc from 'picocolors';
|
|
10
|
-
import prettier from 'prettier';
|
|
11
11
|
|
|
12
|
-
import { loadConfig, type NormalizedConfig, type PullConfig, type SourceConfig } from '../config.
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
15
|
-
import
|
|
16
|
-
import {
|
|
12
|
+
import { loadConfig, type NormalizedConfig, type PullConfig, type SourceConfig } from '../config.ts';
|
|
13
|
+
import { createFormatter, type Formatter } from '../formatter.ts';
|
|
14
|
+
import { pullAtprotoSource } from '../pull-sources/atproto.ts';
|
|
15
|
+
import { pullGitSource } from '../pull-sources/git.ts';
|
|
16
|
+
import type { PullResult, PulledLexicon, SourceLocation } from '../pull-sources/types.ts';
|
|
17
|
+
import { sharedOptions } from '../shared-options.ts';
|
|
17
18
|
|
|
18
19
|
export const pullCommandSchema = command(
|
|
19
20
|
'pull',
|
|
@@ -109,16 +110,13 @@ const writeLexicon = async (
|
|
|
109
110
|
outdir: string,
|
|
110
111
|
nsid: string,
|
|
111
112
|
doc: LexiconDoc,
|
|
112
|
-
|
|
113
|
+
formatter: Formatter,
|
|
113
114
|
): Promise<void> => {
|
|
114
115
|
const nsidPath = nsid.replaceAll('.', '/');
|
|
115
116
|
const target = path.join(outdir, `${nsidPath}.json`);
|
|
116
117
|
const dirname = path.dirname(target);
|
|
117
118
|
|
|
118
|
-
const code = await
|
|
119
|
-
...(prettierConfig ?? {}),
|
|
120
|
-
parser: 'json',
|
|
121
|
-
});
|
|
119
|
+
const code = await formatter.format(JSON.stringify(doc, null, 2), target);
|
|
122
120
|
|
|
123
121
|
await fs.mkdir(dirname, { recursive: true });
|
|
124
122
|
await fs.writeFile(target, code);
|
|
@@ -138,7 +136,7 @@ const pullSource = async (source: SourceConfig): Promise<PullResult> => {
|
|
|
138
136
|
const writeSourceReadme = async (
|
|
139
137
|
outdir: string,
|
|
140
138
|
revisions: SourceRevision[],
|
|
141
|
-
|
|
139
|
+
formatter: Formatter,
|
|
142
140
|
): Promise<void> => {
|
|
143
141
|
const lines = [
|
|
144
142
|
'# lexicon sources',
|
|
@@ -172,12 +170,10 @@ const writeSourceReadme = async (
|
|
|
172
170
|
lines.push('');
|
|
173
171
|
|
|
174
172
|
const content = lines.join('\n');
|
|
175
|
-
const
|
|
176
|
-
|
|
177
|
-
parser: 'markdown',
|
|
178
|
-
});
|
|
173
|
+
const target = path.join(outdir, 'README.md');
|
|
174
|
+
const formatted = await formatter.format(content, target);
|
|
179
175
|
|
|
180
|
-
await fs.writeFile(
|
|
176
|
+
await fs.writeFile(target, formatted);
|
|
181
177
|
};
|
|
182
178
|
|
|
183
179
|
/**
|
|
@@ -189,7 +185,7 @@ export const runPull = async (args: PullCommand): Promise<void> => {
|
|
|
189
185
|
const pullConfig = ensurePullConfig(config);
|
|
190
186
|
|
|
191
187
|
const outdir = path.resolve(config.root, pullConfig.outdir);
|
|
192
|
-
const
|
|
188
|
+
const formatter = await createFormatter(config.formatter, config.root);
|
|
193
189
|
|
|
194
190
|
const seen = new Map<string, SourceLocation>();
|
|
195
191
|
const collected: PulledLexicon[] = [];
|
|
@@ -223,9 +219,8 @@ export const runPull = async (args: PullCommand): Promise<void> => {
|
|
|
223
219
|
|
|
224
220
|
await fs.mkdir(outdir, { recursive: true });
|
|
225
221
|
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
await writeSourceReadme(outdir, sourceRevisions, prettierConfig);
|
|
222
|
+
await Promise.all([
|
|
223
|
+
...collected.map((entry) => writeLexicon(outdir, entry.nsid, entry.doc, formatter)),
|
|
224
|
+
writeSourceReadme(outdir, sourceRevisions, formatter),
|
|
225
|
+
]);
|
|
231
226
|
};
|
package/src/config.ts
CHANGED
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
import * as fs from 'node:fs/promises';
|
|
2
|
+
import { availableParallelism } from 'node:os';
|
|
2
3
|
import * as path from 'node:path';
|
|
3
4
|
import * as url from 'node:url';
|
|
4
5
|
|
|
5
|
-
import * as v from '@badrap/valita';
|
|
6
|
-
import pc from 'picocolors';
|
|
7
|
-
|
|
8
6
|
import { isAtprotoDid } from '@atcute/identity';
|
|
9
7
|
import { isHandle, isNsid } from '@atcute/lexicons/syntax';
|
|
10
8
|
|
|
11
|
-
import
|
|
9
|
+
import * as v from '@badrap/valita';
|
|
10
|
+
import pc from 'picocolors';
|
|
11
|
+
|
|
12
|
+
import type { ImportMapping } from './codegen.ts';
|
|
12
13
|
|
|
13
14
|
const gitSourceConfigSchema = v.object({
|
|
14
15
|
type: v.literal('git'),
|
|
@@ -63,6 +64,18 @@ const exportConfigSchema = v.object({
|
|
|
63
64
|
clean: v.boolean().optional(),
|
|
64
65
|
});
|
|
65
66
|
|
|
67
|
+
const formatterConfigSchema = v.union(
|
|
68
|
+
v.object({ type: v.literal('prettier') }),
|
|
69
|
+
v.object({
|
|
70
|
+
type: v.literal('command'),
|
|
71
|
+
command: v.string().assert((value) => value.length > 0, `must not be empty`),
|
|
72
|
+
concurrency: v
|
|
73
|
+
.number()
|
|
74
|
+
.assert((value) => Number.isInteger(value) && value > 0, `must be a positive integer`)
|
|
75
|
+
.optional(() => availableParallelism()),
|
|
76
|
+
}),
|
|
77
|
+
);
|
|
78
|
+
|
|
66
79
|
export type GitSourceConfig = v.Infer<typeof gitSourceConfigSchema>;
|
|
67
80
|
export type AtprotoNsidsSourceConfig = v.Infer<typeof atprotoNsidsSourceConfigSchema>;
|
|
68
81
|
export type AtprotoAuthoritySourceConfig = v.Infer<typeof atprotoAuthoritySourceConfigSchema>;
|
|
@@ -70,6 +83,7 @@ export type AtprotoSourceConfig = v.Infer<typeof atprotoSourceConfigSchema>;
|
|
|
70
83
|
export type SourceConfig = v.Infer<typeof sourceConfigSchema>;
|
|
71
84
|
export type PullConfig = v.Infer<typeof pullConfigSchema>;
|
|
72
85
|
export type ExportConfig = v.Infer<typeof exportConfigSchema>;
|
|
86
|
+
export type FormatterConfig = v.Infer<typeof formatterConfigSchema>;
|
|
73
87
|
|
|
74
88
|
const isValidLexiconPattern = (pattern: string): boolean => {
|
|
75
89
|
if (pattern.endsWith('.*')) {
|
|
@@ -126,6 +140,7 @@ export const lexiconConfigSchema = v.object({
|
|
|
126
140
|
})
|
|
127
141
|
.partial()
|
|
128
142
|
.optional(),
|
|
143
|
+
formatter: formatterConfigSchema.optional((): FormatterConfig => ({ type: 'prettier' })),
|
|
129
144
|
pull: pullConfigSchema.optional(),
|
|
130
145
|
export: exportConfigSchema.optional(),
|
|
131
146
|
});
|