codedegen - v2.0.0

codedegen 🗡 build

Fast and simple JS/TS code generator.

npm install --save-prod codedegen

Overview

🔎 API documentation is available here.

The code is represented via arrays nested at arbitrary depth:

import { assembleJs, Code } from 'codedegen';

const code: Code = ['console.log(', ['"Hello"'], ')'];

assembleJs(code);
// ⮕ 'console.log("Hello")'

You can use primitives as values:

const code = [1, '+', 2];

assembleJs(code);
// ⮕ '1+2'

Symbols represent variables:

const varA = Symbol();
const varB = Symbol();

const code = [
'if(', varA, '!==0){',
'return ', varA, '*', varB,
'}'
];

assembleJs(code);
// ⮕ 'if(a!==0){return a*b}'

Naming variables

Create a named variable:

import { assembleJs, createVar, Code } from 'codedegen';

const varFoo = createVar('foo');

assembleJs([varFoo, '!==0']);
// ⮕ 'foo!==0'

If there are multiple variables with the same name, they would still have different names in the generated code:

const varFoo1 = createVar('foo');
const varFoo2 = createVar('foo');

assembleJs([varFoo1, '!==', varFoo2]);
// ⮕ 'foo!==foo2'

Variable renamer

You can pass VarRenamer callback to assembleJs to have even more control on how variables are named:

import { assembleJs, createVarRenamer } from 'codedegen';

const varA = Symbol();
const varB = Symbol();

const varRenamer = createVarRenamer([[varA, 'X']]);

assembleJs([varA, '===', varB], varRenamer);
// ⮕ 'X===a'

VarRenamer instance always return the same name for the same variable:

varRenamer(varA) === varRenamer(varA);
// ⮕ true

You can provide a name encoder to createVarRenamer that converts variable index into a valid JS identifier.

import { assembleJs, createVarRenamer } from 'codedegen';

const varRenamer = createVarRenamer([], index => '_' + index);

assembleJs([Symbol(), '>', Symbol()], varRenamer);
// ⮕ '_0>_1'

Compiling a function

You can compile a function directly from the code template:

import { compileFunction } from 'codedegen';

const arg = Symbol();
const varA = Symbol();
const varB = Symbol();

const fn = compileFunction(
// The list of function arguments
[arg],

// The function body
[
'var ', varA, '=123;',
'return ', varA, '+', arg, '+', varB, '.fooBar',
],

// The optional list of variable bindings
[[varB, { fooBar: 456 }]],
);

fn(789);
// ⮕ '1368'

DSL

To ease the codegen there's a set of DSL functions which you can use anywhere in your templates.

propAccess

Returns a prop accessor code:

propAccess('obj', 'foo');
// ⮕ 'obj.foo'

propAccess('obj', 9);
// ⮕ 'obj[9]'

propAccess('obj', 'foo bar', true);
// ⮕ 'obj?.["foo bar"]'

You can generate a nested property access code like this:

import { assembleJs, propAcccess } from 'codedegen';

const varA = Symbol();
const varB = Symbol();

assembleJs([
varA, '=', propAcccess(propAccess(varB, 'fooBar', true), 10)
]);
// ⮕ 'a=b?.fooBar[10]'

objectKey

Returns the code of an object key:

objectKey('foo bar');
// ⮕ '"foo bar"'

objectKey('fooBar');
// ⮕ 'fooBar'

objectKey('0');
// ⮕ '0'

objectKey('0123');
// ⮕ '"0123"'

For example, to create an object you can:

import { assembleJs, Code, objectKey } from 'codedegen';

assembleJs([
'{',
objectKey('fooBar'), ':123,',
objectKey('Yes Sir!'), ':456,',
'}',
]);
// ⮕ '{fooBar:123,"Yes Sir!":456,}'

comment and docComment

Return a code of a comment block:

import { assembleJs } from 'codedegen';

assembleJs(docComment('Yes Sir,\nI Can Boogie'));

varAssign

Returns a variable assignment code:

const varA = Symbol();
const varB = Symbol();

varAssign(varA, [varB]);
// ⮕ 'a=b;'

varAssign(varA, [propAccess(varB, 'fooBar'), '/2']);
// ⮕ 'a=b.fooBar/2'

varDeclare

Returns a variable declaration code:

const varA = Symbol();

varDeclare(varA);
// ⮕ 'var a;'

varDeclare(varA, [123]);
// ⮕ 'var a=123;'

Generated using TypeDoc