@atproto/lex-builder 0.0.13 → 0.0.15
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/CHANGELOG.md +16 -0
- package/dist/filter.d.ts +55 -0
- package/dist/filter.d.ts.map +1 -1
- package/dist/filter.js +22 -0
- package/dist/filter.js.map +1 -1
- package/dist/formatter.d.ts +42 -1
- package/dist/formatter.d.ts.map +1 -1
- package/dist/formatter.js +25 -0
- package/dist/formatter.js.map +1 -1
- package/dist/index.d.ts +34 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +24 -0
- package/dist/index.js.map +1 -1
- package/dist/lex-builder.d.ts +69 -0
- package/dist/lex-builder.d.ts.map +1 -1
- package/dist/lex-builder.js +20 -0
- package/dist/lex-builder.js.map +1 -1
- package/dist/lex-def-builder.d.ts +37 -1
- package/dist/lex-def-builder.d.ts.map +1 -1
- package/dist/lex-def-builder.js +11 -1
- package/dist/lex-def-builder.js.map +1 -1
- package/dist/lexicon-directory-indexer.d.ts +13 -0
- package/dist/lexicon-directory-indexer.d.ts.map +1 -1
- package/dist/lexicon-directory-indexer.js +8 -0
- package/dist/lexicon-directory-indexer.js.map +1 -1
- package/dist/ref-resolver.d.ts +72 -2
- package/dist/ref-resolver.d.ts.map +1 -1
- package/dist/ref-resolver.js +47 -3
- package/dist/ref-resolver.js.map +1 -1
- package/dist/ts-lang.d.ts +44 -0
- package/dist/ts-lang.d.ts.map +1 -1
- package/dist/ts-lang.js +48 -1
- package/dist/ts-lang.js.map +1 -1
- package/package.json +3 -3
- package/src/filter.ts +55 -0
- package/src/formatter.ts +42 -1
- package/src/index.ts +34 -0
- package/src/lex-builder.ts +69 -0
- package/src/lex-def-builder.ts +37 -1
- package/src/lexicon-directory-indexer.ts +13 -0
- package/src/ref-resolver.test.ts +75 -0
- package/src/ref-resolver.ts +78 -6
- package/src/ts-lang.ts +48 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,21 @@
|
|
|
1
1
|
# @atproto/lex-builder
|
|
2
2
|
|
|
3
|
+
## 0.0.15
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [#4610](https://github.com/bluesky-social/atproto/pull/4610) [`619068f`](https://github.com/bluesky-social/atproto/commit/619068fb81203b3b43b632892bdcb0a5067f7fe4) Thanks [@gaearon](https://github.com/gaearon)! - Export `LexDefBuilder` class and add `moduleSpecifier` option to `RefResolverOptions` for custom external import resolution
|
|
8
|
+
|
|
9
|
+
## 0.0.14
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- [#4601](https://github.com/bluesky-social/atproto/pull/4601) [`ed61c62`](https://github.com/bluesky-social/atproto/commit/ed61c62f3161fcde85ee9a93f8ed339c7e06c015) Thanks [@matthieusieben](https://github.com/matthieusieben)! - Add JSDoc
|
|
14
|
+
|
|
15
|
+
- Updated dependencies [[`7b9a98a`](https://github.com/bluesky-social/atproto/commit/7b9a98a763636c5f66a06da11fe6013f29dd9157), [`7b9a98a`](https://github.com/bluesky-social/atproto/commit/7b9a98a763636c5f66a06da11fe6013f29dd9157), [`7b9a98a`](https://github.com/bluesky-social/atproto/commit/7b9a98a763636c5f66a06da11fe6013f29dd9157), [`7b9a98a`](https://github.com/bluesky-social/atproto/commit/7b9a98a763636c5f66a06da11fe6013f29dd9157), [`ed61c62`](https://github.com/bluesky-social/atproto/commit/ed61c62f3161fcde85ee9a93f8ed339c7e06c015), [`7b9a98a`](https://github.com/bluesky-social/atproto/commit/7b9a98a763636c5f66a06da11fe6013f29dd9157), [`7b9a98a`](https://github.com/bluesky-social/atproto/commit/7b9a98a763636c5f66a06da11fe6013f29dd9157), [`ed61c62`](https://github.com/bluesky-social/atproto/commit/ed61c62f3161fcde85ee9a93f8ed339c7e06c015)]:
|
|
16
|
+
- @atproto/lex-schema@0.0.12
|
|
17
|
+
- @atproto/lex-document@0.0.13
|
|
18
|
+
|
|
3
19
|
## 0.0.13
|
|
4
20
|
|
|
5
21
|
### Patch Changes
|
package/dist/filter.d.ts
CHANGED
|
@@ -1,7 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Options for building a filter function to include/exclude lexicon documents.
|
|
3
|
+
*/
|
|
1
4
|
export type BuildFilterOptions = {
|
|
5
|
+
/**
|
|
6
|
+
* Pattern(s) for lexicon NSIDs to include.
|
|
7
|
+
*
|
|
8
|
+
* Supports glob patterns with `*` as a wildcard that matches one or more
|
|
9
|
+
* characters. If not specified, all lexicons are included by default.
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* ```ts
|
|
13
|
+
* { include: 'app.bsky.*' } // Include all app.bsky lexicons
|
|
14
|
+
* { include: ['com.atproto.*', 'app.bsky.*'] } // Include multiple patterns
|
|
15
|
+
* ```
|
|
16
|
+
*/
|
|
2
17
|
include?: string | string[];
|
|
18
|
+
/**
|
|
19
|
+
* Pattern(s) for lexicon NSIDs to exclude.
|
|
20
|
+
*
|
|
21
|
+
* Supports glob patterns with `*` as a wildcard. Exclusions are applied
|
|
22
|
+
* after inclusions.
|
|
23
|
+
*
|
|
24
|
+
* @example
|
|
25
|
+
* ```ts
|
|
26
|
+
* { exclude: '*.internal.*' } // Exclude internal lexicons
|
|
27
|
+
* { exclude: ['*.test', '*.mock'] } // Exclude test and mock lexicons
|
|
28
|
+
* ```
|
|
29
|
+
*/
|
|
3
30
|
exclude?: string | string[];
|
|
4
31
|
};
|
|
32
|
+
/**
|
|
33
|
+
* A function that tests whether a lexicon NSID should be included.
|
|
34
|
+
*
|
|
35
|
+
* @param input - The lexicon NSID to test
|
|
36
|
+
* @returns `true` if the NSID passes the filter, `false` otherwise
|
|
37
|
+
*/
|
|
5
38
|
export type Filter = (input: string) => boolean;
|
|
39
|
+
/**
|
|
40
|
+
* Builds a filter function from include/exclude patterns.
|
|
41
|
+
*
|
|
42
|
+
* The returned filter returns `true` for NSIDs that match any include pattern
|
|
43
|
+
* (or all NSIDs if no include patterns are specified) AND do not match any
|
|
44
|
+
* exclude pattern.
|
|
45
|
+
*
|
|
46
|
+
* @param options - The filter options containing include/exclude patterns
|
|
47
|
+
* @returns A filter function that can be applied to lexicon NSIDs
|
|
48
|
+
*
|
|
49
|
+
* @example
|
|
50
|
+
* ```ts
|
|
51
|
+
* const filter = buildFilter({
|
|
52
|
+
* include: 'app.bsky.*',
|
|
53
|
+
* exclude: '*.internal.*',
|
|
54
|
+
* })
|
|
55
|
+
*
|
|
56
|
+
* filter('app.bsky.feed.post') // true
|
|
57
|
+
* filter('app.bsky.internal.foo') // false
|
|
58
|
+
* filter('com.atproto.repo') // false (not included)
|
|
59
|
+
* ```
|
|
60
|
+
*/
|
|
6
61
|
export declare function buildFilter(options: BuildFilterOptions): Filter;
|
|
7
62
|
//# sourceMappingURL=filter.d.ts.map
|
package/dist/filter.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"filter.d.ts","sourceRoot":"","sources":["../src/filter.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,kBAAkB,GAAG;IAC/B,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAA;IAC3B,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAA;CAC5B,CAAA;AAED,MAAM,MAAM,MAAM,GAAG,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAA;AAE/C,wBAAgB,WAAW,CAAC,OAAO,EAAE,kBAAkB,GAAG,MAAM,CAK/D"}
|
|
1
|
+
{"version":3,"file":"filter.d.ts","sourceRoot":"","sources":["../src/filter.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,MAAM,kBAAkB,GAAG;IAC/B;;;;;;;;;;;OAWG;IACH,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAA;IAC3B;;;;;;;;;;;OAWG;IACH,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAA;CAC5B,CAAA;AAED;;;;;GAKG;AACH,MAAM,MAAM,MAAM,GAAG,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAA;AAE/C;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,kBAAkB,GAAG,MAAM,CAK/D"}
|
package/dist/filter.js
CHANGED
|
@@ -1,6 +1,28 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.buildFilter = buildFilter;
|
|
4
|
+
/**
|
|
5
|
+
* Builds a filter function from include/exclude patterns.
|
|
6
|
+
*
|
|
7
|
+
* The returned filter returns `true` for NSIDs that match any include pattern
|
|
8
|
+
* (or all NSIDs if no include patterns are specified) AND do not match any
|
|
9
|
+
* exclude pattern.
|
|
10
|
+
*
|
|
11
|
+
* @param options - The filter options containing include/exclude patterns
|
|
12
|
+
* @returns A filter function that can be applied to lexicon NSIDs
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* ```ts
|
|
16
|
+
* const filter = buildFilter({
|
|
17
|
+
* include: 'app.bsky.*',
|
|
18
|
+
* exclude: '*.internal.*',
|
|
19
|
+
* })
|
|
20
|
+
*
|
|
21
|
+
* filter('app.bsky.feed.post') // true
|
|
22
|
+
* filter('app.bsky.internal.foo') // false
|
|
23
|
+
* filter('com.atproto.repo') // false (not included)
|
|
24
|
+
* ```
|
|
25
|
+
*/
|
|
4
26
|
function buildFilter(options) {
|
|
5
27
|
const include = createMatcher(options.include, () => true);
|
|
6
28
|
const exclude = createMatcher(options.exclude, () => false);
|
package/dist/filter.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"filter.js","sourceRoot":"","sources":["../src/filter.ts"],"names":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"filter.js","sourceRoot":"","sources":["../src/filter.ts"],"names":[],"mappings":";;AA8DA,kCAKC;AA3BD;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,SAAgB,WAAW,CAAC,OAA2B;IACrD,MAAM,OAAO,GAAG,aAAa,CAAC,OAAO,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,CAAA;IAC1D,MAAM,OAAO,GAAG,aAAa,CAAC,OAAO,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,KAAK,CAAC,CAAA;IAE3D,OAAO,CAAC,EAAE,EAAE,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,CAAA;AAC5C,CAAC;AAED,SAAS,aAAa,CACpB,OAAsC,EACtC,QAAgB;IAEhB,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,CAAC;QACrB,OAAO,QAAQ,CAAA;IACjB,CAAC;SAAM,IAAI,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;QAClC,OAAO,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC,MAAM,CAAC,cAAc,CAAC,CAAA;IACzD,CAAC;SAAM,CAAC;QACN,OAAO,YAAY,CAAC,OAAO,CAAC,CAAA;IAC9B,CAAC;AACH,CAAC;AAED,SAAS,cAAc,CAAC,CAAS,EAAE,CAAS;IAC1C,OAAO,CAAC,KAAa,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,CAAA;AAChD,CAAC;AAED,SAAS,YAAY,CAAC,OAAe;IACnC,IAAI,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;QAC1B,MAAM,KAAK,GAAG,IAAI,MAAM,CACtB,IAAI,OAAO,CAAC,UAAU,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC,UAAU,CAAC,GAAG,EAAE,IAAI,CAAC,GAAG,CAC5D,CAAA;QACD,OAAO,CAAC,KAAa,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;IAC7C,CAAC;IAED,OAAO,CAAC,KAAa,EAAE,EAAE,CAAC,OAAO,KAAK,KAAK,CAAA;AAC7C,CAAC","sourcesContent":["/**\n * Options for building a filter function to include/exclude lexicon documents.\n */\nexport type BuildFilterOptions = {\n /**\n * Pattern(s) for lexicon NSIDs to include.\n *\n * Supports glob patterns with `*` as a wildcard that matches one or more\n * characters. If not specified, all lexicons are included by default.\n *\n * @example\n * ```ts\n * { include: 'app.bsky.*' } // Include all app.bsky lexicons\n * { include: ['com.atproto.*', 'app.bsky.*'] } // Include multiple patterns\n * ```\n */\n include?: string | string[]\n /**\n * Pattern(s) for lexicon NSIDs to exclude.\n *\n * Supports glob patterns with `*` as a wildcard. Exclusions are applied\n * after inclusions.\n *\n * @example\n * ```ts\n * { exclude: '*.internal.*' } // Exclude internal lexicons\n * { exclude: ['*.test', '*.mock'] } // Exclude test and mock lexicons\n * ```\n */\n exclude?: string | string[]\n}\n\n/**\n * A function that tests whether a lexicon NSID should be included.\n *\n * @param input - The lexicon NSID to test\n * @returns `true` if the NSID passes the filter, `false` otherwise\n */\nexport type Filter = (input: string) => boolean\n\n/**\n * Builds a filter function from include/exclude patterns.\n *\n * The returned filter returns `true` for NSIDs that match any include pattern\n * (or all NSIDs if no include patterns are specified) AND do not match any\n * exclude pattern.\n *\n * @param options - The filter options containing include/exclude patterns\n * @returns A filter function that can be applied to lexicon NSIDs\n *\n * @example\n * ```ts\n * const filter = buildFilter({\n * include: 'app.bsky.*',\n * exclude: '*.internal.*',\n * })\n *\n * filter('app.bsky.feed.post') // true\n * filter('app.bsky.internal.foo') // false\n * filter('com.atproto.repo') // false (not included)\n * ```\n */\nexport function buildFilter(options: BuildFilterOptions): Filter {\n const include = createMatcher(options.include, () => true)\n const exclude = createMatcher(options.exclude, () => false)\n\n return (id) => include(id) && !exclude(id)\n}\n\nfunction createMatcher(\n pattern: undefined | string | string[],\n fallback: Filter,\n): Filter {\n if (!pattern?.length) {\n return fallback\n } else if (Array.isArray(pattern)) {\n return pattern.map(buildMatcher).reduce(combineFilters)\n } else {\n return buildMatcher(pattern)\n }\n}\n\nfunction combineFilters(a: Filter, b: Filter): Filter {\n return (input: string) => a(input) || b(input)\n}\n\nfunction buildMatcher(pattern: string): Filter {\n if (pattern.includes('*')) {\n const regex = new RegExp(\n `^${pattern.replaceAll('.', '\\\\.').replaceAll('*', '.+')}$`,\n )\n return (input: string) => regex.test(input)\n }\n\n return (input: string) => pattern === input\n}\n"]}
|
package/dist/formatter.d.ts
CHANGED
|
@@ -1,13 +1,54 @@
|
|
|
1
1
|
import { Options as PrettierOptions } from 'prettier';
|
|
2
|
+
/**
|
|
3
|
+
* Options for configuring the code formatter.
|
|
4
|
+
*/
|
|
2
5
|
export type FormatterOptions = {
|
|
3
|
-
/**
|
|
6
|
+
/**
|
|
7
|
+
* Whether to format the generated code with Prettier.
|
|
8
|
+
*
|
|
9
|
+
* - `false`: No formatting (default)
|
|
10
|
+
* - `true`: Format with default Prettier options
|
|
11
|
+
* - `PrettierOptions`: Format with custom Prettier configuration
|
|
12
|
+
*
|
|
13
|
+
* @default false
|
|
14
|
+
*/
|
|
4
15
|
pretty?: boolean | PrettierOptions;
|
|
16
|
+
/**
|
|
17
|
+
* A banner comment to prepend to each generated file.
|
|
18
|
+
*
|
|
19
|
+
* @default '/* THIS FILE WAS GENERATED BY "@atproto/lex". DO NOT EDIT. *\/'
|
|
20
|
+
*/
|
|
5
21
|
banner?: string;
|
|
6
22
|
};
|
|
23
|
+
/**
|
|
24
|
+
* Formats generated TypeScript code with optional Prettier formatting
|
|
25
|
+
* and banner comments.
|
|
26
|
+
*
|
|
27
|
+
* @example
|
|
28
|
+
* ```ts
|
|
29
|
+
* const formatter = new Formatter({ pretty: true })
|
|
30
|
+
* const formatted = await formatter.format(generatedCode)
|
|
31
|
+
* ```
|
|
32
|
+
*/
|
|
7
33
|
export declare class Formatter {
|
|
34
|
+
/** The banner comment to prepend to formatted code. */
|
|
8
35
|
readonly banner: string;
|
|
36
|
+
/** Prettier options, or `null` if formatting is disabled. */
|
|
9
37
|
readonly prettierOptions: PrettierOptions | null;
|
|
38
|
+
/**
|
|
39
|
+
* Creates a new Formatter instance.
|
|
40
|
+
*
|
|
41
|
+
* @param options - Formatting configuration options
|
|
42
|
+
*/
|
|
10
43
|
constructor(options?: FormatterOptions);
|
|
44
|
+
/**
|
|
45
|
+
* Formats the given code string.
|
|
46
|
+
*
|
|
47
|
+
* Applies Prettier formatting if enabled, and prepends the banner comment.
|
|
48
|
+
*
|
|
49
|
+
* @param code - The TypeScript code to format
|
|
50
|
+
* @returns The formatted code with banner
|
|
51
|
+
*/
|
|
11
52
|
format(code: string): Promise<string>;
|
|
12
53
|
}
|
|
13
54
|
//# sourceMappingURL=formatter.d.ts.map
|
package/dist/formatter.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"formatter.d.ts","sourceRoot":"","sources":["../src/formatter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,eAAe,EAA4B,MAAM,UAAU,CAAA;AAc/E,MAAM,MAAM,gBAAgB,GAAG;IAC7B
|
|
1
|
+
{"version":3,"file":"formatter.d.ts","sourceRoot":"","sources":["../src/formatter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,eAAe,EAA4B,MAAM,UAAU,CAAA;AAc/E;;GAEG;AACH,MAAM,MAAM,gBAAgB,GAAG;IAC7B;;;;;;;;OAQG;IACH,MAAM,CAAC,EAAE,OAAO,GAAG,eAAe,CAAA;IAClC;;;;OAIG;IACH,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB,CAAA;AAED;;;;;;;;;GASG;AACH,qBAAa,SAAS;IACpB,uDAAuD;IACvD,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,6DAA6D;IAC7D,QAAQ,CAAC,eAAe,EAAE,eAAe,GAAG,IAAI,CAAA;IAEhD;;;;OAIG;gBACS,OAAO,GAAE,gBAAqB;IAS1C;;;;;;;OAOG;IACG,MAAM,CAAC,IAAI,EAAE,MAAM;CAQ1B"}
|
package/dist/formatter.js
CHANGED
|
@@ -12,9 +12,26 @@ const DEFAULT_FORMAT_OPTIONS = {
|
|
|
12
12
|
const DEFAULT_BANNER = `/*
|
|
13
13
|
* THIS FILE WAS GENERATED BY "@atproto/lex". DO NOT EDIT.
|
|
14
14
|
*/`;
|
|
15
|
+
/**
|
|
16
|
+
* Formats generated TypeScript code with optional Prettier formatting
|
|
17
|
+
* and banner comments.
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* ```ts
|
|
21
|
+
* const formatter = new Formatter({ pretty: true })
|
|
22
|
+
* const formatted = await formatter.format(generatedCode)
|
|
23
|
+
* ```
|
|
24
|
+
*/
|
|
15
25
|
class Formatter {
|
|
26
|
+
/** The banner comment to prepend to formatted code. */
|
|
16
27
|
banner;
|
|
28
|
+
/** Prettier options, or `null` if formatting is disabled. */
|
|
17
29
|
prettierOptions;
|
|
30
|
+
/**
|
|
31
|
+
* Creates a new Formatter instance.
|
|
32
|
+
*
|
|
33
|
+
* @param options - Formatting configuration options
|
|
34
|
+
*/
|
|
18
35
|
constructor(options = {}) {
|
|
19
36
|
this.banner = options?.banner ?? DEFAULT_BANNER;
|
|
20
37
|
this.prettierOptions =
|
|
@@ -22,6 +39,14 @@ class Formatter {
|
|
|
22
39
|
? DEFAULT_FORMAT_OPTIONS
|
|
23
40
|
: options?.pretty || null;
|
|
24
41
|
}
|
|
42
|
+
/**
|
|
43
|
+
* Formats the given code string.
|
|
44
|
+
*
|
|
45
|
+
* Applies Prettier formatting if enabled, and prepends the banner comment.
|
|
46
|
+
*
|
|
47
|
+
* @param code - The TypeScript code to format
|
|
48
|
+
* @returns The formatted code with banner
|
|
49
|
+
*/
|
|
25
50
|
async format(code) {
|
|
26
51
|
const bannerPadding = this.banner && !this.banner.endsWith('\n') ? '\n\n' : '';
|
|
27
52
|
const codePretty = this.prettierOptions
|
package/dist/formatter.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"formatter.js","sourceRoot":"","sources":["../src/formatter.ts"],"names":[],"mappings":";;;AAAA,uCAA+E;AAE/E,MAAM,sBAAsB,GAAoB;IAC9C,MAAM,EAAE,YAAY;IACpB,QAAQ,EAAE,CAAC;IACX,IAAI,EAAE,KAAK;IACX,WAAW,EAAE,IAAI;IACjB,aAAa,EAAE,KAAK;CACrB,CAAA;AAED,MAAM,cAAc,GAAG;;IAEnB,CAAA;
|
|
1
|
+
{"version":3,"file":"formatter.js","sourceRoot":"","sources":["../src/formatter.ts"],"names":[],"mappings":";;;AAAA,uCAA+E;AAE/E,MAAM,sBAAsB,GAAoB;IAC9C,MAAM,EAAE,YAAY;IACpB,QAAQ,EAAE,CAAC;IACX,IAAI,EAAE,KAAK;IACX,WAAW,EAAE,IAAI;IACjB,aAAa,EAAE,KAAK;CACrB,CAAA;AAED,MAAM,cAAc,GAAG;;IAEnB,CAAA;AAwBJ;;;;;;;;;GASG;AACH,MAAa,SAAS;IACpB,uDAAuD;IAC9C,MAAM,CAAQ;IACvB,6DAA6D;IACpD,eAAe,CAAwB;IAEhD;;;;OAIG;IACH,YAAY,UAA4B,EAAE;QACxC,IAAI,CAAC,MAAM,GAAG,OAAO,EAAE,MAAM,IAAI,cAAc,CAAA;QAE/C,IAAI,CAAC,eAAe;YAClB,OAAO,EAAE,MAAM,KAAK,IAAI;gBACtB,CAAC,CAAC,sBAAsB;gBACxB,CAAC,CAAC,OAAO,EAAE,MAAM,IAAI,IAAI,CAAA;IAC/B,CAAC;IAED;;;;;;;OAOG;IACH,KAAK,CAAC,MAAM,CAAC,IAAY;QACvB,MAAM,aAAa,GACjB,IAAI,CAAC,MAAM,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAA;QAC1D,MAAM,UAAU,GAAG,IAAI,CAAC,eAAe;YACrC,CAAC,CAAC,MAAM,IAAA,iBAAc,EAAC,IAAI,EAAE,IAAI,CAAC,eAAe,CAAC;YAClD,CAAC,CAAC,IAAI,CAAA;QACR,OAAO,GAAG,IAAI,CAAC,MAAM,GAAG,aAAa,GAAG,UAAU,EAAE,CAAA;IACtD,CAAC;CACF;AApCD,8BAoCC","sourcesContent":["import { Options as PrettierOptions, format as prettierFormat } from 'prettier'\n\nconst DEFAULT_FORMAT_OPTIONS: PrettierOptions = {\n parser: 'typescript',\n tabWidth: 2,\n semi: false,\n singleQuote: true,\n trailingComma: 'all',\n}\n\nconst DEFAULT_BANNER = `/*\n * THIS FILE WAS GENERATED BY \"@atproto/lex\". DO NOT EDIT.\n */`\n\n/**\n * Options for configuring the code formatter.\n */\nexport type FormatterOptions = {\n /**\n * Whether to format the generated code with Prettier.\n *\n * - `false`: No formatting (default)\n * - `true`: Format with default Prettier options\n * - `PrettierOptions`: Format with custom Prettier configuration\n *\n * @default false\n */\n pretty?: boolean | PrettierOptions\n /**\n * A banner comment to prepend to each generated file.\n *\n * @default '/* THIS FILE WAS GENERATED BY \"@atproto/lex\". DO NOT EDIT. *\\/'\n */\n banner?: string\n}\n\n/**\n * Formats generated TypeScript code with optional Prettier formatting\n * and banner comments.\n *\n * @example\n * ```ts\n * const formatter = new Formatter({ pretty: true })\n * const formatted = await formatter.format(generatedCode)\n * ```\n */\nexport class Formatter {\n /** The banner comment to prepend to formatted code. */\n readonly banner: string\n /** Prettier options, or `null` if formatting is disabled. */\n readonly prettierOptions: PrettierOptions | null\n\n /**\n * Creates a new Formatter instance.\n *\n * @param options - Formatting configuration options\n */\n constructor(options: FormatterOptions = {}) {\n this.banner = options?.banner ?? DEFAULT_BANNER\n\n this.prettierOptions =\n options?.pretty === true\n ? DEFAULT_FORMAT_OPTIONS\n : options?.pretty || null\n }\n\n /**\n * Formats the given code string.\n *\n * Applies Prettier formatting if enabled, and prepends the banner comment.\n *\n * @param code - The TypeScript code to format\n * @returns The formatted code with banner\n */\n async format(code: string) {\n const bannerPadding =\n this.banner && !this.banner.endsWith('\\n') ? '\\n\\n' : ''\n const codePretty = this.prettierOptions\n ? await prettierFormat(code, this.prettierOptions)\n : code\n return `${this.banner}${bannerPadding}${codePretty}`\n }\n}\n"]}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,41 @@
|
|
|
1
1
|
import './polyfill.js';
|
|
2
2
|
import { LexBuilderLoadOptions, LexBuilderOptions, LexBuilderSaveOptions } from './lex-builder.js';
|
|
3
3
|
export * from './lex-builder.js';
|
|
4
|
+
export * from './lex-def-builder.js';
|
|
4
5
|
export * from './lexicon-directory-indexer.js';
|
|
6
|
+
/**
|
|
7
|
+
* Combined options for building a TypeScript project from Lexicon documents.
|
|
8
|
+
*
|
|
9
|
+
* This type merges all configuration options needed for the complete build
|
|
10
|
+
* process, including builder configuration, loading options, and save options.
|
|
11
|
+
*
|
|
12
|
+
* @see {@link LexBuilderOptions} for builder configuration
|
|
13
|
+
* @see {@link LexBuilderLoadOptions} for lexicon loading options
|
|
14
|
+
* @see {@link LexBuilderSaveOptions} for output save options
|
|
15
|
+
*/
|
|
5
16
|
export type TsProjectBuildOptions = LexBuilderOptions & LexBuilderLoadOptions & LexBuilderSaveOptions;
|
|
17
|
+
/**
|
|
18
|
+
* Builds TypeScript schemas from Lexicon documents.
|
|
19
|
+
*
|
|
20
|
+
* This is the main entry point for programmatic usage of the lex-builder
|
|
21
|
+
* package. It creates a new {@link LexBuilder} instance, loads lexicon
|
|
22
|
+
* documents from the specified directory, and saves the generated TypeScript
|
|
23
|
+
* files to the output directory.
|
|
24
|
+
*
|
|
25
|
+
* @param options - Combined build options including source directory, output
|
|
26
|
+
* directory, and generation settings
|
|
27
|
+
*
|
|
28
|
+
* @example
|
|
29
|
+
* ```ts
|
|
30
|
+
* import { build } from '@atproto/lex-builder'
|
|
31
|
+
*
|
|
32
|
+
* await build({
|
|
33
|
+
* lexicons: './lexicons',
|
|
34
|
+
* out: './src/generated',
|
|
35
|
+
* pretty: true,
|
|
36
|
+
* clear: true,
|
|
37
|
+
* })
|
|
38
|
+
* ```
|
|
39
|
+
*/
|
|
6
40
|
export declare function build(options: TsProjectBuildOptions): Promise<void>;
|
|
7
41
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,eAAe,CAAA;AAEtB,OAAO,EAEL,qBAAqB,EACrB,iBAAiB,EACjB,qBAAqB,EACtB,MAAM,kBAAkB,CAAA;AAEzB,cAAc,kBAAkB,CAAA;AAChC,cAAc,gCAAgC,CAAA;AAE9C,MAAM,MAAM,qBAAqB,GAAG,iBAAiB,GACnD,qBAAqB,GACrB,qBAAqB,CAAA;AAEvB,wBAAsB,KAAK,CAAC,OAAO,EAAE,qBAAqB,iBAIzD"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,eAAe,CAAA;AAEtB,OAAO,EAEL,qBAAqB,EACrB,iBAAiB,EACjB,qBAAqB,EACtB,MAAM,kBAAkB,CAAA;AAEzB,cAAc,kBAAkB,CAAA;AAChC,cAAc,sBAAsB,CAAA;AACpC,cAAc,gCAAgC,CAAA;AAE9C;;;;;;;;;GASG;AACH,MAAM,MAAM,qBAAqB,GAAG,iBAAiB,GACnD,qBAAqB,GACrB,qBAAqB,CAAA;AAEvB;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAsB,KAAK,CAAC,OAAO,EAAE,qBAAqB,iBAIzD"}
|
package/dist/index.js
CHANGED
|
@@ -6,7 +6,31 @@ const tslib_1 = require("tslib");
|
|
|
6
6
|
require("./polyfill.js");
|
|
7
7
|
const lex_builder_js_1 = require("./lex-builder.js");
|
|
8
8
|
tslib_1.__exportStar(require("./lex-builder.js"), exports);
|
|
9
|
+
tslib_1.__exportStar(require("./lex-def-builder.js"), exports);
|
|
9
10
|
tslib_1.__exportStar(require("./lexicon-directory-indexer.js"), exports);
|
|
11
|
+
/**
|
|
12
|
+
* Builds TypeScript schemas from Lexicon documents.
|
|
13
|
+
*
|
|
14
|
+
* This is the main entry point for programmatic usage of the lex-builder
|
|
15
|
+
* package. It creates a new {@link LexBuilder} instance, loads lexicon
|
|
16
|
+
* documents from the specified directory, and saves the generated TypeScript
|
|
17
|
+
* files to the output directory.
|
|
18
|
+
*
|
|
19
|
+
* @param options - Combined build options including source directory, output
|
|
20
|
+
* directory, and generation settings
|
|
21
|
+
*
|
|
22
|
+
* @example
|
|
23
|
+
* ```ts
|
|
24
|
+
* import { build } from '@atproto/lex-builder'
|
|
25
|
+
*
|
|
26
|
+
* await build({
|
|
27
|
+
* lexicons: './lexicons',
|
|
28
|
+
* out: './src/generated',
|
|
29
|
+
* pretty: true,
|
|
30
|
+
* clear: true,
|
|
31
|
+
* })
|
|
32
|
+
* ```
|
|
33
|
+
*/
|
|
10
34
|
async function build(options) {
|
|
11
35
|
const builder = new lex_builder_js_1.LexBuilder(options);
|
|
12
36
|
await builder.load(options);
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;AAmDA,sBAIC;;AAvDD,gBAAgB;AAChB,yBAAsB;AAEtB,qDAKyB;AAEzB,2DAAgC;AAChC,+DAAoC;AACpC,yEAA8C;AAgB9C;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACI,KAAK,UAAU,KAAK,CAAC,OAA8B;IACxD,MAAM,OAAO,GAAG,IAAI,2BAAU,CAAC,OAAO,CAAC,CAAA;IACvC,MAAM,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;IAC3B,MAAM,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;AAC7B,CAAC","sourcesContent":["// Must be first\nimport './polyfill.js'\n\nimport {\n LexBuilder,\n LexBuilderLoadOptions,\n LexBuilderOptions,\n LexBuilderSaveOptions,\n} from './lex-builder.js'\n\nexport * from './lex-builder.js'\nexport * from './lex-def-builder.js'\nexport * from './lexicon-directory-indexer.js'\n\n/**\n * Combined options for building a TypeScript project from Lexicon documents.\n *\n * This type merges all configuration options needed for the complete build\n * process, including builder configuration, loading options, and save options.\n *\n * @see {@link LexBuilderOptions} for builder configuration\n * @see {@link LexBuilderLoadOptions} for lexicon loading options\n * @see {@link LexBuilderSaveOptions} for output save options\n */\nexport type TsProjectBuildOptions = LexBuilderOptions &\n LexBuilderLoadOptions &\n LexBuilderSaveOptions\n\n/**\n * Builds TypeScript schemas from Lexicon documents.\n *\n * This is the main entry point for programmatic usage of the lex-builder\n * package. It creates a new {@link LexBuilder} instance, loads lexicon\n * documents from the specified directory, and saves the generated TypeScript\n * files to the output directory.\n *\n * @param options - Combined build options including source directory, output\n * directory, and generation settings\n *\n * @example\n * ```ts\n * import { build } from '@atproto/lex-builder'\n *\n * await build({\n * lexicons: './lexicons',\n * out: './src/generated',\n * pretty: true,\n * clear: true,\n * })\n * ```\n */\nexport async function build(options: TsProjectBuildOptions) {\n const builder = new LexBuilder(options)\n await builder.load(options)\n await builder.save(options)\n}\n"]}
|
package/dist/lex-builder.d.ts
CHANGED
|
@@ -2,6 +2,14 @@ import { BuildFilterOptions } from './filter.js';
|
|
|
2
2
|
import { FormatterOptions } from './formatter.js';
|
|
3
3
|
import { LexDefBuilderOptions } from './lex-def-builder.js';
|
|
4
4
|
import { LexiconDirectoryIndexerOptions } from './lexicon-directory-indexer.js';
|
|
5
|
+
/**
|
|
6
|
+
* Configuration options for the {@link LexBuilder} class.
|
|
7
|
+
*
|
|
8
|
+
* Extends {@link LexDefBuilderOptions} with additional settings for
|
|
9
|
+
* controlling the generated TypeScript project structure.
|
|
10
|
+
*
|
|
11
|
+
* @see {@link LexDefBuilderOptions} for definition generation options
|
|
12
|
+
*/
|
|
5
13
|
export type LexBuilderOptions = LexDefBuilderOptions & {
|
|
6
14
|
/**
|
|
7
15
|
* Whether to generate an index file at the root exporting all top-level
|
|
@@ -11,15 +19,76 @@ export type LexBuilderOptions = LexDefBuilderOptions & {
|
|
|
11
19
|
* @default false
|
|
12
20
|
*/
|
|
13
21
|
indexFile?: boolean;
|
|
22
|
+
/**
|
|
23
|
+
* The file extension to use for import specifiers in the generated code.
|
|
24
|
+
*
|
|
25
|
+
* @default '.js'
|
|
26
|
+
*/
|
|
14
27
|
importExt?: string;
|
|
28
|
+
/**
|
|
29
|
+
* The file extension to use for generated TypeScript files.
|
|
30
|
+
*
|
|
31
|
+
* @default '.ts'
|
|
32
|
+
*/
|
|
15
33
|
fileExt?: string;
|
|
16
34
|
};
|
|
35
|
+
/**
|
|
36
|
+
* Options for loading lexicon documents into the builder.
|
|
37
|
+
*
|
|
38
|
+
* Combines directory indexing options with filtering options to control
|
|
39
|
+
* which lexicon documents are processed.
|
|
40
|
+
*
|
|
41
|
+
* @see {@link LexiconDirectoryIndexerOptions} for directory scanning options
|
|
42
|
+
* @see {@link BuildFilterOptions} for include/exclude filtering
|
|
43
|
+
*/
|
|
17
44
|
export type LexBuilderLoadOptions = LexiconDirectoryIndexerOptions & BuildFilterOptions;
|
|
45
|
+
/**
|
|
46
|
+
* Options for saving generated TypeScript files.
|
|
47
|
+
*
|
|
48
|
+
* Combines formatting options with output directory configuration.
|
|
49
|
+
*/
|
|
18
50
|
export type LexBuilderSaveOptions = FormatterOptions & {
|
|
51
|
+
/**
|
|
52
|
+
* The output directory path where generated TypeScript files will be written.
|
|
53
|
+
*/
|
|
19
54
|
out: string;
|
|
55
|
+
/**
|
|
56
|
+
* Whether to clear the output directory before writing files.
|
|
57
|
+
*
|
|
58
|
+
* When `true`, the entire output directory is deleted before writing new files.
|
|
59
|
+
*
|
|
60
|
+
* @default false
|
|
61
|
+
*/
|
|
20
62
|
clear?: boolean;
|
|
63
|
+
/**
|
|
64
|
+
* Whether to allow overwriting existing files.
|
|
65
|
+
*
|
|
66
|
+
* When `false`, an error is thrown if any output file already exists.
|
|
67
|
+
*
|
|
68
|
+
* @default false
|
|
69
|
+
*/
|
|
21
70
|
override?: boolean;
|
|
22
71
|
};
|
|
72
|
+
/**
|
|
73
|
+
* Main builder class for generating TypeScript schemas from Lexicon documents.
|
|
74
|
+
*
|
|
75
|
+
* The LexBuilder orchestrates the entire code generation process:
|
|
76
|
+
* 1. Loading and indexing lexicon documents from the filesystem
|
|
77
|
+
* 2. Generating TypeScript type definitions and runtime schemas
|
|
78
|
+
* 3. Creating namespace export trees for convenient imports
|
|
79
|
+
* 4. Saving formatted output files
|
|
80
|
+
*
|
|
81
|
+
* @example
|
|
82
|
+
* ```ts
|
|
83
|
+
* const builder = new LexBuilder({ indexFile: true, pretty: true })
|
|
84
|
+
*
|
|
85
|
+
* // Load lexicons from a directory
|
|
86
|
+
* await builder.load({ lexicons: './lexicons' })
|
|
87
|
+
*
|
|
88
|
+
* // Save generated TypeScript to output directory
|
|
89
|
+
* await builder.save({ out: './src/generated', clear: true })
|
|
90
|
+
* ```
|
|
91
|
+
*/
|
|
23
92
|
export declare class LexBuilder {
|
|
24
93
|
#private;
|
|
25
94
|
private readonly options;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lex-builder.d.ts","sourceRoot":"","sources":["../src/lex-builder.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,kBAAkB,EAAe,MAAM,aAAa,CAAA;AAE7D,OAAO,EAAa,gBAAgB,EAAE,MAAM,gBAAgB,CAAA;AAC5D,OAAO,EAAiB,oBAAoB,EAAE,MAAM,sBAAsB,CAAA;AAC1E,OAAO,EAEL,8BAA8B,EAC/B,MAAM,gCAAgC,CAAA;AAGvC,MAAM,MAAM,iBAAiB,GAAG,oBAAoB,GAAG;IACrD;;;;;;OAMG;IACH,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,OAAO,CAAC,EAAE,MAAM,CAAA;CACjB,CAAA;AAED,MAAM,MAAM,qBAAqB,GAAG,8BAA8B,GAChE,kBAAkB,CAAA;AAEpB,MAAM,MAAM,qBAAqB,GAAG,gBAAgB,GAAG;IACrD,GAAG,EAAE,MAAM,CAAA;IACX,KAAK,CAAC,EAAE,OAAO,CAAA;IACf,QAAQ,CAAC,EAAE,OAAO,CAAA;CACnB,CAAA;AAED,qBAAa,UAAU;;IAOT,OAAO,CAAC,QAAQ,CAAC,OAAO;gBAAP,OAAO,GAAE,iBAAsB;IAE5D,IAAI,OAAO,WAEV;IAED,IAAI,SAAS,WAEZ;IAEY,IAAI,CAAC,OAAO,EAAE,qBAAqB;IAkBnC,IAAI,CAAC,OAAO,EAAE,qBAAqB;IA4BhD,OAAO,CAAC,UAAU;IAIlB,OAAO,CAAC,OAAO;YAID,gBAAgB;YAyDhB,cAAc;CAU7B"}
|
|
1
|
+
{"version":3,"file":"lex-builder.d.ts","sourceRoot":"","sources":["../src/lex-builder.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,kBAAkB,EAAe,MAAM,aAAa,CAAA;AAE7D,OAAO,EAAa,gBAAgB,EAAE,MAAM,gBAAgB,CAAA;AAC5D,OAAO,EAAiB,oBAAoB,EAAE,MAAM,sBAAsB,CAAA;AAC1E,OAAO,EAEL,8BAA8B,EAC/B,MAAM,gCAAgC,CAAA;AAGvC;;;;;;;GAOG;AACH,MAAM,MAAM,iBAAiB,GAAG,oBAAoB,GAAG;IACrD;;;;;;OAMG;IACH,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB;;;;OAIG;IACH,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB;;;;OAIG;IACH,OAAO,CAAC,EAAE,MAAM,CAAA;CACjB,CAAA;AAED;;;;;;;;GAQG;AACH,MAAM,MAAM,qBAAqB,GAAG,8BAA8B,GAChE,kBAAkB,CAAA;AAEpB;;;;GAIG;AACH,MAAM,MAAM,qBAAqB,GAAG,gBAAgB,GAAG;IACrD;;OAEG;IACH,GAAG,EAAE,MAAM,CAAA;IACX;;;;;;OAMG;IACH,KAAK,CAAC,EAAE,OAAO,CAAA;IACf;;;;;;OAMG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAA;CACnB,CAAA;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,qBAAa,UAAU;;IAOT,OAAO,CAAC,QAAQ,CAAC,OAAO;gBAAP,OAAO,GAAE,iBAAsB;IAE5D,IAAI,OAAO,WAEV;IAED,IAAI,SAAS,WAEZ;IAEY,IAAI,CAAC,OAAO,EAAE,qBAAqB;IAkBnC,IAAI,CAAC,OAAO,EAAE,qBAAqB;IA4BhD,OAAO,CAAC,UAAU;IAIlB,OAAO,CAAC,OAAO;YAID,gBAAgB;YAyDhB,cAAc;CAU7B"}
|
package/dist/lex-builder.js
CHANGED
|
@@ -12,6 +12,26 @@ const formatter_js_1 = require("./formatter.js");
|
|
|
12
12
|
const lex_def_builder_js_1 = require("./lex-def-builder.js");
|
|
13
13
|
const lexicon_directory_indexer_js_1 = require("./lexicon-directory-indexer.js");
|
|
14
14
|
const ts_lang_js_1 = require("./ts-lang.js");
|
|
15
|
+
/**
|
|
16
|
+
* Main builder class for generating TypeScript schemas from Lexicon documents.
|
|
17
|
+
*
|
|
18
|
+
* The LexBuilder orchestrates the entire code generation process:
|
|
19
|
+
* 1. Loading and indexing lexicon documents from the filesystem
|
|
20
|
+
* 2. Generating TypeScript type definitions and runtime schemas
|
|
21
|
+
* 3. Creating namespace export trees for convenient imports
|
|
22
|
+
* 4. Saving formatted output files
|
|
23
|
+
*
|
|
24
|
+
* @example
|
|
25
|
+
* ```ts
|
|
26
|
+
* const builder = new LexBuilder({ indexFile: true, pretty: true })
|
|
27
|
+
*
|
|
28
|
+
* // Load lexicons from a directory
|
|
29
|
+
* await builder.load({ lexicons: './lexicons' })
|
|
30
|
+
*
|
|
31
|
+
* // Save generated TypeScript to output directory
|
|
32
|
+
* await builder.save({ out: './src/generated', clear: true })
|
|
33
|
+
* ```
|
|
34
|
+
*/
|
|
15
35
|
class LexBuilder {
|
|
16
36
|
options;
|
|
17
37
|
#imported = new Set();
|
package/dist/lex-builder.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lex-builder.js","sourceRoot":"","sources":["../src/lex-builder.ts"],"names":[],"mappings":"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","sourcesContent":["import assert from 'node:assert'\nimport { mkdir, rm, stat, writeFile } from 'node:fs/promises'\nimport { join, resolve } from 'node:path'\nimport { IndentationText, Project } from 'ts-morph'\nimport { LexiconDocument, LexiconIndexer } from '@atproto/lex-document'\nimport { BuildFilterOptions, buildFilter } from './filter.js'\nimport { FilteredIndexer } from './filtered-indexer.js'\nimport { Formatter, FormatterOptions } from './formatter.js'\nimport { LexDefBuilder, LexDefBuilderOptions } from './lex-def-builder.js'\nimport {\n LexiconDirectoryIndexer,\n LexiconDirectoryIndexerOptions,\n} from './lexicon-directory-indexer.js'\nimport { asNamespaceExport } from './ts-lang.js'\n\nexport type LexBuilderOptions = LexDefBuilderOptions & {\n /**\n * Whether to generate an index file at the root exporting all top-level\n * namespaces.\n *\n * @note This could theoretically cause name conflicts if a\n * @default false\n */\n indexFile?: boolean\n importExt?: string\n fileExt?: string\n}\n\nexport type LexBuilderLoadOptions = LexiconDirectoryIndexerOptions &\n BuildFilterOptions\n\nexport type LexBuilderSaveOptions = FormatterOptions & {\n out: string\n clear?: boolean\n override?: boolean\n}\n\nexport class LexBuilder {\n readonly #imported = new Set<string>()\n readonly #project = new Project({\n useInMemoryFileSystem: true,\n manipulationSettings: { indentationText: IndentationText.TwoSpaces },\n })\n\n constructor(private readonly options: LexBuilderOptions = {}) {}\n\n get fileExt() {\n return this.options.fileExt ?? '.ts'\n }\n\n get importExt() {\n return this.options.importExt ?? '.js'\n }\n\n public async load(options: LexBuilderLoadOptions) {\n await using indexer = new FilteredIndexer(\n new LexiconDirectoryIndexer(options),\n buildFilter(options),\n )\n\n for await (const doc of indexer) {\n if (!this.#imported.has(doc.id)) {\n this.#imported.add(doc.id)\n } else {\n throw new Error(`Duplicate lexicon document id: ${doc.id}`)\n }\n\n await this.createDefsFile(doc, indexer)\n await this.createExportTree(doc)\n }\n }\n\n public async save(options: LexBuilderSaveOptions) {\n const files = this.#project.getSourceFiles()\n\n const destination = resolve(options.out)\n\n if (options.clear) {\n await rm(destination, { recursive: true, force: true })\n } else if (!options.override) {\n await Promise.all(\n files.map(async (f) =>\n assertNotFileExists(join(destination, f.getFilePath())),\n ),\n )\n }\n\n const formatter = new Formatter(options)\n\n await Promise.all(\n Array.from(files, async (file) => {\n const filePath = join(destination, file.getFilePath())\n const content = await formatter.format(file.getFullText())\n await mkdir(join(filePath, '..'), { recursive: true })\n await rm(filePath, { recursive: true, force: true })\n await writeFile(filePath, content, 'utf8')\n }),\n )\n }\n\n private createFile(path: string) {\n return this.#project.createSourceFile(path)\n }\n\n private getFile(path: string) {\n return this.#project.getSourceFile(path) || this.createFile(path)\n }\n\n private async createExportTree(doc: LexiconDocument) {\n const namespaces = doc.id.split('.')\n\n if (this.options.indexFile) {\n const indexFile = this.getFile(`/index${this.fileExt}`)\n\n const tldNs = namespaces[0]!\n assert(\n tldNs !== 'index',\n 'The \"indexFile\" options cannot be used with namespaces using a \".index\" tld.',\n )\n const tldNsSpecifier = `./${tldNs}${this.importExt}`\n if (!indexFile.getExportDeclaration(tldNsSpecifier)) {\n indexFile.addExportDeclaration({\n moduleSpecifier: tldNsSpecifier,\n namespaceExport: asNamespaceExport(tldNs),\n })\n }\n }\n\n // First create the parent namespaces\n for (let i = 0; i < namespaces.length - 1; i++) {\n const currentNs = namespaces[i]\n const childNs = namespaces[i + 1]\n\n const path = join('/', ...namespaces.slice(0, i + 1))\n const file = this.getFile(`${path}${this.fileExt}`)\n\n const childModuleSpecifier = `./${currentNs}/${childNs}${this.importExt}`\n const dec = file.getExportDeclaration(childModuleSpecifier)\n if (!dec) {\n file.addExportDeclaration({\n moduleSpecifier: childModuleSpecifier,\n namespaceExport: asNamespaceExport(childNs),\n })\n }\n }\n\n // The child file exports the schemas (as *)\n const path = join('/', ...namespaces)\n const file = this.getFile(`${path}${this.fileExt}`)\n\n file.addExportDeclaration({\n moduleSpecifier: `./${namespaces.at(-1)}.defs${this.importExt}`,\n })\n\n // @NOTE Individual exports exports from the defs file might conflict with\n // child namespaces. For this reason, we also add a namespace export for the\n // defs (export * as $defs from './xyz.defs'). This is an escape hatch\n // allowing to still access the definitions if a hash get shadowed by a\n // child namespace.\n file.addExportDeclaration({\n moduleSpecifier: `./${namespaces.at(-1)}.defs${this.importExt}`,\n namespaceExport: '$defs',\n })\n }\n\n private async createDefsFile(\n doc: LexiconDocument,\n indexer: LexiconIndexer,\n ): Promise<void> {\n const path = join('/', ...doc.id.split('.'))\n const file = this.createFile(`${path}.defs${this.fileExt}`)\n\n const fileBuilder = new LexDefBuilder(this.options, file, doc, indexer)\n await fileBuilder.build()\n }\n}\n\nasync function assertNotFileExists(file: string): Promise<void> {\n try {\n await stat(file)\n throw new Error(`File already exists: ${file}`)\n } catch (err) {\n if (err instanceof Error && 'code' in err && err.code === 'ENOENT') return\n throw err\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"lex-builder.js","sourceRoot":"","sources":["../src/lex-builder.ts"],"names":[],"mappings":"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","sourcesContent":["import assert from 'node:assert'\nimport { mkdir, rm, stat, writeFile } from 'node:fs/promises'\nimport { join, resolve } from 'node:path'\nimport { IndentationText, Project } from 'ts-morph'\nimport { LexiconDocument, LexiconIndexer } from '@atproto/lex-document'\nimport { BuildFilterOptions, buildFilter } from './filter.js'\nimport { FilteredIndexer } from './filtered-indexer.js'\nimport { Formatter, FormatterOptions } from './formatter.js'\nimport { LexDefBuilder, LexDefBuilderOptions } from './lex-def-builder.js'\nimport {\n LexiconDirectoryIndexer,\n LexiconDirectoryIndexerOptions,\n} from './lexicon-directory-indexer.js'\nimport { asNamespaceExport } from './ts-lang.js'\n\n/**\n * Configuration options for the {@link LexBuilder} class.\n *\n * Extends {@link LexDefBuilderOptions} with additional settings for\n * controlling the generated TypeScript project structure.\n *\n * @see {@link LexDefBuilderOptions} for definition generation options\n */\nexport type LexBuilderOptions = LexDefBuilderOptions & {\n /**\n * Whether to generate an index file at the root exporting all top-level\n * namespaces.\n *\n * @note This could theoretically cause name conflicts if a\n * @default false\n */\n indexFile?: boolean\n /**\n * The file extension to use for import specifiers in the generated code.\n *\n * @default '.js'\n */\n importExt?: string\n /**\n * The file extension to use for generated TypeScript files.\n *\n * @default '.ts'\n */\n fileExt?: string\n}\n\n/**\n * Options for loading lexicon documents into the builder.\n *\n * Combines directory indexing options with filtering options to control\n * which lexicon documents are processed.\n *\n * @see {@link LexiconDirectoryIndexerOptions} for directory scanning options\n * @see {@link BuildFilterOptions} for include/exclude filtering\n */\nexport type LexBuilderLoadOptions = LexiconDirectoryIndexerOptions &\n BuildFilterOptions\n\n/**\n * Options for saving generated TypeScript files.\n *\n * Combines formatting options with output directory configuration.\n */\nexport type LexBuilderSaveOptions = FormatterOptions & {\n /**\n * The output directory path where generated TypeScript files will be written.\n */\n out: string\n /**\n * Whether to clear the output directory before writing files.\n *\n * When `true`, the entire output directory is deleted before writing new files.\n *\n * @default false\n */\n clear?: boolean\n /**\n * Whether to allow overwriting existing files.\n *\n * When `false`, an error is thrown if any output file already exists.\n *\n * @default false\n */\n override?: boolean\n}\n\n/**\n * Main builder class for generating TypeScript schemas from Lexicon documents.\n *\n * The LexBuilder orchestrates the entire code generation process:\n * 1. Loading and indexing lexicon documents from the filesystem\n * 2. Generating TypeScript type definitions and runtime schemas\n * 3. Creating namespace export trees for convenient imports\n * 4. Saving formatted output files\n *\n * @example\n * ```ts\n * const builder = new LexBuilder({ indexFile: true, pretty: true })\n *\n * // Load lexicons from a directory\n * await builder.load({ lexicons: './lexicons' })\n *\n * // Save generated TypeScript to output directory\n * await builder.save({ out: './src/generated', clear: true })\n * ```\n */\nexport class LexBuilder {\n readonly #imported = new Set<string>()\n readonly #project = new Project({\n useInMemoryFileSystem: true,\n manipulationSettings: { indentationText: IndentationText.TwoSpaces },\n })\n\n constructor(private readonly options: LexBuilderOptions = {}) {}\n\n get fileExt() {\n return this.options.fileExt ?? '.ts'\n }\n\n get importExt() {\n return this.options.importExt ?? '.js'\n }\n\n public async load(options: LexBuilderLoadOptions) {\n await using indexer = new FilteredIndexer(\n new LexiconDirectoryIndexer(options),\n buildFilter(options),\n )\n\n for await (const doc of indexer) {\n if (!this.#imported.has(doc.id)) {\n this.#imported.add(doc.id)\n } else {\n throw new Error(`Duplicate lexicon document id: ${doc.id}`)\n }\n\n await this.createDefsFile(doc, indexer)\n await this.createExportTree(doc)\n }\n }\n\n public async save(options: LexBuilderSaveOptions) {\n const files = this.#project.getSourceFiles()\n\n const destination = resolve(options.out)\n\n if (options.clear) {\n await rm(destination, { recursive: true, force: true })\n } else if (!options.override) {\n await Promise.all(\n files.map(async (f) =>\n assertNotFileExists(join(destination, f.getFilePath())),\n ),\n )\n }\n\n const formatter = new Formatter(options)\n\n await Promise.all(\n Array.from(files, async (file) => {\n const filePath = join(destination, file.getFilePath())\n const content = await formatter.format(file.getFullText())\n await mkdir(join(filePath, '..'), { recursive: true })\n await rm(filePath, { recursive: true, force: true })\n await writeFile(filePath, content, 'utf8')\n }),\n )\n }\n\n private createFile(path: string) {\n return this.#project.createSourceFile(path)\n }\n\n private getFile(path: string) {\n return this.#project.getSourceFile(path) || this.createFile(path)\n }\n\n private async createExportTree(doc: LexiconDocument) {\n const namespaces = doc.id.split('.')\n\n if (this.options.indexFile) {\n const indexFile = this.getFile(`/index${this.fileExt}`)\n\n const tldNs = namespaces[0]!\n assert(\n tldNs !== 'index',\n 'The \"indexFile\" options cannot be used with namespaces using a \".index\" tld.',\n )\n const tldNsSpecifier = `./${tldNs}${this.importExt}`\n if (!indexFile.getExportDeclaration(tldNsSpecifier)) {\n indexFile.addExportDeclaration({\n moduleSpecifier: tldNsSpecifier,\n namespaceExport: asNamespaceExport(tldNs),\n })\n }\n }\n\n // First create the parent namespaces\n for (let i = 0; i < namespaces.length - 1; i++) {\n const currentNs = namespaces[i]\n const childNs = namespaces[i + 1]\n\n const path = join('/', ...namespaces.slice(0, i + 1))\n const file = this.getFile(`${path}${this.fileExt}`)\n\n const childModuleSpecifier = `./${currentNs}/${childNs}${this.importExt}`\n const dec = file.getExportDeclaration(childModuleSpecifier)\n if (!dec) {\n file.addExportDeclaration({\n moduleSpecifier: childModuleSpecifier,\n namespaceExport: asNamespaceExport(childNs),\n })\n }\n }\n\n // The child file exports the schemas (as *)\n const path = join('/', ...namespaces)\n const file = this.getFile(`${path}${this.fileExt}`)\n\n file.addExportDeclaration({\n moduleSpecifier: `./${namespaces.at(-1)}.defs${this.importExt}`,\n })\n\n // @NOTE Individual exports exports from the defs file might conflict with\n // child namespaces. For this reason, we also add a namespace export for the\n // defs (export * as $defs from './xyz.defs'). This is an escape hatch\n // allowing to still access the definitions if a hash get shadowed by a\n // child namespace.\n file.addExportDeclaration({\n moduleSpecifier: `./${namespaces.at(-1)}.defs${this.importExt}`,\n namespaceExport: '$defs',\n })\n }\n\n private async createDefsFile(\n doc: LexiconDocument,\n indexer: LexiconIndexer,\n ): Promise<void> {\n const path = join('/', ...doc.id.split('.'))\n const file = this.createFile(`${path}.defs${this.fileExt}`)\n\n const fileBuilder = new LexDefBuilder(this.options, file, doc, indexer)\n await fileBuilder.build()\n }\n}\n\nasync function assertNotFileExists(file: string): Promise<void> {\n try {\n await stat(file)\n throw new Error(`File already exists: ${file}`)\n } catch (err) {\n if (err instanceof Error && 'code' in err && err.code === 'ENOENT') return\n throw err\n }\n}\n"]}
|
|
@@ -1,13 +1,49 @@
|
|
|
1
1
|
import { SourceFile } from 'ts-morph';
|
|
2
2
|
import { LexiconDocument, LexiconIndexer, LexiconProcedure, LexiconQuery, LexiconSubscription } from '@atproto/lex-document';
|
|
3
3
|
import { RefResolverOptions, ResolvedRef } from './ref-resolver.js';
|
|
4
|
+
/**
|
|
5
|
+
* Configuration options for the {@link LexDefBuilder} class.
|
|
6
|
+
*
|
|
7
|
+
* @see {@link RefResolverOptions} for reference resolution options
|
|
8
|
+
*/
|
|
4
9
|
export type LexDefBuilderOptions = RefResolverOptions & {
|
|
10
|
+
/**
|
|
11
|
+
* The module specifier to use for importing the lexicon schema library.
|
|
12
|
+
*
|
|
13
|
+
* @default '@atproto/lex-schema'
|
|
14
|
+
*/
|
|
5
15
|
lib?: string;
|
|
16
|
+
/**
|
|
17
|
+
* Whether to allow legacy blob references in the generated schemas.
|
|
18
|
+
*
|
|
19
|
+
* When `true`, blob types will accept both modern `BlobRef` and legacy
|
|
20
|
+
* `LegacyBlobRef` formats.
|
|
21
|
+
*
|
|
22
|
+
* @default false
|
|
23
|
+
*/
|
|
6
24
|
allowLegacyBlobs?: boolean;
|
|
25
|
+
/**
|
|
26
|
+
* Whether to add `#__PURE__` annotations to function calls.
|
|
27
|
+
*
|
|
28
|
+
* These annotations help bundlers with tree-shaking by marking
|
|
29
|
+
* side-effect-free function calls.
|
|
30
|
+
*
|
|
31
|
+
* @default false
|
|
32
|
+
*/
|
|
7
33
|
pureAnnotations?: boolean;
|
|
8
34
|
};
|
|
9
35
|
/**
|
|
10
|
-
*
|
|
36
|
+
* Builds TypeScript type definitions and runtime schemas from a single
|
|
37
|
+
* Lexicon document.
|
|
38
|
+
*
|
|
39
|
+
* This class is responsible for generating the `.defs.ts` files that contain:
|
|
40
|
+
* - Type aliases for each lexicon definition
|
|
41
|
+
* - Runtime schema validators using `@atproto/lex-schema`
|
|
42
|
+
* - Utility functions for type checking and validation
|
|
43
|
+
* - Proper import statements for cross-references
|
|
44
|
+
*
|
|
45
|
+
* Each lexicon definition type (record, object, query, procedure, etc.)
|
|
46
|
+
* is handled with specialized code generation logic.
|
|
11
47
|
*/
|
|
12
48
|
export declare class LexDefBuilder {
|
|
13
49
|
private readonly options;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lex-def-builder.d.ts","sourceRoot":"","sources":["../src/lex-def-builder.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,UAAU,EAEX,MAAM,UAAU,CAAA;AACjB,OAAO,EAOL,eAAe,EAEf,cAAc,EAMd,gBAAgB,EAChB,YAAY,EAKZ,mBAAmB,EAGpB,MAAM,uBAAuB,CAAA;AAE9B,OAAO,EAEL,kBAAkB,EAClB,WAAW,EAEZ,MAAM,mBAAmB,CAAA;AAG1B,MAAM,MAAM,oBAAoB,GAAG,kBAAkB,GAAG;IACtD,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,gBAAgB,CAAC,EAAE,OAAO,CAAA;IAC1B,eAAe,CAAC,EAAE,OAAO,CAAA;CAC1B,CAAA;AAED
|
|
1
|
+
{"version":3,"file":"lex-def-builder.d.ts","sourceRoot":"","sources":["../src/lex-def-builder.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,UAAU,EAEX,MAAM,UAAU,CAAA;AACjB,OAAO,EAOL,eAAe,EAEf,cAAc,EAMd,gBAAgB,EAChB,YAAY,EAKZ,mBAAmB,EAGpB,MAAM,uBAAuB,CAAA;AAE9B,OAAO,EAEL,kBAAkB,EAClB,WAAW,EAEZ,MAAM,mBAAmB,CAAA;AAG1B;;;;GAIG;AACH,MAAM,MAAM,oBAAoB,GAAG,kBAAkB,GAAG;IACtD;;;;OAIG;IACH,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ;;;;;;;OAOG;IACH,gBAAgB,CAAC,EAAE,OAAO,CAAA;IAC1B;;;;;;;OAOG;IACH,eAAe,CAAC,EAAE,OAAO,CAAA;CAC1B,CAAA;AAED;;;;;;;;;;;;GAYG;AACH,qBAAa,aAAa;IAItB,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,IAAI;IACrB,OAAO,CAAC,QAAQ,CAAC,GAAG;IALtB,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAa;gBAGtB,OAAO,EAAE,oBAAoB,EAC7B,IAAI,EAAE,UAAU,EAChB,GAAG,EAAE,eAAe,EACrC,OAAO,EAAE,cAAc;IAKzB,OAAO,CAAC,IAAI;IAIN,KAAK;IAyBX,OAAO,CAAC,QAAQ;YAgBF,MAAM;YA8BN,gBAAgB;YAsBhB,YAAY;YA4BZ,QAAQ;YA0BR,eAAe;IA0B7B,kBAAkB,CAChB,GAAG,EAAE,WAAW,EAChB,GAAG,EAAE,gBAAgB,GAAG,YAAY,GAAG,mBAAmB;YAmD9C,SAAS;YAsBT,SAAS;YAiBT,QAAQ;YAQR,QAAQ;YAuBR,SAAS;YA2FT,cAAc;YAkBd,iBAAiB;YAQjB,mBAAmB;YAWnB,aAAa;YAKb,mBAAmB;YAKnB,wBAAwB;YAsBxB,sBAAsB;YAYtB,0BAA0B;YAuB1B,wBAAwB;YAoBxB,sBAAsB;YA8BtB,oBAAoB;YA8BpB,kBAAkB;YASlB,gBAAgB;YAIhB,oBAAoB;YAIpB,kBAAkB;IAIhC,OAAO,CAAC,WAAW;YAQL,oBAAoB;YAYpB,kBAAkB;YAKlB,oBAAoB;YA0BpB,kBAAkB;YAOlB,mBAAmB;YA6BnB,iBAAiB;YA2CjB,kBAAkB;YAQlB,gBAAgB;YAIhB,iBAAiB;YAUjB,eAAe;YAMf,oBAAoB;YAIpB,kBAAkB;YAIlB,gBAAgB;YAOhB,cAAc;YAKd,qBAAqB;YAmBrB,mBAAmB;YAWnB,kBAAkB;YAYlB,gBAAgB;YAShB,iBAAiB;YAgBjB,eAAe;CAK9B"}
|
package/dist/lex-def-builder.js
CHANGED
|
@@ -6,7 +6,17 @@ const lex_schema_1 = require("@atproto/lex-schema");
|
|
|
6
6
|
const ref_resolver_js_1 = require("./ref-resolver.js");
|
|
7
7
|
const ts_lang_js_1 = require("./ts-lang.js");
|
|
8
8
|
/**
|
|
9
|
-
*
|
|
9
|
+
* Builds TypeScript type definitions and runtime schemas from a single
|
|
10
|
+
* Lexicon document.
|
|
11
|
+
*
|
|
12
|
+
* This class is responsible for generating the `.defs.ts` files that contain:
|
|
13
|
+
* - Type aliases for each lexicon definition
|
|
14
|
+
* - Runtime schema validators using `@atproto/lex-schema`
|
|
15
|
+
* - Utility functions for type checking and validation
|
|
16
|
+
* - Proper import statements for cross-references
|
|
17
|
+
*
|
|
18
|
+
* Each lexicon definition type (record, object, query, procedure, etc.)
|
|
19
|
+
* is handled with specialized code generation logic.
|
|
10
20
|
*/
|
|
11
21
|
class LexDefBuilder {
|
|
12
22
|
options;
|