@atcute/lex-cli 2.3.3 → 2.4.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/README.md CHANGED
@@ -23,6 +23,40 @@ then run the tool:
23
23
  npm exec lex-cli generate -c ./lex.config.js
24
24
  ```
25
25
 
26
+ ## pulling lexicons
27
+
28
+ configure sources to be pulled locally before code generation. pulled files are written using their
29
+ nsids (e.g., `app.bsky.feed.post` becomes `app/bsky/feed/post.json`).
30
+
31
+ ```ts
32
+ // file: lex.config.js
33
+ import { defineLexiconConfig } from '@atcute/lex-cli';
34
+
35
+ export default defineLexiconConfig({
36
+ pull: {
37
+ outdir: 'lexicons/',
38
+ clean: true,
39
+ sources: [
40
+ {
41
+ type: 'git',
42
+ remote: 'https://github.com/bluesky-social/atproto.git',
43
+ ref: 'main',
44
+ pattern: ['lexicons/**/*.json'],
45
+ },
46
+ ],
47
+ },
48
+ files: ['lexicons/**/*.json'],
49
+ outdir: 'src/lexicons/',
50
+ });
51
+ ```
52
+
53
+ pull the lexicons to disk, then generate types from them:
54
+
55
+ ```
56
+ npm exec lex-cli pull -c ./lex.config.js
57
+ npm exec lex-cli generate -c ./lex.config.js
58
+ ```
59
+
26
60
  ## publishing your schemas
27
61
 
28
62
  if you're packaging your generated schemas as a publishable library, add the `atcute:lexicons`
package/dist/cli.js CHANGED
@@ -3,12 +3,14 @@ import * as path from 'node:path';
3
3
  import { lexiconDoc, refineLexiconDoc } from '@atcute/lexicon-doc';
4
4
  import { object } from '@optique/core/constructs';
5
5
  import { command, constant, option } from '@optique/core/primitives';
6
+ import { or } from '@optique/core/constructs';
6
7
  import { run } from '@optique/run';
7
8
  import { path as pathParser } from '@optique/run/valueparser';
8
9
  import pc from 'picocolors';
9
10
  import { generateLexiconApi } from './codegen.js';
10
11
  import { loadConfig } from './config.js';
11
12
  import { packageJsonSchema } from './lexicon-metadata.js';
13
+ import { runPull } from './pull.js';
12
14
  /**
13
15
  * Resolves package imports to ImportMapping[]
14
16
  */
@@ -96,10 +98,13 @@ const resolveImportsToMappings = async (imports, configDirname) => {
96
98
  }
97
99
  return mappings;
98
100
  };
99
- const parser = command('generate', object({
101
+ const parser = or(command('generate', object({
100
102
  type: constant('generate'),
101
103
  config: option('-c', '--config', pathParser({ metavar: 'CONFIG' })),
102
- }));
104
+ })), command('pull', object({
105
+ type: constant('pull'),
106
+ config: option('-c', '--config', pathParser({ metavar: 'CONFIG' })),
107
+ })));
103
108
  const result = run(parser, { programName: 'lex-cli' });
104
109
  if (result.type === 'generate') {
105
110
  const config = await loadConfig(result.config);
@@ -163,4 +168,8 @@ if (result.type === 'generate') {
163
168
  await fs.writeFile(filename, file.code);
164
169
  }
165
170
  }
171
+ else if (result.type === 'pull') {
172
+ const config = await loadConfig(result.config);
173
+ await runPull(config);
174
+ }
166
175
  //# sourceMappingURL=cli.js.map
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
package/dist/config.d.ts CHANGED
@@ -1,5 +1,30 @@
1
1
  import * as v from '@badrap/valita';
2
2
  import type { ImportMapping } from './codegen.js';
3
+ declare const gitSourceConfigSchema: v.ObjectType<{
4
+ type: v.Type<"git">;
5
+ remote: v.Type<string>;
6
+ ref: v.Optional<string>;
7
+ pattern: v.Type<string[]>;
8
+ }, undefined>;
9
+ declare const sourceConfigSchema: v.UnionType<[v.ObjectType<{
10
+ type: v.Type<"git">;
11
+ remote: v.Type<string>;
12
+ ref: v.Optional<string>;
13
+ pattern: v.Type<string[]>;
14
+ }, undefined>]>;
15
+ declare const pullConfigSchema: v.ObjectType<{
16
+ outdir: v.Type<string>;
17
+ clean: v.Optional<boolean>;
18
+ sources: v.Type<{
19
+ type: "git";
20
+ remote: string;
21
+ ref?: string | undefined;
22
+ pattern: string[];
23
+ }[]>;
24
+ }, undefined>;
25
+ export type GitSourceConfig = v.Infer<typeof gitSourceConfigSchema>;
26
+ export type SourceConfig = v.Infer<typeof sourceConfigSchema>;
27
+ export type PullConfig = v.Infer<typeof pullConfigSchema>;
3
28
  export declare const lexiconConfigSchema: v.ObjectType<{
4
29
  outdir: v.Type<string>;
5
30
  files: v.Type<string[]>;
@@ -8,10 +33,21 @@ export declare const lexiconConfigSchema: v.ObjectType<{
8
33
  modules: v.Optional<{
9
34
  importSuffix?: string | undefined;
10
35
  }>;
36
+ pull: v.Optional<{
37
+ outdir: string;
38
+ clean?: boolean | undefined;
39
+ sources: {
40
+ type: "git";
41
+ remote: string;
42
+ ref?: string | undefined;
43
+ pattern: string[];
44
+ }[];
45
+ }>;
11
46
  }, undefined>;
12
47
  export type LexiconConfig = v.Infer<typeof lexiconConfigSchema>;
13
48
  export interface NormalizedConfig extends LexiconConfig {
14
49
  root: string;
15
50
  }
16
51
  export declare const loadConfig: (configPath: string) => Promise<NormalizedConfig>;
52
+ export {};
17
53
  //# sourceMappingURL=config.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,CAAC,MAAM,gBAAgB,CAAC;AAKpC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AA6ClD,eAAO,MAAM,mBAAmB;;;;;;;;aA8B9B,CAAC;AAEH,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAEhE,MAAM,WAAW,gBAAiB,SAAQ,aAAa;IACtD,IAAI,EAAE,MAAM,CAAC;CACb;AAED,eAAO,MAAM,UAAU,GAAU,YAAY,MAAM,KAAG,OAAO,CAAC,gBAAgB,CA6B7E,CAAC"}
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,CAAC,MAAM,gBAAgB,CAAC;AAKpC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAElD,QAAA,MAAM,qBAAqB;;;;;aAUzB,CAAC;AAEH,QAAA,MAAM,kBAAkB;;;;;eAAiC,CAAC;AAE1D,QAAA,MAAM,gBAAgB;;;;;;;;;aAMpB,CAAC;AAEH,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAC;AACpE,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAC9D,MAAM,MAAM,UAAU,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAyC1D,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;aAiB9B,CAAC;AAEH,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAEhE,MAAM,WAAW,gBAAiB,SAAQ,aAAa;IACtD,IAAI,EAAE,MAAM,CAAC;CACb;AAED,eAAO,MAAM,UAAU,GAAU,YAAY,MAAM,KAAG,OAAO,CAAC,gBAAgB,CA6B7E,CAAC"}
package/dist/config.js CHANGED
@@ -3,6 +3,25 @@ import * as url from 'node:url';
3
3
  import * as v from '@badrap/valita';
4
4
  import pc from 'picocolors';
5
5
  import { isNsid } from '@atcute/lexicons/syntax';
6
+ const gitSourceConfigSchema = v.object({
7
+ type: v.literal('git'),
8
+ remote: v.string().assert((value) => value.length > 0, `must not be empty`),
9
+ ref: v
10
+ .string()
11
+ .assert((value) => value.length > 0, `must not be empty`)
12
+ .optional(),
13
+ pattern: v
14
+ .array(v.string().assert((value) => value.length > 0, `must not be empty`))
15
+ .assert((value) => value.length > 0, `must include at least one glob pattern`),
16
+ });
17
+ const sourceConfigSchema = v.union(gitSourceConfigSchema);
18
+ const pullConfigSchema = v.object({
19
+ outdir: v.string().assert((value) => value.length > 0, `must not be empty`),
20
+ clean: v.boolean().optional(),
21
+ sources: v
22
+ .array(sourceConfigSchema)
23
+ .assert((value) => value.length > 0, `must include at least one source`),
24
+ });
6
25
  const isValidLexiconPattern = (pattern) => {
7
26
  if (pattern.endsWith('.*')) {
8
27
  return isNsid(`${pattern.slice(0, -2)}.x`);
@@ -12,56 +31,43 @@ const isValidLexiconPattern = (pattern) => {
12
31
  const mappingImports = v.unknown().chain((value) => {
13
32
  if (typeof value === 'string') {
14
33
  if (value.length === 0) {
15
- return v.err({ message: 'imports must not be empty' });
34
+ return v.err('imports must not be empty');
16
35
  }
17
36
  return v.ok(value);
18
37
  }
19
38
  if (typeof value === 'function') {
20
39
  return v.ok(value);
21
40
  }
22
- return v.err({ message: 'imports must be a string or function' });
41
+ return v.err('imports must be a string or function');
23
42
  });
24
43
  const importMappingSchema = v.object({
25
44
  nsid: v
26
45
  .array(v.string().chain((value) => {
27
46
  if (!isValidLexiconPattern(value)) {
28
- return v.err({
29
- message: 'invalid NSID pattern (must be valid NSID or end with .*)',
30
- });
47
+ return v.err(`invalid NSID pattern (must be valid NSID or end with .*)`);
31
48
  }
32
49
  return v.ok(value);
33
50
  }))
34
- .assert((patterns) => patterns.length > 0, {
35
- message: 'nsid requires at least one pattern',
36
- }),
51
+ .assert((patterns) => patterns.length > 0, `nsid requires at least one pattern`),
37
52
  imports: mappingImports,
38
53
  });
39
54
  export const lexiconConfigSchema = v.object({
40
- outdir: v.string().assert((value) => value.length > 0, {
41
- message: 'outdir must not be empty',
42
- }),
55
+ outdir: v.string().assert((value) => value.length > 0, `must not be empty`),
43
56
  files: v
44
- .array(v.string().assert((value) => value.length > 0, {
45
- message: 'files entries must not be empty',
46
- }))
47
- .assert((value) => value.length > 0, {
48
- message: 'files must include at least one pattern',
49
- }),
50
- imports: v
51
- .array(v.string().assert((value) => value.length > 0, {
52
- message: 'imports entries must not be empty',
53
- }))
54
- .optional(),
57
+ .array(v.string().assert((value) => value.length > 0, `must not be empty`))
58
+ .assert((value) => value.length > 0, `must include at least one glob pattern`),
59
+ imports: v.array(v.string().assert((value) => value.length > 0, `must not be empty`)).optional(),
55
60
  mappings: v.array(importMappingSchema).optional(),
56
61
  modules: v
57
62
  .object({
58
63
  importSuffix: v
59
64
  .string()
60
- .assert((value) => value.length > 0, { message: 'importSuffix must not be empty' })
65
+ .assert((value) => value.length > 0, `must not be empty`)
61
66
  .optional(),
62
67
  })
63
68
  .partial()
64
69
  .optional(),
70
+ pull: pullConfigSchema.optional(),
65
71
  });
66
72
  export const loadConfig = async (configPath) => {
67
73
  const configFilename = path.resolve(configPath);
@@ -1 +1 @@
1
- {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
package/dist/git.d.ts ADDED
@@ -0,0 +1,27 @@
1
+ export interface GitCommandOptions {
2
+ cwd?: string;
3
+ env?: NodeJS.ProcessEnv;
4
+ stdin?: string;
5
+ timeoutMs?: number;
6
+ }
7
+ export interface GitResult {
8
+ stdout: string;
9
+ stderr: string;
10
+ }
11
+ export declare class GitError extends Error {
12
+ readonly args: readonly string[];
13
+ readonly code: number | null;
14
+ readonly signal: NodeJS.Signals | null;
15
+ readonly stdout: string;
16
+ readonly stderr: string;
17
+ constructor(args: readonly string[], stdout: string, stderr: string, code: number | null, signal: NodeJS.Signals | null);
18
+ }
19
+ /**
20
+ * runs git with the provided arguments and throws when the command fails.
21
+ * @param args positional arguments for git
22
+ * @param options execution options
23
+ * @returns stdout and stderr from git
24
+ * @throws GitError when git exits with a non-zero status or is terminated
25
+ */
26
+ export declare const runGit: (args: readonly string[], options?: GitCommandOptions) => Promise<GitResult>;
27
+ //# sourceMappingURL=git.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"git.d.ts","sourceRoot":"","sources":["../src/git.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,iBAAiB;IACjC,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IACxB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,SAAS;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;CACf;AAED,qBAAa,QAAS,SAAQ,KAAK;IAClC,QAAQ,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,CAAC;IACjC,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC,OAAO,GAAG,IAAI,CAAC;IACvC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;gBAGvB,IAAI,EAAE,SAAS,MAAM,EAAE,EACvB,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,GAAG,IAAI,EACnB,MAAM,EAAE,MAAM,CAAC,OAAO,GAAG,IAAI;CAY9B;AAED;;;;;;GAMG;AACH,eAAO,MAAM,MAAM,GAAI,MAAM,SAAS,MAAM,EAAE,EAAE,UAAS,iBAAsB,KAAG,OAAO,CAAC,SAAS,CAwDlG,CAAC"}
package/dist/git.js ADDED
@@ -0,0 +1,73 @@
1
+ import { spawn } from 'node:child_process';
2
+ export class GitError extends Error {
3
+ args;
4
+ code;
5
+ signal;
6
+ stdout;
7
+ stderr;
8
+ constructor(args, stdout, stderr, code, signal) {
9
+ const reason = code !== null ? `code ${code}` : `signal ${signal ?? 'unknown'}`;
10
+ super(`git ${args.join(' ')} failed with ${reason}`);
11
+ this.name = 'GitError';
12
+ this.args = args;
13
+ this.code = code;
14
+ this.signal = signal;
15
+ this.stdout = stdout;
16
+ this.stderr = stderr;
17
+ }
18
+ }
19
+ /**
20
+ * runs git with the provided arguments and throws when the command fails.
21
+ * @param args positional arguments for git
22
+ * @param options execution options
23
+ * @returns stdout and stderr from git
24
+ * @throws GitError when git exits with a non-zero status or is terminated
25
+ */
26
+ export const runGit = (args, options = {}) => {
27
+ return new Promise((resolve, reject) => {
28
+ const child = spawn('git', args, {
29
+ cwd: options.cwd,
30
+ env: options.env,
31
+ stdio: ['pipe', 'pipe', 'pipe'],
32
+ });
33
+ let stdout = '';
34
+ let stderr = '';
35
+ child.stdout?.setEncoding('utf8');
36
+ child.stderr?.setEncoding('utf8');
37
+ child.stdout?.on('data', (chunk) => {
38
+ stdout += chunk;
39
+ });
40
+ child.stderr?.on('data', (chunk) => {
41
+ stderr += chunk;
42
+ });
43
+ let timer;
44
+ if (options.timeoutMs !== undefined) {
45
+ timer = setTimeout(() => {
46
+ child.kill('SIGKILL');
47
+ }, options.timeoutMs);
48
+ }
49
+ child.on('error', (err) => {
50
+ if (timer) {
51
+ clearTimeout(timer);
52
+ }
53
+ reject(err);
54
+ });
55
+ child.on('close', (code, signal) => {
56
+ if (timer) {
57
+ clearTimeout(timer);
58
+ }
59
+ if (code === 0) {
60
+ resolve({ stdout, stderr });
61
+ return;
62
+ }
63
+ reject(new GitError(args, stdout, stderr, code, signal));
64
+ });
65
+ if (options.stdin !== undefined) {
66
+ child.stdin?.end(options.stdin);
67
+ }
68
+ else {
69
+ child.stdin?.end();
70
+ }
71
+ });
72
+ };
73
+ //# sourceMappingURL=git.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"git.js","sourceRoot":"","sources":["../src/git.ts"],"names":[],"mappings":"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"}
package/dist/pull.d.ts ADDED
@@ -0,0 +1,7 @@
1
+ import type { NormalizedConfig } from './config.js';
2
+ /**
3
+ * pulls lexicon documents from configured sources and writes them to disk using nsid-based paths.
4
+ * @param config normalized lex-cli configuration
5
+ */
6
+ export declare const runPull: (config: NormalizedConfig) => Promise<void>;
7
+ //# sourceMappingURL=pull.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pull.d.ts","sourceRoot":"","sources":["../src/pull.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,gBAAgB,EAA4B,MAAM,aAAa,CAAC;AAkP9E;;;GAGG;AACH,eAAO,MAAM,OAAO,GAAU,QAAQ,gBAAgB,KAAG,OAAO,CAAC,IAAI,CA0CpE,CAAC"}
package/dist/pull.js ADDED
@@ -0,0 +1,209 @@
1
+ import * as fs from 'node:fs/promises';
2
+ import * as os from 'node:os';
3
+ import * as path from 'node:path';
4
+ import { lexiconDoc, refineLexiconDoc } from '@atcute/lexicon-doc';
5
+ import prettier from 'prettier';
6
+ import pc from 'picocolors';
7
+ import { runGit, GitError } from './git.js';
8
+ const ensurePullConfig = (config) => {
9
+ if (!config.pull) {
10
+ console.error(pc.bold(pc.red(`pull configuration missing`)));
11
+ process.exit(1);
12
+ }
13
+ return config.pull;
14
+ };
15
+ const parseLexiconFile = async (loc) => {
16
+ let source;
17
+ try {
18
+ source = await fs.readFile(loc.absolutePath, 'utf8');
19
+ }
20
+ catch (err) {
21
+ console.error(pc.bold(pc.red(`file read error for ${loc.relativePath} when pulling ${loc.sourceDescription}`)));
22
+ console.error(`found in ${loc.absolutePath}`);
23
+ console.error(err);
24
+ process.exit(1);
25
+ }
26
+ let json;
27
+ try {
28
+ json = JSON.parse(source);
29
+ }
30
+ catch (err) {
31
+ console.error(pc.bold(pc.red(`json parse error in ${loc.relativePath} when pulling ${loc.sourceDescription}`)));
32
+ console.error(`found in ${loc.absolutePath}`);
33
+ console.error(err);
34
+ process.exit(1);
35
+ }
36
+ const result = lexiconDoc.try(json, { mode: 'passthrough' });
37
+ if (!result.ok) {
38
+ console.error(pc.bold(pc.red(`schema validation failed for ${loc.relativePath} when pulling ${loc.sourceDescription}`)));
39
+ console.error(`found in ${loc.absolutePath}`);
40
+ console.error(result.message);
41
+ for (const issue of result.issues) {
42
+ console.log(`- ${issue.code} at .${issue.path.join('.')}`);
43
+ }
44
+ process.exit(1);
45
+ }
46
+ const issues = refineLexiconDoc(result.value, true);
47
+ if (issues.length > 0) {
48
+ console.error(pc.bold(pc.red(`lint validation failed for ${loc.relativePath} when pulling ${loc.sourceDescription}`)));
49
+ console.error(`found in ${loc.absolutePath}`);
50
+ for (const issue of issues) {
51
+ console.log(`- ${issue.message} at .${issue.path.join('.')}`);
52
+ }
53
+ process.exit(1);
54
+ }
55
+ return result.value;
56
+ };
57
+ const writeLexicon = async (outdir, nsid, doc, prettierConfig) => {
58
+ const nsidPath = nsid.replaceAll('.', '/');
59
+ const target = path.join(outdir, `${nsidPath}.json`);
60
+ const dirname = path.dirname(target);
61
+ const code = await prettier.format(JSON.stringify(doc, null, 2), {
62
+ ...(prettierConfig ?? {}),
63
+ parser: 'json',
64
+ });
65
+ await fs.mkdir(dirname, { recursive: true });
66
+ await fs.writeFile(target, code);
67
+ };
68
+ /**
69
+ * pulls lexicon documents from a git repository source
70
+ * @param source git source configuration
71
+ * @returns pulled lexicons and commit hash
72
+ */
73
+ const pullGitSource = async (source) => {
74
+ const tempParent = await fs.mkdtemp(path.join(os.tmpdir(), 'lex-cli-pull-'));
75
+ const cloneDir = path.join(tempParent, 'repo');
76
+ try {
77
+ await runGit([
78
+ 'clone',
79
+ '--filter=blob:none',
80
+ '--depth',
81
+ '1',
82
+ '--sparse',
83
+ ...(source.ref ? ['--branch', source.ref, '--single-branch'] : []),
84
+ source.remote,
85
+ cloneDir,
86
+ ], { timeoutMs: 60_000 });
87
+ }
88
+ catch (err) {
89
+ if (err instanceof GitError) {
90
+ console.error(pc.bold(pc.red(`git clone failed for ${source.remote}:`)));
91
+ console.error(err.stderr || err.message);
92
+ process.exit(1);
93
+ }
94
+ throw err;
95
+ }
96
+ try {
97
+ await runGit(['-C', cloneDir, 'sparse-checkout', 'set', '--no-cone', ...source.pattern], {
98
+ timeoutMs: 30_000,
99
+ });
100
+ }
101
+ catch (err) {
102
+ if (err instanceof GitError) {
103
+ console.error(pc.bold(pc.red(`git sparse-checkout failed for ${source.remote}:`)));
104
+ console.error(err.stderr || err.message);
105
+ process.exit(1);
106
+ }
107
+ throw err;
108
+ }
109
+ const pulled = new Map();
110
+ for await (const filename of fs.glob(source.pattern, { cwd: cloneDir })) {
111
+ const absolute = path.join(cloneDir, filename);
112
+ const stat = await fs.stat(absolute);
113
+ if (!stat.isFile()) {
114
+ continue;
115
+ }
116
+ const location = {
117
+ absolutePath: absolute,
118
+ relativePath: filename,
119
+ sourceDescription: source.remote,
120
+ };
121
+ const doc = await parseLexiconFile(location);
122
+ pulled.set(doc.id, { nsid: doc.id, doc, location });
123
+ }
124
+ // get the commit hash
125
+ let rev;
126
+ try {
127
+ const result = await runGit(['-C', cloneDir, 'rev-parse', 'HEAD'], { timeoutMs: 10_000 });
128
+ rev = result.stdout.trim();
129
+ }
130
+ catch (err) {
131
+ if (err instanceof GitError) {
132
+ console.error(pc.bold(pc.red(`git rev-parse failed for ${source.remote}:`)));
133
+ console.error(err.stderr || err.message);
134
+ process.exit(1);
135
+ }
136
+ throw err;
137
+ }
138
+ await fs.rm(tempParent, { recursive: true, force: true });
139
+ return { pulled, rev };
140
+ };
141
+ const pullSource = async (source) => {
142
+ switch (source.type) {
143
+ case 'git': {
144
+ return pullGitSource(source);
145
+ }
146
+ }
147
+ };
148
+ const writeSourceReadme = async (outdir, revisions, prettierConfig) => {
149
+ const lines = [
150
+ '# lexicon sources',
151
+ '',
152
+ 'this directory contains lexicon documents pulled from the following sources:',
153
+ '',
154
+ ];
155
+ for (const { source, rev } of revisions) {
156
+ switch (source.type) {
157
+ case 'git': {
158
+ lines.push(`- ${source.remote}${source.ref ? ` (ref: ${source.ref})` : ``}`);
159
+ lines.push(` - commit: ${rev}`);
160
+ break;
161
+ }
162
+ }
163
+ }
164
+ lines.push('');
165
+ const content = lines.join('\n');
166
+ const formatted = await prettier.format(content, {
167
+ ...(prettierConfig ?? {}),
168
+ parser: 'markdown',
169
+ });
170
+ await fs.writeFile(path.join(outdir, 'README.md'), formatted);
171
+ };
172
+ /**
173
+ * pulls lexicon documents from configured sources and writes them to disk using nsid-based paths.
174
+ * @param config normalized lex-cli configuration
175
+ */
176
+ export const runPull = async (config) => {
177
+ const pullConfig = ensurePullConfig(config);
178
+ const outdir = path.resolve(config.root, pullConfig.outdir);
179
+ const prettierConfig = await prettier.resolveConfig(config.root, { editorconfig: true });
180
+ const seen = new Map();
181
+ const collected = [];
182
+ const sourceRevisions = [];
183
+ for (const source of pullConfig.sources) {
184
+ const result = await pullSource(source);
185
+ sourceRevisions.push({ source, rev: result.rev });
186
+ for (const [nsid, entry] of result.pulled) {
187
+ const existing = seen.get(nsid);
188
+ if (existing) {
189
+ console.error(pc.bold(pc.red(`duplicate lexicon "${nsid}"`)));
190
+ console.error(`- found ${entry.location.relativePath} from ${entry.location.sourceDescription}`);
191
+ console.error(` at ${entry.location.absolutePath}`);
192
+ console.error(`- already found ${existing.relativePath} from ${existing.sourceDescription}`);
193
+ console.error(` at ${existing.absolutePath}`);
194
+ process.exit(1);
195
+ }
196
+ seen.set(nsid, entry.location);
197
+ collected.push(entry);
198
+ }
199
+ }
200
+ if (pullConfig.clean) {
201
+ await fs.rm(outdir, { recursive: true, force: true });
202
+ }
203
+ await fs.mkdir(outdir, { recursive: true });
204
+ for (const entry of collected) {
205
+ await writeLexicon(outdir, entry.nsid, entry.doc, prettierConfig);
206
+ }
207
+ await writeSourceReadme(outdir, sourceRevisions, prettierConfig);
208
+ };
209
+ //# sourceMappingURL=pull.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pull.js","sourceRoot":"","sources":["../src/pull.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "type": "module",
3
3
  "name": "@atcute/lex-cli",
4
- "version": "2.3.3",
4
+ "version": "2.4.0",
5
5
  "description": "cli tool to generate type definitions for atcute",
6
6
  "license": "0BSD",
7
7
  "repository": {
@@ -26,12 +26,12 @@
26
26
  "@optique/run": "^0.6.2",
27
27
  "picocolors": "^1.1.1",
28
28
  "prettier": "^3.6.2",
29
- "@atcute/lexicon-doc": "^2.0.0"
29
+ "@atcute/lexicon-doc": "^2.0.2"
30
30
  },
31
31
  "devDependencies": {
32
32
  "@types/node": "^22.19.0",
33
33
  "tschema": "^3.2.0",
34
- "@atcute/lexicons": "^1.2.4"
34
+ "@atcute/lexicons": "^1.2.5"
35
35
  },
36
36
  "scripts": {
37
37
  "build": "pnpm run generate:schema && tsc",
package/src/cli.ts CHANGED
@@ -5,6 +5,7 @@ import { lexiconDoc, refineLexiconDoc, type LexiconDoc } from '@atcute/lexicon-d
5
5
 
6
6
  import { object } from '@optique/core/constructs';
7
7
  import { command, constant, option } from '@optique/core/primitives';
8
+ import { or } from '@optique/core/constructs';
8
9
  import { run } from '@optique/run';
9
10
  import { path as pathParser } from '@optique/run/valueparser';
10
11
  import pc from 'picocolors';
@@ -12,6 +13,7 @@ import pc from 'picocolors';
12
13
  import { generateLexiconApi, type ImportMapping } from './codegen.js';
13
14
  import { loadConfig } from './config.js';
14
15
  import { packageJsonSchema } from './lexicon-metadata.js';
16
+ import { runPull } from './pull.js';
15
17
 
16
18
  /**
17
19
  * Resolves package imports to ImportMapping[]
@@ -116,12 +118,21 @@ const resolveImportsToMappings = async (
116
118
  return mappings;
117
119
  };
118
120
 
119
- const parser = command(
120
- 'generate',
121
- object({
122
- type: constant('generate'),
123
- config: option('-c', '--config', pathParser({ metavar: 'CONFIG' })),
124
- }),
121
+ const parser = or(
122
+ command(
123
+ 'generate',
124
+ object({
125
+ type: constant('generate'),
126
+ config: option('-c', '--config', pathParser({ metavar: 'CONFIG' })),
127
+ }),
128
+ ),
129
+ command(
130
+ 'pull',
131
+ object({
132
+ type: constant('pull'),
133
+ config: option('-c', '--config', pathParser({ metavar: 'CONFIG' })),
134
+ }),
135
+ ),
125
136
  );
126
137
 
127
138
  const result = run(parser, { programName: 'lex-cli' });
@@ -202,4 +213,7 @@ if (result.type === 'generate') {
202
213
  await fs.mkdir(dirname, { recursive: true });
203
214
  await fs.writeFile(filename, file.code);
204
215
  }
216
+ } else if (result.type === 'pull') {
217
+ const config = await loadConfig(result.config);
218
+ await runPull(config);
205
219
  }
package/src/config.ts CHANGED
@@ -8,6 +8,32 @@ import { isNsid } from '@atcute/lexicons/syntax';
8
8
 
9
9
  import type { ImportMapping } from './codegen.js';
10
10
 
11
+ const gitSourceConfigSchema = v.object({
12
+ type: v.literal('git'),
13
+ remote: v.string().assert((value) => value.length > 0, `must not be empty`),
14
+ ref: v
15
+ .string()
16
+ .assert((value) => value.length > 0, `must not be empty`)
17
+ .optional(),
18
+ pattern: v
19
+ .array(v.string().assert((value) => value.length > 0, `must not be empty`))
20
+ .assert((value) => value.length > 0, `must include at least one glob pattern`),
21
+ });
22
+
23
+ const sourceConfigSchema = v.union(gitSourceConfigSchema);
24
+
25
+ const pullConfigSchema = v.object({
26
+ outdir: v.string().assert((value) => value.length > 0, `must not be empty`),
27
+ clean: v.boolean().optional(),
28
+ sources: v
29
+ .array(sourceConfigSchema)
30
+ .assert((value) => value.length > 0, `must include at least one source`),
31
+ });
32
+
33
+ export type GitSourceConfig = v.Infer<typeof gitSourceConfigSchema>;
34
+ export type SourceConfig = v.Infer<typeof sourceConfigSchema>;
35
+ export type PullConfig = v.Infer<typeof pullConfigSchema>;
36
+
11
37
  const isValidLexiconPattern = (pattern: string): boolean => {
12
38
  if (pattern.endsWith('.*')) {
13
39
  return isNsid(`${pattern.slice(0, -2)}.x`);
@@ -19,7 +45,7 @@ const isValidLexiconPattern = (pattern: string): boolean => {
19
45
  const mappingImports: v.Type<ImportMapping['imports']> = v.unknown().chain((value) => {
20
46
  if (typeof value === 'string') {
21
47
  if (value.length === 0) {
22
- return v.err({ message: 'imports must not be empty' });
48
+ return v.err('imports must not be empty');
23
49
  }
24
50
 
25
51
  return v.ok(value);
@@ -29,7 +55,7 @@ const mappingImports: v.Type<ImportMapping['imports']> = v.unknown().chain((valu
29
55
  return v.ok(value as ImportMapping['imports']);
30
56
  }
31
57
 
32
- return v.err({ message: 'imports must be a string or function' });
58
+ return v.err('imports must be a string or function');
33
59
  });
34
60
 
35
61
  const importMappingSchema: v.Type<ImportMapping> = v.object({
@@ -37,50 +63,33 @@ const importMappingSchema: v.Type<ImportMapping> = v.object({
37
63
  .array(
38
64
  v.string().chain((value) => {
39
65
  if (!isValidLexiconPattern(value)) {
40
- return v.err({
41
- message: 'invalid NSID pattern (must be valid NSID or end with .*)',
42
- });
66
+ return v.err(`invalid NSID pattern (must be valid NSID or end with .*)`);
43
67
  }
44
68
 
45
69
  return v.ok(value);
46
70
  }),
47
71
  )
48
- .assert((patterns) => patterns.length > 0, {
49
- message: 'nsid requires at least one pattern',
50
- }),
72
+ .assert((patterns) => patterns.length > 0, `nsid requires at least one pattern`),
51
73
  imports: mappingImports,
52
74
  });
53
75
 
54
76
  export const lexiconConfigSchema = v.object({
55
- outdir: v.string().assert((value) => value.length > 0, {
56
- message: 'outdir must not be empty',
57
- }),
77
+ outdir: v.string().assert((value) => value.length > 0, `must not be empty`),
58
78
  files: v
59
- .array(
60
- v.string().assert((value) => value.length > 0, {
61
- message: 'files entries must not be empty',
62
- }),
63
- )
64
- .assert((value) => value.length > 0, {
65
- message: 'files must include at least one pattern',
66
- }),
67
- imports: v
68
- .array(
69
- v.string().assert((value) => value.length > 0, {
70
- message: 'imports entries must not be empty',
71
- }),
72
- )
73
- .optional(),
79
+ .array(v.string().assert((value) => value.length > 0, `must not be empty`))
80
+ .assert((value) => value.length > 0, `must include at least one glob pattern`),
81
+ imports: v.array(v.string().assert((value) => value.length > 0, `must not be empty`)).optional(),
74
82
  mappings: v.array(importMappingSchema).optional(),
75
83
  modules: v
76
84
  .object({
77
85
  importSuffix: v
78
86
  .string()
79
- .assert((value) => value.length > 0, { message: 'importSuffix must not be empty' })
87
+ .assert((value) => value.length > 0, `must not be empty`)
80
88
  .optional(),
81
89
  })
82
90
  .partial()
83
91
  .optional(),
92
+ pull: pullConfigSchema.optional(),
84
93
  });
85
94
 
86
95
  export type LexiconConfig = v.Infer<typeof lexiconConfigSchema>;
package/src/git.ts ADDED
@@ -0,0 +1,104 @@
1
+ import { spawn } from 'node:child_process';
2
+
3
+ export interface GitCommandOptions {
4
+ cwd?: string;
5
+ env?: NodeJS.ProcessEnv;
6
+ stdin?: string;
7
+ timeoutMs?: number;
8
+ }
9
+
10
+ export interface GitResult {
11
+ stdout: string;
12
+ stderr: string;
13
+ }
14
+
15
+ export class GitError extends Error {
16
+ readonly args: readonly string[];
17
+ readonly code: number | null;
18
+ readonly signal: NodeJS.Signals | null;
19
+ readonly stdout: string;
20
+ readonly stderr: string;
21
+
22
+ constructor(
23
+ args: readonly string[],
24
+ stdout: string,
25
+ stderr: string,
26
+ code: number | null,
27
+ signal: NodeJS.Signals | null,
28
+ ) {
29
+ const reason = code !== null ? `code ${code}` : `signal ${signal ?? 'unknown'}`;
30
+ super(`git ${args.join(' ')} failed with ${reason}`);
31
+
32
+ this.name = 'GitError';
33
+ this.args = args;
34
+ this.code = code;
35
+ this.signal = signal;
36
+ this.stdout = stdout;
37
+ this.stderr = stderr;
38
+ }
39
+ }
40
+
41
+ /**
42
+ * runs git with the provided arguments and throws when the command fails.
43
+ * @param args positional arguments for git
44
+ * @param options execution options
45
+ * @returns stdout and stderr from git
46
+ * @throws GitError when git exits with a non-zero status or is terminated
47
+ */
48
+ export const runGit = (args: readonly string[], options: GitCommandOptions = {}): Promise<GitResult> => {
49
+ return new Promise((resolve, reject) => {
50
+ const child = spawn('git', args, {
51
+ cwd: options.cwd,
52
+ env: options.env,
53
+ stdio: ['pipe', 'pipe', 'pipe'],
54
+ });
55
+
56
+ let stdout = '';
57
+ let stderr = '';
58
+
59
+ child.stdout?.setEncoding('utf8');
60
+ child.stderr?.setEncoding('utf8');
61
+
62
+ child.stdout?.on('data', (chunk) => {
63
+ stdout += chunk;
64
+ });
65
+
66
+ child.stderr?.on('data', (chunk) => {
67
+ stderr += chunk;
68
+ });
69
+
70
+ let timer: NodeJS.Timeout | undefined;
71
+ if (options.timeoutMs !== undefined) {
72
+ timer = setTimeout(() => {
73
+ child.kill('SIGKILL');
74
+ }, options.timeoutMs);
75
+ }
76
+
77
+ child.on('error', (err) => {
78
+ if (timer) {
79
+ clearTimeout(timer);
80
+ }
81
+
82
+ reject(err);
83
+ });
84
+
85
+ child.on('close', (code, signal) => {
86
+ if (timer) {
87
+ clearTimeout(timer);
88
+ }
89
+
90
+ if (code === 0) {
91
+ resolve({ stdout, stderr });
92
+ return;
93
+ }
94
+
95
+ reject(new GitError(args, stdout, stderr, code, signal));
96
+ });
97
+
98
+ if (options.stdin !== undefined) {
99
+ child.stdin?.end(options.stdin);
100
+ } else {
101
+ child.stdin?.end();
102
+ }
103
+ });
104
+ };
package/src/pull.ts ADDED
@@ -0,0 +1,298 @@
1
+ import * as fs from 'node:fs/promises';
2
+ import * as os from 'node:os';
3
+ import * as path from 'node:path';
4
+
5
+ import { lexiconDoc, refineLexiconDoc, type LexiconDoc } from '@atcute/lexicon-doc';
6
+ import prettier from 'prettier';
7
+ import pc from 'picocolors';
8
+
9
+ import { runGit, GitError } from './git.js';
10
+ import type { NormalizedConfig, PullConfig, SourceConfig } from './config.js';
11
+
12
+ interface SourceRevision {
13
+ source: SourceConfig;
14
+ rev: string;
15
+ }
16
+
17
+ interface SourceLocation {
18
+ absolutePath: string;
19
+ relativePath: string;
20
+ sourceDescription: string;
21
+ }
22
+
23
+ interface PulledLexicon {
24
+ nsid: string;
25
+ doc: LexiconDoc;
26
+ location: SourceLocation;
27
+ }
28
+
29
+ interface PullResult {
30
+ pulled: Map<string, PulledLexicon>;
31
+ rev: string;
32
+ }
33
+
34
+ const ensurePullConfig = (config: NormalizedConfig): PullConfig => {
35
+ if (!config.pull) {
36
+ console.error(pc.bold(pc.red(`pull configuration missing`)));
37
+ process.exit(1);
38
+ }
39
+
40
+ return config.pull;
41
+ };
42
+
43
+ const parseLexiconFile = async (loc: SourceLocation): Promise<LexiconDoc> => {
44
+ let source: string;
45
+
46
+ try {
47
+ source = await fs.readFile(loc.absolutePath, 'utf8');
48
+ } catch (err) {
49
+ console.error(
50
+ pc.bold(pc.red(`file read error for ${loc.relativePath} when pulling ${loc.sourceDescription}`)),
51
+ );
52
+ console.error(`found in ${loc.absolutePath}`);
53
+ console.error(err);
54
+ process.exit(1);
55
+ }
56
+
57
+ let json: unknown;
58
+ try {
59
+ json = JSON.parse(source);
60
+ } catch (err) {
61
+ console.error(
62
+ pc.bold(pc.red(`json parse error in ${loc.relativePath} when pulling ${loc.sourceDescription}`)),
63
+ );
64
+ console.error(`found in ${loc.absolutePath}`);
65
+ console.error(err);
66
+ process.exit(1);
67
+ }
68
+
69
+ const result = lexiconDoc.try(json, { mode: 'passthrough' });
70
+ if (!result.ok) {
71
+ console.error(
72
+ pc.bold(
73
+ pc.red(`schema validation failed for ${loc.relativePath} when pulling ${loc.sourceDescription}`),
74
+ ),
75
+ );
76
+ console.error(`found in ${loc.absolutePath}`);
77
+ console.error(result.message);
78
+
79
+ for (const issue of result.issues) {
80
+ console.log(`- ${issue.code} at .${issue.path.join('.')}`);
81
+ }
82
+
83
+ process.exit(1);
84
+ }
85
+
86
+ const issues = refineLexiconDoc(result.value, true);
87
+ if (issues.length > 0) {
88
+ console.error(
89
+ pc.bold(pc.red(`lint validation failed for ${loc.relativePath} when pulling ${loc.sourceDescription}`)),
90
+ );
91
+ console.error(`found in ${loc.absolutePath}`);
92
+
93
+ for (const issue of issues) {
94
+ console.log(`- ${issue.message} at .${issue.path.join('.')}`);
95
+ }
96
+
97
+ process.exit(1);
98
+ }
99
+
100
+ return result.value;
101
+ };
102
+
103
+ const writeLexicon = async (
104
+ outdir: string,
105
+ nsid: string,
106
+ doc: LexiconDoc,
107
+ prettierConfig: prettier.Options | null,
108
+ ): Promise<void> => {
109
+ const nsidPath = nsid.replaceAll('.', '/');
110
+ const target = path.join(outdir, `${nsidPath}.json`);
111
+ const dirname = path.dirname(target);
112
+
113
+ const code = await prettier.format(JSON.stringify(doc, null, 2), {
114
+ ...(prettierConfig ?? {}),
115
+ parser: 'json',
116
+ });
117
+
118
+ await fs.mkdir(dirname, { recursive: true });
119
+ await fs.writeFile(target, code);
120
+ };
121
+
122
+ /**
123
+ * pulls lexicon documents from a git repository source
124
+ * @param source git source configuration
125
+ * @returns pulled lexicons and commit hash
126
+ */
127
+ const pullGitSource = async (source: SourceConfig & { type: 'git' }): Promise<PullResult> => {
128
+ const tempParent = await fs.mkdtemp(path.join(os.tmpdir(), 'lex-cli-pull-'));
129
+
130
+ const cloneDir = path.join(tempParent, 'repo');
131
+
132
+ try {
133
+ await runGit(
134
+ [
135
+ 'clone',
136
+ '--filter=blob:none',
137
+ '--depth',
138
+ '1',
139
+ '--sparse',
140
+ ...(source.ref ? ['--branch', source.ref, '--single-branch'] : []),
141
+ source.remote,
142
+ cloneDir,
143
+ ],
144
+ { timeoutMs: 60_000 },
145
+ );
146
+ } catch (err) {
147
+ if (err instanceof GitError) {
148
+ console.error(pc.bold(pc.red(`git clone failed for ${source.remote}:`)));
149
+ console.error(err.stderr || err.message);
150
+ process.exit(1);
151
+ }
152
+
153
+ throw err;
154
+ }
155
+
156
+ try {
157
+ await runGit(['-C', cloneDir, 'sparse-checkout', 'set', '--no-cone', ...source.pattern], {
158
+ timeoutMs: 30_000,
159
+ });
160
+ } catch (err) {
161
+ if (err instanceof GitError) {
162
+ console.error(pc.bold(pc.red(`git sparse-checkout failed for ${source.remote}:`)));
163
+ console.error(err.stderr || err.message);
164
+ process.exit(1);
165
+ }
166
+
167
+ throw err;
168
+ }
169
+
170
+ const pulled = new Map<string, PulledLexicon>();
171
+
172
+ for await (const filename of fs.glob(source.pattern, { cwd: cloneDir })) {
173
+ const absolute = path.join(cloneDir, filename);
174
+ const stat = await fs.stat(absolute);
175
+
176
+ if (!stat.isFile()) {
177
+ continue;
178
+ }
179
+
180
+ const location: SourceLocation = {
181
+ absolutePath: absolute,
182
+ relativePath: filename,
183
+ sourceDescription: source.remote,
184
+ };
185
+
186
+ const doc = await parseLexiconFile(location);
187
+
188
+ pulled.set(doc.id, { nsid: doc.id, doc, location });
189
+ }
190
+
191
+ // get the commit hash
192
+ let rev: string;
193
+ try {
194
+ const result = await runGit(['-C', cloneDir, 'rev-parse', 'HEAD'], { timeoutMs: 10_000 });
195
+ rev = result.stdout.trim();
196
+ } catch (err) {
197
+ if (err instanceof GitError) {
198
+ console.error(pc.bold(pc.red(`git rev-parse failed for ${source.remote}:`)));
199
+ console.error(err.stderr || err.message);
200
+ process.exit(1);
201
+ }
202
+
203
+ throw err;
204
+ }
205
+
206
+ await fs.rm(tempParent, { recursive: true, force: true });
207
+
208
+ return { pulled, rev };
209
+ };
210
+
211
+ const pullSource = async (source: SourceConfig): Promise<PullResult> => {
212
+ switch (source.type) {
213
+ case 'git': {
214
+ return pullGitSource(source);
215
+ }
216
+ }
217
+ };
218
+
219
+ const writeSourceReadme = async (
220
+ outdir: string,
221
+ revisions: SourceRevision[],
222
+ prettierConfig: prettier.Options | null,
223
+ ): Promise<void> => {
224
+ const lines = [
225
+ '# lexicon sources',
226
+ '',
227
+ 'this directory contains lexicon documents pulled from the following sources:',
228
+ '',
229
+ ];
230
+
231
+ for (const { source, rev } of revisions) {
232
+ switch (source.type) {
233
+ case 'git': {
234
+ lines.push(`- ${source.remote}${source.ref ? ` (ref: ${source.ref})` : ``}`);
235
+ lines.push(` - commit: ${rev}`);
236
+ break;
237
+ }
238
+ }
239
+ }
240
+
241
+ lines.push('');
242
+
243
+ const content = lines.join('\n');
244
+ const formatted = await prettier.format(content, {
245
+ ...(prettierConfig ?? {}),
246
+ parser: 'markdown',
247
+ });
248
+
249
+ await fs.writeFile(path.join(outdir, 'README.md'), formatted);
250
+ };
251
+
252
+ /**
253
+ * pulls lexicon documents from configured sources and writes them to disk using nsid-based paths.
254
+ * @param config normalized lex-cli configuration
255
+ */
256
+ export const runPull = async (config: NormalizedConfig): Promise<void> => {
257
+ const pullConfig = ensurePullConfig(config);
258
+ const outdir = path.resolve(config.root, pullConfig.outdir);
259
+ const prettierConfig = await prettier.resolveConfig(config.root, { editorconfig: true });
260
+
261
+ const seen = new Map<string, SourceLocation>();
262
+ const collected: PulledLexicon[] = [];
263
+ const sourceRevisions: SourceRevision[] = [];
264
+
265
+ for (const source of pullConfig.sources) {
266
+ const result = await pullSource(source);
267
+
268
+ sourceRevisions.push({ source, rev: result.rev });
269
+
270
+ for (const [nsid, entry] of result.pulled) {
271
+ const existing = seen.get(nsid);
272
+
273
+ if (existing) {
274
+ console.error(pc.bold(pc.red(`duplicate lexicon "${nsid}"`)));
275
+ console.error(`- found ${entry.location.relativePath} from ${entry.location.sourceDescription}`);
276
+ console.error(` at ${entry.location.absolutePath}`);
277
+ console.error(`- already found ${existing.relativePath} from ${existing.sourceDescription}`);
278
+ console.error(` at ${existing.absolutePath}`);
279
+ process.exit(1);
280
+ }
281
+
282
+ seen.set(nsid, entry.location);
283
+ collected.push(entry);
284
+ }
285
+ }
286
+
287
+ if (pullConfig.clean) {
288
+ await fs.rm(outdir, { recursive: true, force: true });
289
+ }
290
+
291
+ await fs.mkdir(outdir, { recursive: true });
292
+
293
+ for (const entry of collected) {
294
+ await writeLexicon(outdir, entry.nsid, entry.doc, prettierConfig);
295
+ }
296
+
297
+ await writeSourceReadme(outdir, sourceRevisions, prettierConfig);
298
+ };