Skip to content

Commit

Permalink
Update to churi v0.15 API
Browse files Browse the repository at this point in the history
  • Loading branch information
surol committed Aug 29, 2023
1 parent 43b4368 commit 323dea4
Show file tree
Hide file tree
Showing 6 changed files with 49 additions and 140 deletions.
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
},
"sideEffects": false,
"peerDependencies": {
"churi": "^0.11.0",
"churi": "^0.15.0-pre.0",
"typescript": "5.0.4 - 5.3.0"
},
"dependencies": {
Expand All @@ -44,7 +44,7 @@
"@types/node": "^18.17.11",
"@typescript-eslint/eslint-plugin": "^6.4.1",
"@typescript-eslint/parser": "^6.4.1",
"churi": "^0.14.0",
"churi": "^0.15.0-pre.0",
"eslint": "^8.48.0",
"eslint-plugin-jest": "^27.2.3",
"gh-pages": "^6.0.0",
Expand Down
35 changes: 30 additions & 5 deletions src/impl/ts/ts-options-literal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -130,15 +130,40 @@ export class TsOptionValue {
);
}

getValue(): string | number | undefined {
getBoolean(): boolean | undefined {
const value = this.getValue();

if (value === undefined || typeof value === 'boolean') {
return value;
}

throw new TsError(
`Value of option ${this.#name} in ${this.#options.target} expected to be a boolean constant`,
{ node: this.#valueNode },
);
}

getValue(): string | number | boolean | null | undefined {
const initializer = this.#initializer;

if (initializer) {
if (ts.isStringLiteralLike(initializer)) {
return initializer.text;
if (ts.isLiteralExpression(initializer)) {
if (ts.isStringLiteralLike(initializer)) {
return initializer.text;
}
if (ts.isNumericLiteral(initializer)) {
return Number(initializer.text);
}
}
if (ts.isNumericLiteral(initializer)) {
return Number(initializer.text);

switch (initializer.kind) {
case ts.SyntaxKind.TrueKeyword:
return true;
case ts.SyntaxKind.FalseKeyword:
return false;
case ts.SyntaxKind.NullKeyword:
return null;
default:
}

const {
Expand Down
4 changes: 2 additions & 2 deletions src/impl/uc-transformer.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { UcDeserializer, UcFormatName } from 'churi';
import { UcDeserializer } from 'churi';
import { EsNameRegistry } from 'esgen';
import { capitalize } from 'httongue';
import path from 'node:path';
Expand Down Expand Up @@ -184,7 +184,7 @@ export class UcTransformer {
modelId,
from: stTfm.sourceFile.fileName,
mode: (options.mode?.getString() as UcDeserializer.Mode | undefined) ?? 'universal',
format: (options.from?.getString() as UcFormatName | undefined) ?? 'charge',
byTokens: options.byTokens?.getBoolean() ?? false,
});

return replacement;
Expand Down
100 changes: 12 additions & 88 deletions src/impl/uct-bundle.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { UcFormatName, UcPresentationName } from 'churi';
import {
EsCode,
EsFunction,
Expand All @@ -18,7 +17,6 @@ export class UctBundle {

readonly #setup: UctSetup;
#distFile: string;
#presentations?: EsCode;
#ucdModels?: EsCode;
#ucsModels?: EsCode;

Expand All @@ -44,44 +42,22 @@ export class UctBundle {
(this.#ucdModels ??= new EsCode()).write(this.#addDeserializer(task));
}

#addDeserializer({ fnId, modelId, from, mode, format }: UctCompileDeserializerFn): EsSnippet {
#addDeserializer({ fnId, modelId, from, mode, byTokens }: UctCompileDeserializerFn): EsSnippet {
const moduleSpec = this.#setup.relativeImport(this.#setup.tsRoot.rootDir!, from);
const model = esImport(moduleSpec, modelId.text);
let lexerOptions: UctLexerOptions | undefined;

if (format !== 'tokens') {
lexerOptions = UCT_FORMAT_LEXERS[format];

this.#addPresentation(format);
this.#addPresentations(lexerOptions?.presentations);
}

return code => {
code
.write(esline`${fnId}: {`)
.indent(code => {
code.write(esline`model: ${model},`).write(`mode: ${esStringLiteral(mode)},`);
if (lexerOptions) {
const { lexer, inset } = lexerOptions;

code.write(esline`lexer: ${lexer},`);
if (inset) {
code.write(esline`inset: ${inset},`);
}
}
})
.indent(
esline`model: ${model},`,
`mode: ${esStringLiteral(mode)},`,
`byTokens: ${byTokens},`,
)
.write('}');
};
}

#addPresentation(presentation: UcPresentationName): void {
(this.#presentations ??= new EsCode()).write(esStringLiteral(presentation) + ',');
}

#addPresentations(presentations: readonly UcPresentationName[] | undefined): void {
presentations?.forEach(presentation => this.#addPresentation(presentation));
}

compileUcSerializer(task: UctCompileSerializerFn): void {
(this.#ucsModels ??= new EsCode()).write(this.#addSerializer(task));
}
Expand All @@ -90,7 +66,12 @@ export class UctBundle {
const moduleSpec = this.#setup.relativeImport(this.#setup.tsRoot.rootDir!, from);
const model = esImport(moduleSpec, modelId.text);

return esline`${fnId}: ${model},`;
return code => {
code
.write(esline`${fnId}: {`)
.indent(esline`model: ${model},`)
.write('},');
};
}

emitBundlerFn(): EsFunction<EsSignature.NoArgs> | undefined {
Expand Down Expand Up @@ -125,7 +106,6 @@ export class UctBundle {
.write(esline`new ${UcdCompiler}({`)
.indent(code => {
code.write(`models: {`).indent(ucdModels).write(`},`);
code.write(this.#presentationsOption());
})
.write('})');
});
Expand Down Expand Up @@ -184,60 +164,4 @@ export class UctBundle {
);
}

#presentationsOption(): EsSnippet {
const presentations = this.#presentations;

if (!presentations) {
return EsCode.none;
}

return code => {
code.write(`presentations: [`).indent(presentations).write(`],`);
};
}

}

const UCT_FORMAT_LEXERS: {
readonly [format in UcFormatName]: UctLexerOptions;
} = {
charge: {
lexer: createLexerOption('UcChargeLexer'),
},
plainText: {
lexer: createLexerOption('UcPlainTextLexer'),
},
uriEncoded: {
lexer: createLexerOption('UcURIEncodedLexer'),
},
uriParams: {
presentations: ['uriParam'],
lexer: createLexerOption('UcURIParamsLexer'),
inset: createLexerOption('UcChargeLexer'),
},
};

interface UctLexerOptions {
presentations?: readonly UcPresentationName[] | undefined;
readonly lexer: EsSnippet;
readonly inset?: EsSnippet | undefined;
}

function createLexerOption(lexer: string, from = 'churi'): EsSnippet {
return code => {
code
.write(esline`({ emit }) => code => {`)
.indent(code => {
const $esImport = esImport('esgen', 'esImport');

code
.write(
esline`const Lexer = ${$esImport}(${esStringLiteral(from)}, ${esStringLiteral(
lexer,
)});`,
)
.write(`code.line('return new ', Lexer, '(', emit, ');');`);
})
.write('}');
};
}
42 changes: 1 addition & 41 deletions src/impl/uct-lib.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -125,53 +125,13 @@ export const readValue = createUcDeserializer(String);
expect(file).toContain('export function readValue(');
expect(file).toContain('new UcChargeLexer(');
});
it('emits deserializer lib with custom lexer', async () => {
transform(
{
'deserializer.ts': `
import { createUcDeserializer } from 'churi';
export const readValue = createUcDeserializer(String, { from: 'uriEncoded' });
`,
},
createUcTransformer,
);

await lib.compile();

const file = await fs.readFile(`${testDir}/test.uc-lib.js`, 'utf-8');

expect(file).toContain('export function readValue(');
expect(file).toContain('new UcURIEncodedLexer(');
expect(file).not.toContain('new UcChargeLexer(');
});
it('emits deserializer lib with custom inset', async () => {
transform(
{
'deserializer.ts': `
import { createUcDeserializer } from 'churi';
export const readValue = createUcDeserializer(String, { from: 'uriParams' });
`,
},
createUcTransformer,
);

await lib.compile();

const file = await fs.readFile(`${testDir}/test.uc-lib.js`, 'utf-8');

expect(file).toContain('export function readValue(');
expect(file).toContain('new UcURIParamsLexer(');
expect(file).toContain('new UcChargeLexer(');
});
it('emits by-tokens deserializer', async () => {
transform(
{
'deserializer.ts': `
import { createUcDeserializer } from 'churi';
export const readValue = createUcDeserializer(String, { from: 'tokens' });
export const readValue = createUcDeserializer(String, { byTokens: true });
`,
},
createUcTransformer,
Expand Down
4 changes: 2 additions & 2 deletions src/impl/uct-tasks.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { UcDeserializer, UcFormatName } from 'churi';
import { UcDeserializer } from 'churi';
import ts from 'typescript';
import { UctBundle } from './uct-bundle.js';

Expand All @@ -14,7 +14,7 @@ export interface UctCompileDeserializerFn {
readonly modelId: ts.Identifier;
readonly from: string;
readonly mode: UcDeserializer.Mode;
readonly format: UcFormatName | 'tokens';
readonly byTokens: boolean;
}

export interface UctCompileSerializerFn {
Expand Down

0 comments on commit 323dea4

Please sign in to comment.