@gaearon/lex-builder 0.0.13
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 +144 -0
- package/dist/filter.d.ts +7 -0
- package/dist/filter.d.ts.map +1 -0
- package/dist/filter.js +30 -0
- package/dist/filter.js.map +1 -0
- package/dist/filtered-indexer.d.ts +2100 -0
- package/dist/filtered-indexer.d.ts.map +1 -0
- package/dist/filtered-indexer.js +56 -0
- package/dist/filtered-indexer.js.map +1 -0
- package/dist/formatter.d.ts +13 -0
- package/dist/formatter.d.ts.map +1 -0
- package/dist/formatter.js +34 -0
- package/dist/formatter.js.map +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +16 -0
- package/dist/index.js.map +1 -0
- package/dist/lex-builder.d.ts +36 -0
- package/dist/lex-builder.d.ts.map +1 -0
- package/dist/lex-builder.js +144 -0
- package/dist/lex-builder.js.map +1 -0
- package/dist/lex-def-builder.d.ts +69 -0
- package/dist/lex-def-builder.d.ts.map +1 -0
- package/dist/lex-def-builder.js +734 -0
- package/dist/lex-def-builder.js.map +1 -0
- package/dist/lexicon-directory-indexer.d.ts +11 -0
- package/dist/lexicon-directory-indexer.d.ts.map +1 -0
- package/dist/lexicon-directory-indexer.js +46 -0
- package/dist/lexicon-directory-indexer.js.map +1 -0
- package/dist/polyfill.d.ts +1 -0
- package/dist/polyfill.d.ts.map +1 -0
- package/dist/polyfill.js +7 -0
- package/dist/polyfill.js.map +1 -0
- package/dist/ref-resolver.d.ts +53 -0
- package/dist/ref-resolver.d.ts.map +1 -0
- package/dist/ref-resolver.js +277 -0
- package/dist/ref-resolver.js.map +1 -0
- package/dist/ts-lang.d.ts +6 -0
- package/dist/ts-lang.d.ts.map +1 -0
- package/dist/ts-lang.js +150 -0
- package/dist/ts-lang.js.map +1 -0
- package/dist/util.d.ts +12 -0
- package/dist/util.d.ts.map +1 -0
- package/dist/util.js +72 -0
- package/dist/util.js.map +1 -0
- package/package.json +53 -0
- package/src/filter.ts +41 -0
- package/src/filtered-indexer.test.ts +84 -0
- package/src/filtered-indexer.ts +60 -0
- package/src/formatter.ts +42 -0
- package/src/index.ts +23 -0
- package/src/lex-builder.ts +186 -0
- package/src/lex-def-builder.ts +980 -0
- package/src/lexicon-directory-indexer.ts +52 -0
- package/src/polyfill.ts +7 -0
- package/src/ref-resolver.test.ts +75 -0
- package/src/ref-resolver.ts +368 -0
- package/src/ts-lang.ts +150 -0
- package/src/util.ts +72 -0
- package/tsconfig.build.json +13 -0
- package/tsconfig.json +7 -0
- package/tsconfig.tests.json +9 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"filtered-indexer.d.ts","sourceRoot":"","sources":["../src/filtered-indexer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAA;AACvE,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AAEpC;;;;;GAKG;AACH,qBAAa,eAAgB,YAAW,cAAc,EAAE,eAAe;IAInE,QAAQ,CAAC,OAAO,EAAE,cAAc,GAAG,aAAa,CAAC,eAAe,CAAC;IACjE,QAAQ,CAAC,MAAM,EAAE,MAAM;IAJzB,SAAS,CAAC,QAAQ,CAAC,QAAQ,cAAoB;gBAGpC,OAAO,EAAE,cAAc,GAAG,aAAa,CAAC,eAAe,CAAC,EACxD,MAAM,EAAE,MAAM;IAGnB,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC;IAKxC,CAAC,MAAM,CAAC,aAAa,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAkCvB,CAAC,MAAM,CAAC,YAAY,CAAC,IAAI,OAAO,CAAC,IAAI,CAAC;CAG7C"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.FilteredIndexer = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* A lexicon indexer that filters documents based on a provided filter.
|
|
6
|
+
*
|
|
7
|
+
* If a document was filtered out but later requested via `get()`, the filter
|
|
8
|
+
* will be bypassed for that document.
|
|
9
|
+
*/
|
|
10
|
+
class FilteredIndexer {
|
|
11
|
+
indexer;
|
|
12
|
+
filter;
|
|
13
|
+
returned = new Set();
|
|
14
|
+
constructor(indexer, filter) {
|
|
15
|
+
this.indexer = indexer;
|
|
16
|
+
this.filter = filter;
|
|
17
|
+
}
|
|
18
|
+
async get(id) {
|
|
19
|
+
this.returned.add(id);
|
|
20
|
+
return this.indexer.get(id);
|
|
21
|
+
}
|
|
22
|
+
async *[Symbol.asyncIterator]() {
|
|
23
|
+
const returned = new Set();
|
|
24
|
+
for await (const doc of this.indexer) {
|
|
25
|
+
if (returned.has(doc.id)) {
|
|
26
|
+
// Should never happen
|
|
27
|
+
throw new Error(`Duplicate lexicon document id: ${doc.id}`);
|
|
28
|
+
}
|
|
29
|
+
if (this.returned.has(doc.id) || this.filter(doc.id)) {
|
|
30
|
+
this.returned.add(doc.id);
|
|
31
|
+
returned.add(doc.id);
|
|
32
|
+
yield doc;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
// When we yield control back to the caller, there may be requests (.get())
|
|
36
|
+
// for documents that were initially ignored (filtered out). We won't be
|
|
37
|
+
// done iterating until every document that may have been requested when the
|
|
38
|
+
// control was yielded to the caller has been returned.
|
|
39
|
+
let returnedAny;
|
|
40
|
+
do {
|
|
41
|
+
returnedAny = false;
|
|
42
|
+
for (const id of this.returned) {
|
|
43
|
+
if (!returned.has(id)) {
|
|
44
|
+
yield await this.indexer.get(id);
|
|
45
|
+
returned.add(id);
|
|
46
|
+
returnedAny = true;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
} while (returnedAny);
|
|
50
|
+
}
|
|
51
|
+
async [Symbol.asyncDispose]() {
|
|
52
|
+
await this.indexer[Symbol.asyncDispose]?.();
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
exports.FilteredIndexer = FilteredIndexer;
|
|
56
|
+
//# sourceMappingURL=filtered-indexer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"filtered-indexer.js","sourceRoot":"","sources":["../src/filtered-indexer.ts"],"names":[],"mappings":";;;AAGA;;;;;GAKG;AACH,MAAa,eAAe;IAIf;IACA;IAJQ,QAAQ,GAAG,IAAI,GAAG,EAAU,CAAA;IAE/C,YACW,OAAwD,EACxD,MAAc;QADd,YAAO,GAAP,OAAO,CAAiD;QACxD,WAAM,GAAN,MAAM,CAAQ;IACtB,CAAC;IAEJ,KAAK,CAAC,GAAG,CAAC,EAAU;QAClB,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;QACrB,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;IAC7B,CAAC;IAED,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,aAAa,CAAC;QAC3B,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAU,CAAA;QAElC,IAAI,KAAK,EAAE,MAAM,GAAG,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YACrC,IAAI,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC;gBACzB,sBAAsB;gBACtB,MAAM,IAAI,KAAK,CAAC,kCAAkC,GAAG,CAAC,EAAE,EAAE,CAAC,CAAA;YAC7D,CAAC;YAED,IAAI,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC;gBACrD,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;gBACzB,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;gBACpB,MAAM,GAAG,CAAA;YACX,CAAC;QACH,CAAC;QAED,2EAA2E;QAC3E,wEAAwE;QACxE,4EAA4E;QAC5E,uDAAuD;QAEvD,IAAI,WAAoB,CAAA;QACxB,GAAG,CAAC;YACF,WAAW,GAAG,KAAK,CAAA;YACnB,KAAK,MAAM,EAAE,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;gBAC/B,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC;oBACtB,MAAM,MAAM,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;oBAChC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;oBAChB,WAAW,GAAG,IAAI,CAAA;gBACpB,CAAC;YACH,CAAC;QACH,CAAC,QAAQ,WAAW,EAAC;IACvB,CAAC;IAED,KAAK,CAAC,CAAC,MAAM,CAAC,YAAY,CAAC;QACzB,MAAM,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,YAAY,CAAC,EAAE,EAAE,CAAA;IAC7C,CAAC;CACF;AAlDD,0CAkDC","sourcesContent":["import { LexiconDocument, LexiconIndexer } from '@atproto/lex-document'\nimport { Filter } from './filter.js'\n\n/**\n * A lexicon indexer that filters documents based on a provided filter.\n *\n * If a document was filtered out but later requested via `get()`, the filter\n * will be bypassed for that document.\n */\nexport class FilteredIndexer implements LexiconIndexer, AsyncDisposable {\n protected readonly returned = new Set<string>()\n\n constructor(\n readonly indexer: LexiconIndexer & AsyncIterable<LexiconDocument>,\n readonly filter: Filter,\n ) {}\n\n async get(id: string): Promise<LexiconDocument> {\n this.returned.add(id)\n return this.indexer.get(id)\n }\n\n async *[Symbol.asyncIterator]() {\n const returned = new Set<string>()\n\n for await (const doc of this.indexer) {\n if (returned.has(doc.id)) {\n // Should never happen\n throw new Error(`Duplicate lexicon document id: ${doc.id}`)\n }\n\n if (this.returned.has(doc.id) || this.filter(doc.id)) {\n this.returned.add(doc.id)\n returned.add(doc.id)\n yield doc\n }\n }\n\n // When we yield control back to the caller, there may be requests (.get())\n // for documents that were initially ignored (filtered out). We won't be\n // done iterating until every document that may have been requested when the\n // control was yielded to the caller has been returned.\n\n let returnedAny: boolean\n do {\n returnedAny = false\n for (const id of this.returned) {\n if (!returned.has(id)) {\n yield await this.indexer.get(id)\n returned.add(id)\n returnedAny = true\n }\n }\n } while (returnedAny)\n }\n\n async [Symbol.asyncDispose](): Promise<void> {\n await this.indexer[Symbol.asyncDispose]?.()\n }\n}\n"]}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { Options as PrettierOptions } from 'prettier';
|
|
2
|
+
export type FormatterOptions = {
|
|
3
|
+
/** @default false */
|
|
4
|
+
pretty?: boolean | PrettierOptions;
|
|
5
|
+
banner?: string;
|
|
6
|
+
};
|
|
7
|
+
export declare class Formatter {
|
|
8
|
+
readonly banner: string;
|
|
9
|
+
readonly prettierOptions: PrettierOptions | null;
|
|
10
|
+
constructor(options?: FormatterOptions);
|
|
11
|
+
format(code: string): Promise<string>;
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=formatter.d.ts.map
|
|
@@ -0,0 +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,qBAAqB;IACrB,MAAM,CAAC,EAAE,OAAO,GAAG,eAAe,CAAA;IAClC,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB,CAAA;AAED,qBAAa,SAAS;IACpB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,eAAe,EAAE,eAAe,GAAG,IAAI,CAAA;gBAEpC,OAAO,GAAE,gBAAqB;IASpC,MAAM,CAAC,IAAI,EAAE,MAAM;CAQ1B"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Formatter = void 0;
|
|
4
|
+
const prettier_1 = require("prettier");
|
|
5
|
+
const DEFAULT_FORMAT_OPTIONS = {
|
|
6
|
+
parser: 'typescript',
|
|
7
|
+
tabWidth: 2,
|
|
8
|
+
semi: false,
|
|
9
|
+
singleQuote: true,
|
|
10
|
+
trailingComma: 'all',
|
|
11
|
+
};
|
|
12
|
+
const DEFAULT_BANNER = `/*
|
|
13
|
+
* THIS FILE WAS GENERATED BY "@atproto/lex". DO NOT EDIT.
|
|
14
|
+
*/`;
|
|
15
|
+
class Formatter {
|
|
16
|
+
banner;
|
|
17
|
+
prettierOptions;
|
|
18
|
+
constructor(options = {}) {
|
|
19
|
+
this.banner = options?.banner ?? DEFAULT_BANNER;
|
|
20
|
+
this.prettierOptions =
|
|
21
|
+
options?.pretty === true
|
|
22
|
+
? DEFAULT_FORMAT_OPTIONS
|
|
23
|
+
: options?.pretty || null;
|
|
24
|
+
}
|
|
25
|
+
async format(code) {
|
|
26
|
+
const bannerPadding = this.banner && !this.banner.endsWith('\n') ? '\n\n' : '';
|
|
27
|
+
const codePretty = this.prettierOptions
|
|
28
|
+
? await (0, prettier_1.format)(code, this.prettierOptions)
|
|
29
|
+
: code;
|
|
30
|
+
return `${this.banner}${bannerPadding}${codePretty}`;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
exports.Formatter = Formatter;
|
|
34
|
+
//# sourceMappingURL=formatter.js.map
|
|
@@ -0,0 +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;AAQJ,MAAa,SAAS;IACX,MAAM,CAAQ;IACd,eAAe,CAAwB;IAEhD,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,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;AArBD,8BAqBC","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\nexport type FormatterOptions = {\n /** @default false */\n pretty?: boolean | PrettierOptions\n banner?: string\n}\n\nexport class Formatter {\n readonly banner: string\n readonly prettierOptions: PrettierOptions | null\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 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
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import './polyfill.js';
|
|
2
|
+
import { LexBuilderLoadOptions, LexBuilderOptions, LexBuilderSaveOptions } from './lex-builder.js';
|
|
3
|
+
export * from './lex-builder.js';
|
|
4
|
+
export * from './lex-def-builder.js';
|
|
5
|
+
export * from './lexicon-directory-indexer.js';
|
|
6
|
+
export type TsProjectBuildOptions = LexBuilderOptions & LexBuilderLoadOptions & LexBuilderSaveOptions;
|
|
7
|
+
export declare function build(options: TsProjectBuildOptions): Promise<void>;
|
|
8
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +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,sBAAsB,CAAA;AACpC,cAAc,gCAAgC,CAAA;AAE9C,MAAM,MAAM,qBAAqB,GAAG,iBAAiB,GACnD,qBAAqB,GACrB,qBAAqB,CAAA;AAEvB,wBAAsB,KAAK,CAAC,OAAO,EAAE,qBAAqB,iBAIzD"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.build = build;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
// Must be first
|
|
6
|
+
require("./polyfill.js");
|
|
7
|
+
const lex_builder_js_1 = require("./lex-builder.js");
|
|
8
|
+
tslib_1.__exportStar(require("./lex-builder.js"), exports);
|
|
9
|
+
tslib_1.__exportStar(require("./lex-def-builder.js"), exports);
|
|
10
|
+
tslib_1.__exportStar(require("./lexicon-directory-indexer.js"), exports);
|
|
11
|
+
async function build(options) {
|
|
12
|
+
const builder = new lex_builder_js_1.LexBuilder(options);
|
|
13
|
+
await builder.load(options);
|
|
14
|
+
await builder.save(options);
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;AAkBA,sBAIC;;AAtBD,gBAAgB;AAChB,yBAAsB;AAEtB,qDAKyB;AAEzB,2DAAgC;AAChC,+DAAoC;AACpC,yEAA8C;AAMvC,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\nexport type TsProjectBuildOptions = LexBuilderOptions &\n LexBuilderLoadOptions &\n LexBuilderSaveOptions\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"]}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { BuildFilterOptions } from './filter.js';
|
|
2
|
+
import { FormatterOptions } from './formatter.js';
|
|
3
|
+
import { LexDefBuilderOptions } from './lex-def-builder.js';
|
|
4
|
+
import { LexiconDirectoryIndexerOptions } from './lexicon-directory-indexer.js';
|
|
5
|
+
export type LexBuilderOptions = LexDefBuilderOptions & {
|
|
6
|
+
/**
|
|
7
|
+
* Whether to generate an index file at the root exporting all top-level
|
|
8
|
+
* namespaces.
|
|
9
|
+
*
|
|
10
|
+
* @note This could theoretically cause name conflicts if a
|
|
11
|
+
* @default false
|
|
12
|
+
*/
|
|
13
|
+
indexFile?: boolean;
|
|
14
|
+
importExt?: string;
|
|
15
|
+
fileExt?: string;
|
|
16
|
+
};
|
|
17
|
+
export type LexBuilderLoadOptions = LexiconDirectoryIndexerOptions & BuildFilterOptions;
|
|
18
|
+
export type LexBuilderSaveOptions = FormatterOptions & {
|
|
19
|
+
out: string;
|
|
20
|
+
clear?: boolean;
|
|
21
|
+
override?: boolean;
|
|
22
|
+
};
|
|
23
|
+
export declare class LexBuilder {
|
|
24
|
+
#private;
|
|
25
|
+
private readonly options;
|
|
26
|
+
constructor(options?: LexBuilderOptions);
|
|
27
|
+
get fileExt(): string;
|
|
28
|
+
get importExt(): string;
|
|
29
|
+
load(options: LexBuilderLoadOptions): Promise<void>;
|
|
30
|
+
save(options: LexBuilderSaveOptions): Promise<void>;
|
|
31
|
+
private createFile;
|
|
32
|
+
private getFile;
|
|
33
|
+
private createExportTree;
|
|
34
|
+
private createDefsFile;
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=lex-builder.d.ts.map
|
|
@@ -0,0 +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"}
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.LexBuilder = void 0;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const node_assert_1 = tslib_1.__importDefault(require("node:assert"));
|
|
6
|
+
const promises_1 = require("node:fs/promises");
|
|
7
|
+
const node_path_1 = require("node:path");
|
|
8
|
+
const ts_morph_1 = require("ts-morph");
|
|
9
|
+
const filter_js_1 = require("./filter.js");
|
|
10
|
+
const filtered_indexer_js_1 = require("./filtered-indexer.js");
|
|
11
|
+
const formatter_js_1 = require("./formatter.js");
|
|
12
|
+
const lex_def_builder_js_1 = require("./lex-def-builder.js");
|
|
13
|
+
const lexicon_directory_indexer_js_1 = require("./lexicon-directory-indexer.js");
|
|
14
|
+
const ts_lang_js_1 = require("./ts-lang.js");
|
|
15
|
+
class LexBuilder {
|
|
16
|
+
options;
|
|
17
|
+
#imported = new Set();
|
|
18
|
+
#project = new ts_morph_1.Project({
|
|
19
|
+
useInMemoryFileSystem: true,
|
|
20
|
+
manipulationSettings: { indentationText: ts_morph_1.IndentationText.TwoSpaces },
|
|
21
|
+
});
|
|
22
|
+
constructor(options = {}) {
|
|
23
|
+
this.options = options;
|
|
24
|
+
}
|
|
25
|
+
get fileExt() {
|
|
26
|
+
return this.options.fileExt ?? '.ts';
|
|
27
|
+
}
|
|
28
|
+
get importExt() {
|
|
29
|
+
return this.options.importExt ?? '.js';
|
|
30
|
+
}
|
|
31
|
+
async load(options) {
|
|
32
|
+
const env_1 = { stack: [], error: void 0, hasError: false };
|
|
33
|
+
try {
|
|
34
|
+
const indexer = tslib_1.__addDisposableResource(env_1, new filtered_indexer_js_1.FilteredIndexer(new lexicon_directory_indexer_js_1.LexiconDirectoryIndexer(options), (0, filter_js_1.buildFilter)(options)), true);
|
|
35
|
+
for await (const doc of indexer) {
|
|
36
|
+
if (!this.#imported.has(doc.id)) {
|
|
37
|
+
this.#imported.add(doc.id);
|
|
38
|
+
}
|
|
39
|
+
else {
|
|
40
|
+
throw new Error(`Duplicate lexicon document id: ${doc.id}`);
|
|
41
|
+
}
|
|
42
|
+
await this.createDefsFile(doc, indexer);
|
|
43
|
+
await this.createExportTree(doc);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
catch (e_1) {
|
|
47
|
+
env_1.error = e_1;
|
|
48
|
+
env_1.hasError = true;
|
|
49
|
+
}
|
|
50
|
+
finally {
|
|
51
|
+
const result_1 = tslib_1.__disposeResources(env_1);
|
|
52
|
+
if (result_1)
|
|
53
|
+
await result_1;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
async save(options) {
|
|
57
|
+
const files = this.#project.getSourceFiles();
|
|
58
|
+
const destination = (0, node_path_1.resolve)(options.out);
|
|
59
|
+
if (options.clear) {
|
|
60
|
+
await (0, promises_1.rm)(destination, { recursive: true, force: true });
|
|
61
|
+
}
|
|
62
|
+
else if (!options.override) {
|
|
63
|
+
await Promise.all(files.map(async (f) => assertNotFileExists((0, node_path_1.join)(destination, f.getFilePath()))));
|
|
64
|
+
}
|
|
65
|
+
const formatter = new formatter_js_1.Formatter(options);
|
|
66
|
+
await Promise.all(Array.from(files, async (file) => {
|
|
67
|
+
const filePath = (0, node_path_1.join)(destination, file.getFilePath());
|
|
68
|
+
const content = await formatter.format(file.getFullText());
|
|
69
|
+
await (0, promises_1.mkdir)((0, node_path_1.join)(filePath, '..'), { recursive: true });
|
|
70
|
+
await (0, promises_1.rm)(filePath, { recursive: true, force: true });
|
|
71
|
+
await (0, promises_1.writeFile)(filePath, content, 'utf8');
|
|
72
|
+
}));
|
|
73
|
+
}
|
|
74
|
+
createFile(path) {
|
|
75
|
+
return this.#project.createSourceFile(path);
|
|
76
|
+
}
|
|
77
|
+
getFile(path) {
|
|
78
|
+
return this.#project.getSourceFile(path) || this.createFile(path);
|
|
79
|
+
}
|
|
80
|
+
async createExportTree(doc) {
|
|
81
|
+
const namespaces = doc.id.split('.');
|
|
82
|
+
if (this.options.indexFile) {
|
|
83
|
+
const indexFile = this.getFile(`/index${this.fileExt}`);
|
|
84
|
+
const tldNs = namespaces[0];
|
|
85
|
+
(0, node_assert_1.default)(tldNs !== 'index', 'The "indexFile" options cannot be used with namespaces using a ".index" tld.');
|
|
86
|
+
const tldNsSpecifier = `./${tldNs}${this.importExt}`;
|
|
87
|
+
if (!indexFile.getExportDeclaration(tldNsSpecifier)) {
|
|
88
|
+
indexFile.addExportDeclaration({
|
|
89
|
+
moduleSpecifier: tldNsSpecifier,
|
|
90
|
+
namespaceExport: (0, ts_lang_js_1.asNamespaceExport)(tldNs),
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
// First create the parent namespaces
|
|
95
|
+
for (let i = 0; i < namespaces.length - 1; i++) {
|
|
96
|
+
const currentNs = namespaces[i];
|
|
97
|
+
const childNs = namespaces[i + 1];
|
|
98
|
+
const path = (0, node_path_1.join)('/', ...namespaces.slice(0, i + 1));
|
|
99
|
+
const file = this.getFile(`${path}${this.fileExt}`);
|
|
100
|
+
const childModuleSpecifier = `./${currentNs}/${childNs}${this.importExt}`;
|
|
101
|
+
const dec = file.getExportDeclaration(childModuleSpecifier);
|
|
102
|
+
if (!dec) {
|
|
103
|
+
file.addExportDeclaration({
|
|
104
|
+
moduleSpecifier: childModuleSpecifier,
|
|
105
|
+
namespaceExport: (0, ts_lang_js_1.asNamespaceExport)(childNs),
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
// The child file exports the schemas (as *)
|
|
110
|
+
const path = (0, node_path_1.join)('/', ...namespaces);
|
|
111
|
+
const file = this.getFile(`${path}${this.fileExt}`);
|
|
112
|
+
file.addExportDeclaration({
|
|
113
|
+
moduleSpecifier: `./${namespaces.at(-1)}.defs${this.importExt}`,
|
|
114
|
+
});
|
|
115
|
+
// @NOTE Individual exports exports from the defs file might conflict with
|
|
116
|
+
// child namespaces. For this reason, we also add a namespace export for the
|
|
117
|
+
// defs (export * as $defs from './xyz.defs'). This is an escape hatch
|
|
118
|
+
// allowing to still access the definitions if a hash get shadowed by a
|
|
119
|
+
// child namespace.
|
|
120
|
+
file.addExportDeclaration({
|
|
121
|
+
moduleSpecifier: `./${namespaces.at(-1)}.defs${this.importExt}`,
|
|
122
|
+
namespaceExport: '$defs',
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
async createDefsFile(doc, indexer) {
|
|
126
|
+
const path = (0, node_path_1.join)('/', ...doc.id.split('.'));
|
|
127
|
+
const file = this.createFile(`${path}.defs${this.fileExt}`);
|
|
128
|
+
const fileBuilder = new lex_def_builder_js_1.LexDefBuilder(this.options, file, doc, indexer);
|
|
129
|
+
await fileBuilder.build();
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
exports.LexBuilder = LexBuilder;
|
|
133
|
+
async function assertNotFileExists(file) {
|
|
134
|
+
try {
|
|
135
|
+
await (0, promises_1.stat)(file);
|
|
136
|
+
throw new Error(`File already exists: ${file}`);
|
|
137
|
+
}
|
|
138
|
+
catch (err) {
|
|
139
|
+
if (err instanceof Error && 'code' in err && err.code === 'ENOENT')
|
|
140
|
+
return;
|
|
141
|
+
throw err;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
//# sourceMappingURL=lex-builder.js.map
|
|
@@ -0,0 +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"]}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { SourceFile } from 'ts-morph';
|
|
2
|
+
import { LexiconDocument, LexiconIndexer, LexiconProcedure, LexiconQuery, LexiconSubscription } from '@atproto/lex-document';
|
|
3
|
+
import { RefResolverOptions, ResolvedRef } from './ref-resolver.js';
|
|
4
|
+
export type LexDefBuilderOptions = RefResolverOptions & {
|
|
5
|
+
lib?: string;
|
|
6
|
+
allowLegacyBlobs?: boolean;
|
|
7
|
+
pureAnnotations?: boolean;
|
|
8
|
+
};
|
|
9
|
+
/**
|
|
10
|
+
* Utility class to build a TypeScript source file from a lexicon document.
|
|
11
|
+
*/
|
|
12
|
+
export declare class LexDefBuilder {
|
|
13
|
+
private readonly options;
|
|
14
|
+
private readonly file;
|
|
15
|
+
private readonly doc;
|
|
16
|
+
private readonly refResolver;
|
|
17
|
+
constructor(options: LexDefBuilderOptions, file: SourceFile, doc: LexiconDocument, indexer: LexiconIndexer);
|
|
18
|
+
private pure;
|
|
19
|
+
build(): Promise<void>;
|
|
20
|
+
private addUtils;
|
|
21
|
+
private addDef;
|
|
22
|
+
private addPermissionSet;
|
|
23
|
+
private addProcedure;
|
|
24
|
+
private addQuery;
|
|
25
|
+
private addSubscription;
|
|
26
|
+
addMethodTypeUtils(ref: ResolvedRef, def: LexiconProcedure | LexiconQuery | LexiconSubscription): void;
|
|
27
|
+
private addRecord;
|
|
28
|
+
private addObject;
|
|
29
|
+
private addToken;
|
|
30
|
+
private addArray;
|
|
31
|
+
private addSchema;
|
|
32
|
+
private compilePayload;
|
|
33
|
+
private compileBodySchema;
|
|
34
|
+
private compileParamsSchema;
|
|
35
|
+
private compileErrors;
|
|
36
|
+
private compileObjectSchema;
|
|
37
|
+
private compilePropertiesSchemas;
|
|
38
|
+
private compilePropertiesTypes;
|
|
39
|
+
private compilePropertyEntrySchema;
|
|
40
|
+
private compilePropertyEntryType;
|
|
41
|
+
private compileContainedSchema;
|
|
42
|
+
private compileContainedType;
|
|
43
|
+
private compileArraySchema;
|
|
44
|
+
private compileArrayType;
|
|
45
|
+
private compileUnknownSchema;
|
|
46
|
+
private compileUnknownType;
|
|
47
|
+
private withDefault;
|
|
48
|
+
private compileBooleanSchema;
|
|
49
|
+
private compileBooleanType;
|
|
50
|
+
private compileIntegerSchema;
|
|
51
|
+
private compileIntegerType;
|
|
52
|
+
private compileStringSchema;
|
|
53
|
+
private compileStringType;
|
|
54
|
+
private compileBytesSchema;
|
|
55
|
+
private compileBytesType;
|
|
56
|
+
private compileBlobSchema;
|
|
57
|
+
private compileBlobType;
|
|
58
|
+
private compileCidLinkSchema;
|
|
59
|
+
private compileCidLinkType;
|
|
60
|
+
private compileRefSchema;
|
|
61
|
+
private compileRefType;
|
|
62
|
+
private compileRefUnionSchema;
|
|
63
|
+
private compileRefUnionType;
|
|
64
|
+
private compileConstSchema;
|
|
65
|
+
private compileConstType;
|
|
66
|
+
private compileEnumSchema;
|
|
67
|
+
private compileEnumType;
|
|
68
|
+
}
|
|
69
|
+
//# sourceMappingURL=lex-def-builder.d.ts.map
|
|
@@ -0,0 +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;;GAEG;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"}
|