API

Javascript Post Processors

To specify the post processors in settings, see the codegen configuration section.

Here is an example of how to use the Prettier and Eslint post processors:

from alliance_platform.frontend.util import guess_node_path
from django.conf import settings

PROJECT_DIR = settings.PROJECT_DIR
NODE_PATH = guess_node_path(PROJECT_DIR / ".nvmrc") or "node"
NODE_MODULES_DIR = PROJECT_DIR / "node_modules"

post_processors = [
    PrettierPostProcessor(
        NODE_PATH,
        NODE_MODULES_DIR,
        prettier_config=PROJECT_DIR / "config/prettier.config.js",
    ),
    EslintFixPostProcessor(
        NODE_PATH,
        NODE_MODULES_DIR,
        plugins=["eslint-plugin-simple-import-sort"],
        rules={
            "simple-import-sort/imports": [
                "error",
                {
                    # Keep in sync with config/eslintrc.cjs.
                    "groups": [
                        ["^\\u0000[^.]"],
                        ["^@?\\w"],
                        ["^"],
                        ["^\\."],
                        ["^.+\\.less$"],
                    ],
                },
            ],
        },
    ),
]
class alliance_platform.codegen.post_processors.js.JsPostProcessor(node_path, node_modules_dir)

Base class for post processors that run on JS files.

Parameters:
  • node_path (Path) – Path to node executable

  • node_modules_dir (Path) – Path to the node modules directory

node_path: Path

Path to the node executable

node_modules_dir: Path

Path to the node_modules directory

class alliance_platform.codegen.post_processors.js.PrettierPostProcessor(node_path, node_modules_dir, *, prettier_config=None)

Post processor that runs prettier on typescript, JS and JSON files.

Parameters:
  • node_path (Path) – Path to node executable

  • node_modules_dir (Path) – Path to the node modules directory

  • prettier_config (Path | str | None) – The path to a prettier config file

file_extensions: list[str] = ['.js', '.ts', '.tsx', '.jsx', '.json']

File extensions that this post processor should run on

post_process(paths)

Post process a list of paths.

You can assume any path passed to this method will have already been filtered by the does_apply method.

This method has no return value - all changes should be made in place.

Parameters:

paths (list[Path]) – The paths to post process.

Raises:

NotImplementedError – This method must be implemented by subclasses.

class alliance_platform.codegen.post_processors.js.LegacyEslintFixPostProcessor(node_path, node_modules_dir, *, plugins=None, rules)

Legacy post processor that runs eslint –fix on typescript, JS, TSX and JSX files.

Warning

This post processor works only for Eslint 7 & 8. Due to significant changes introduced in version 9 a separate class is used for newer versions. See EslintFixPostProcessor

Parameters:
  • node_path (Path) – Path to node executable

  • node_modules_dir (Path) – Path to the node modules directory

  • plugins (list[str]) – Any eslint plugins to use

  • rules (dict | None) – Any eslint rules to apply

file_extensions: list[str] = ['.js', '.ts', '.tsx', '.jsx']

File extensions that this post processor should run on

plugins: list[str]

List of eslint plugins to use

rules: dict | None

Any eslint rules to apply

post_process(paths)

Post process a list of paths.

You can assume any path passed to this method will have already been filtered by the does_apply method.

This method has no return value - all changes should be made in place.

Parameters:

paths (list[Path]) – The paths to post process.

Raises:

NotImplementedError – This method must be implemented by subclasses.

class alliance_platform.codegen.post_processors.js.EslintFixPostProcessor(node_path, node_modules_dir, *, plugins=None, rules)

Post processor that runs eslint –fix on typescript, JS, TSX and JSX files.

Requires Eslint 9 or newer.

Note that this intentionally does not use the project eslint config due to speed concerns. A subset of rules should instead be passed to handle the main formatting concerns, e.g. import sorting.

Parameters:
  • node_path (Path) – Path to node executable

  • node_modules_dir (Path) – Path to the node modules directory

  • plugins (list[str]) – Any eslint plugins to use

  • rules (dict | None) – Any eslint rules to apply

file_extensions: list[str] = ['.js', '.ts', '.tsx', '.jsx']

File extensions that this post processor should run on

plugins: list[str]

List of eslint plugins to use

rules: dict | None

Any eslint rules to apply

post_process(paths)

Post process a list of paths.

You can assume any path passed to this method will have already been filtered by the does_apply method.

This method has no return value - all changes should be made in place.

Parameters:

paths (list[Path]) – The paths to post process.

Raises:

NotImplementedError – This method must be implemented by subclasses.

Typescript Codegen

These modules provide support for generating Typescript sourcecode in a declarative way.

For example:

printer = TypescriptPrinter()
printer.print(
    FunctionDeclaration(
        Identifier("renderButton"),
        [Parameter(Identifier("container")), Parameter(Identifier("props"))],
        [VariableDeclaration([VariableDeclarator(Identifier("name"), "Gandalf")], "const")],
        [ExportKeyword(is_default=True), AsyncKeyword()],
    )
)

> export default async function renderButton(container, props) {
>   const name = "Gandalf";
> }

Nodes

class alliance_platform.codegen.typescript.ArrayLiteralExpression(elements)[source]

e.g. [1,2,3]

Usage:

ArrayLiteralExpression(
    [
        1,
        ObjectLiteralExpression([ObjectProperty(Identifier("color"), "#ccc")]),
        True,
        "test",
        9.8,
    ]
)

> [1, {color: "#ccc"}, true, "test", 9.8]
Parameters:

elements (list[Node])

class alliance_platform.codegen.typescript.ArrowFunction(parameters: list[alliance_platform.codegen.typescript.Parameter], body: alliance_platform.codegen.typescript.Node, *, leading_comments: Sequence[ForwardRef('SingleLineComment') | ForwardRef('MultiLineComment')] | None = None, trailing_comments: Sequence[ForwardRef('SingleLineComment') | ForwardRef('MultiLineComment')] | None = None)[source]
Parameters:
body: Node[source]

The body as either a single expression valid for Arrow functions or a Block node

parameters: list[Parameter][source]

Any parameters to the function

class alliance_platform.codegen.typescript.AsExpression(expression, type_annotation, *, leading_comments=None, trailing_comments=None)[source]

Typescript as expression, e.g.

const a = { “example”: true } as const;

Usage:

AsExpression(
    ObjectLiteralExpression([ObjectProperty("example", True)]),
    TypeReference(Identifier("const")),
)

> {"example": true} as const
Parameters:
class alliance_platform.codegen.typescript.AsyncKeyword[source]

Makes it so the function this is attached to is marked as async

Usage:

FunctionDeclaration(
    Identifier("renderButton"),
    [Parameter(Identifier("container")), Parameter(Identifier("props"))],
    [VariableDeclaration([VariableDeclarator(Identifier("name"), "Gandalf")], "const")],
    [ExportKeyword(is_default=True), AsyncKeyword()],
)

> export default async function renderButton(container, props) {
>  const name = "Gandalf";
> }
class alliance_platform.codegen.typescript.Block(statements, *, leading_comments=None, trailing_comments=None)[source]

Useful for ArrowFunction if not returning a single expression

Parameters:
class alliance_platform.codegen.typescript.BooleanLiteral(value, *, leading_comments=None, trailing_comments=None)[source]

A boolean literal

Parameters:
class alliance_platform.codegen.typescript.CallExpression(expression, arguments=None)[source]

Function call eg. identifier(arg1, arg2) or obj[key](arg1, arg2)

Usage:

CallExpression(
    Identifier("renderButton"),
    [Identifier("container"), Identifier("props")],
)

> renderButton(container, props)
Parameters:
  • expression (Node)

  • arguments (list[Node])

class alliance_platform.codegen.typescript.ElementAccessExpression(expression, argument_expression, *, leading_comments=None, trailing_comments=None)[source]

e.g. my_obj[“key”], my_array[5] etc

Usage:

ElementAccessExpression(ElementAccessExpression(Identifier("my_obj"), "my key"), 5)

> my_obj["my key"][5]
Parameters:
class alliance_platform.codegen.typescript.ExportKeyword(is_default=False)[source]

Makes it so the identifier this is attached to is exported

Usage:

VariableDeclaration(
    [VariableDeclarator(Identifier("name"), "Gandalf")], "const", modifiers=[ExportKeyword()]
)

> export const name = "Gandalf"
Parameters:

is_default (bool)

class alliance_platform.codegen.typescript.FunctionDeclaration(name, parameters, statements, modifiers=<factory>, *, leading_comments=None, trailing_comments=None)[source]

Usage:

FunctionDeclaration(
    Identifier("renderButton"),
    [Parameter(Identifier("container")), Parameter(Identifier("props"))],
    [VariableDeclaration([VariableDeclarator(Identifier("name"), "Gandalf")], "const")],
)

> function renderButton(container, props) {
>     const name = "Gandalf";
> }
Parameters:
modifiers: list[Modifier][source]

Can be used to export the function and/or make it async

name: Identifier[source]

The name of the function

parameters: list[Parameter][source]

Any parameters to the function

statements: list[Node][source]

List of body statements

class alliance_platform.codegen.typescript.Identifier(name, type=None, *, leading_comments=None, trailing_comments=None)[source]

An identifier

Will enforce naming is valid (i.e. cannot start with a digit, only contains alphanumeric characters, $ & _)

Optionally can enforce not a reserved word.

Parameters:
validate_reserved_words()[source]

Validate can be used as an identifier

This isn’t done automatically as it doesn’t apply universally

e.g. const a = { test: true } as const;
                     const a = { const: 5 }
                               a.const
                                    ^ these three are all Identifier's and are valid
     const const = { test: true };
            ^ this is an Identifier but is not valid in this context
class alliance_platform.codegen.typescript.ImportDeclaration(source, specifiers=<factory>, import_order_priority=0, *, leading_comments=None, trailing_comments=None)[source]

Represents a javascript import declaration.

A declaration is made up of source which is the module to import from and a numer of specifiers, one of which can be ImportDefaultSpecifier.

import antd, { Button, Alert as DefaultAlert } from 'antd';

would be represented with

ImportDeclaration('antd', [
    ImportDefaultSpecifier("antd"),
    ImportSpecifier("Button"),
    ImportSpecifier("Alert", "DefaultAlert"),
])
Parameters:
add_specifier(specifier)[source]

Add the specifier. If it already exists an error will be thrown.

Parameters:

specifier (ImportDefaultSpecifier | ImportSpecifier)

get_specifier(specifier)[source]

Get matching specifier if it exists, otherwise return None

Parameters:

specifier (ImportDefaultSpecifier | ImportSpecifier)

Return type:

ImportDefaultSpecifier | ImportSpecifier | None

class alliance_platform.codegen.typescript.ImportDefaultSpecifier(local)[source]

Represents the default portion of an import declaration

import Button from 'antd/es/button';

would be represented with

ImportDefaultSpecifier("Button")

Should be used in conjunction with ImportDeclaration

Parameters:

local (Identifier)

class alliance_platform.codegen.typescript.ImportSpecifier(imported, local=None)[source]

Represents the named import portion of an import declaration

import { path as defaultPath } from 'pathlib';

would be represented as

ImportSpecifier("path", "defaultPath")

Should be used in conjunction with ImportDeclaration

Parameters:
imported: Identifier[source]

The name of the import from the module

local: Identifier[source]

The local name of the import - defaults to same as imported

exception alliance_platform.codegen.typescript.InvalidIdentifier[source]
class alliance_platform.codegen.typescript.JsxAttribute(name: alliance_platform.codegen.typescript.Identifier | alliance_platform.codegen.typescript.StringLiteral, initializer: alliance_platform.codegen.typescript.Node, *, leading_comments: Sequence[ForwardRef('SingleLineComment') | ForwardRef('MultiLineComment')] | None = None, trailing_comments: Sequence[ForwardRef('SingleLineComment') | ForwardRef('MultiLineComment')] | None = None)[source]
Parameters:
class alliance_platform.codegen.typescript.JsxElement(tag_name: alliance_platform.codegen.typescript.Identifier | alliance_platform.codegen.typescript.StringLiteral, attributes: Sequence[alliance_platform.codegen.typescript.JsxAttribute | alliance_platform.codegen.typescript.JsxSpreadAttribute], children: list[Union[alliance_platform.codegen.typescript.JsxText, alliance_platform.codegen.typescript.JsxExpression, ForwardRef('JsxElement')]], *, leading_comments: Sequence[ForwardRef('SingleLineComment') | ForwardRef('MultiLineComment')] | None = None, trailing_comments: Sequence[ForwardRef('SingleLineComment') | ForwardRef('MultiLineComment')] | None = None)[source]
Parameters:
class alliance_platform.codegen.typescript.JsxExpression(expression: alliance_platform.codegen.typescript.Node | None, *, leading_comments: Sequence[ForwardRef('SingleLineComment') | ForwardRef('MultiLineComment')] | None = None, trailing_comments: Sequence[ForwardRef('SingleLineComment') | ForwardRef('MultiLineComment')] | None = None)[source]
Parameters:
class alliance_platform.codegen.typescript.JsxSpreadAttribute(expression: alliance_platform.codegen.typescript.Identifier, *, leading_comments: Sequence[ForwardRef('SingleLineComment') | ForwardRef('MultiLineComment')] | None = None, trailing_comments: Sequence[ForwardRef('SingleLineComment') | ForwardRef('MultiLineComment')] | None = None)[source]
Parameters:
class alliance_platform.codegen.typescript.JsxText(value: str, *, leading_comments: Sequence[ForwardRef('SingleLineComment') | ForwardRef('MultiLineComment')] | None = None, trailing_comments: Sequence[ForwardRef('SingleLineComment') | ForwardRef('MultiLineComment')] | None = None)[source]
Parameters:
class alliance_platform.codegen.typescript.Modifier[source]

Base class for modifiers

class alliance_platform.codegen.typescript.MultiLineComment(comment_text: str, *, leading_comments: Sequence[ForwardRef('SingleLineComment') | ForwardRef('MultiLineComment')] | None = None, trailing_comments: Sequence[ForwardRef('SingleLineComment') | ForwardRef('MultiLineComment')] | None = None)[source]
Parameters:
class alliance_platform.codegen.typescript.NewExpression(expression: alliance_platform.codegen.typescript.Node, arguments: Sequence[alliance_platform.codegen.typescript.Node | str | int | float | bool | None | list['NodeLike'] | tuple['NodeLike'] | dict] = <factory>, *, leading_comments: Optional[Sequence[Union[ForwardRef('SingleLineComment'), ForwardRef('MultiLineComment')]]] = None, trailing_comments: Optional[Sequence[Union[ForwardRef('SingleLineComment'), ForwardRef('MultiLineComment')]]] = None)[source]
Parameters:
  • expression (Node)

  • arguments (Sequence[Node | str | int | float | bool | None | list[Node | str | int | float | bool | None | list[NodeLike] | tuple[NodeLike] | dict] | tuple[Node | str | int | float | bool | None | list[NodeLike] | tuple[NodeLike] | dict] | dict])

  • leading_comments (Sequence[SingleLineComment | MultiLineComment] | None)

  • trailing_comments (Sequence[SingleLineComment | MultiLineComment] | None)

class alliance_platform.codegen.typescript.Node(*, leading_comments=None, trailing_comments=None)[source]

Root node everything else should extend from

Parameters:
alliance_platform.codegen.typescript.NodeLike = alliance_platform.codegen.typescript.Node | str | int | float | bool | None | list['NodeLike'] | tuple['NodeLike'] | dict[source]

A type that can be converted to a node

class alliance_platform.codegen.typescript.NullKeyword(*, leading_comments: Sequence[ForwardRef('SingleLineComment') | ForwardRef('MultiLineComment')] | None = None, trailing_comments: Sequence[ForwardRef('SingleLineComment') | ForwardRef('MultiLineComment')] | None = None)[source]
Parameters:
class alliance_platform.codegen.typescript.NumericLiteral(value, *, leading_comments=None, trailing_comments=None)[source]

A numeric literal

Parameters:
class alliance_platform.codegen.typescript.ObjectLiteralExpression(properties, *, leading_comments=None, trailing_comments=None)[source]

e.g. { key1: “One”, key2: “Two” }

Usage:

ObjectLiteralExpression(
    [
        ObjectProperty(
            Identifier("level1"),
            ObjectLiteralExpression(
                [
                    ObjectProperty(Identifier("level2_1"), "One"),
                    ObjectProperty(Identifier("level2_2"), "Two"),
                ]
            ),
        ),
        ObjectProperty("contains space", True),
    ]
)

> {level1: {level2_1: "One", level2_2: "Two"}, "contains space": true}
Parameters:
class alliance_platform.codegen.typescript.ObjectProperty(name, init, *, leading_comments=None, trailing_comments=None)[source]

The property (key / value pair) on an object

Parameters:
class alliance_platform.codegen.typescript.Parameter(name, init=None, *, leading_comments=None, trailing_comments=None)[source]

Parameter to function

Parameters:
class alliance_platform.codegen.typescript.PropertyAccessExpression(expression, name, *, leading_comments=None, trailing_comments=None)[source]

e.g. my_obj.primary

Usage:

PropertyAccessExpression(
    PropertyAccessExpression(
        Identifier("my_obj"),
        Identifier("property"),
    ),
    Identifier("nested"),
)

> my_obj.property.nested
Parameters:
class alliance_platform.codegen.typescript.RawNode(code, *, leading_comments=None, trailing_comments=None)[source]

A raw node that will be output as is

This is useful if you have some code you want to manually craft as a string rather than building up from nodes.

Warning

Be careful using this with any user input, as no escaping will be done.

Parameters:
class alliance_platform.codegen.typescript.ReturnStatement(expression, *, leading_comments=None, trailing_comments=None)[source]

A return statement in a function

Usage:

FunctionDeclaration(
    Identifier("identity"),
    [Parameter(Identifier("a"))],
    [ReturnStatement(Identifier("a"))],
)

> function identity(a) {
>   return a;
> }
Parameters:
class alliance_platform.codegen.typescript.SingleLineComment(comment_text: str, *, leading_comments: Sequence[ForwardRef('SingleLineComment') | ForwardRef('MultiLineComment')] | None = None, trailing_comments: Sequence[ForwardRef('SingleLineComment') | ForwardRef('MultiLineComment')] | None = None)[source]
Parameters:
class alliance_platform.codegen.typescript.SpreadAssignment(expression, *, leading_comments=None, trailing_comments=None)[source]

A spread assignment within an object

Usage:

ObjectLiteralExpression(
    [
        SpreadAssignment(Identifier("base")),
        ObjectProperty(Identifier("key1", "One")),
    ]
)

> { ...base, key1: 'One' }
Parameters:
class alliance_platform.codegen.typescript.StringLiteral(value, *, leading_comments=None, trailing_comments=None)[source]

A string literal

Parameters:
class alliance_platform.codegen.typescript.TemplateExpression(children, *, leading_comments=None, trailing_comments=None)[source]

e.g. ${my_var} ${another_var}

Usage:

TemplateExpression(
    [StringLiteral("Hello my name is "), Identifier("name"), ". What's yours?"]
)

> `Hello my name is ${name}. What's yours?`
Parameters:
class alliance_platform.codegen.typescript.TypeReference(name, *, leading_comments=None, trailing_comments=None)[source]

TODO: Unclear what this should look like yet; need typeArguments as well for generics

Parameters:
exception alliance_platform.codegen.typescript.UnconvertibleValueException(value)[source]
class alliance_platform.codegen.typescript.VariableDeclaration(declarations, kind, modifiers=<factory>, *, leading_comments=None, trailing_comments=None)[source]

Usage:

VariableDeclaration([VariableDeclarator(Identifier("name"), "Gandalf")], "const")

> const name = "Gandalf"
Parameters:
class alliance_platform.codegen.typescript.VariableDeclarator(name, init, *, leading_comments=None, trailing_comments=None)[source]

This is the myVar = 5 part of a declaration

Parameters:
alliance_platform.codegen.typescript.construct_object_property_key(value)[source]

Construct node to use for a property key

If value is numeric will return NumericLiteral

e.g. { 5: "five" }

If value is a string will return Identifier if it’s a valid identifier otherwise StringLiteral

e.g. { test: "test" } vs { "contains space": true }

Otherwise, returns Identifier

Parameters:

value (int | float | str | Identifier | NumericLiteral | StringLiteral)

Return type:

Identifier | NumericLiteral | StringLiteral

alliance_platform.codegen.typescript.convert_literal(value)[source]

Helper to convert a native python value into a node

Parameters:

value (str | int | bool | float | None)

alliance_platform.codegen.typescript.convert_to_node(value, convert_unknown=None)[source]

Helper to convert a native python value into a node

Parameters:
  • value (Node | str | int | float | bool | None | list[Node | str | int | float | bool | None | list[NodeLike] | tuple[NodeLike] | dict] | tuple[Node | str | int | float | bool | None | list[NodeLike] | tuple[NodeLike] | dict] | dict)

  • convert_unknown (Callable[[Node | str | int | float | bool | None | list[Node | str | int | float | bool | None | list[NodeLike] | tuple[NodeLike] | dict] | tuple[Node | str | int | float | bool | None | list[NodeLike] | tuple[NodeLike] | dict] | dict], Node] | None)

Return type:

Node

alliance_platform.codegen.typescript.create_accessor(path)[source]

Helper to create an accessor based on a path

Will use PropertyAccessExpression or ElementAccessExpression based on whether the value is valid Identifier or not.

e.g. passing ["palette", "primary", 500] generates:

ElementAccessExpression(
    PropertyAccessExpression(Identifier('palette'), Identifier('primary')),
    500
)
Parameters:

path (list[str | int | PropertyAccessExpression | Identifier | NumericLiteral])

Printer & Source File Writer

class alliance_platform.codegen.printer.TypescriptPrinter(relative_to_path=None, resolve_import_url=None, jsx_transform=PropertyAccessExpression(leading_comments=None, trailing_comments=None, expression=Identifier(leading_comments=None, trailing_comments=None, name='React', type=None), name=Identifier(leading_comments=None, trailing_comments=None, name='createElement', type=None)), codegen_target='html')[source]

Print out code for the specified node

NOTE: This does not generate nicely formatted code - it’s expected the code will be passed through prettier.

Parameters:
  • relative_to_path (Path)

  • resolve_import_url (Callable[[Path | str], str] | None)

  • jsx_transform (Node | None)

  • codegen_target (Literal['html', 'file'])

apply_modifiers(code, modifiers, node)[source]

Apply some modifiers (e.g. export or async keywords)

This can change e.g. function myFunc() to export async myFunc()

Parameters:
codegen_target: Literal['html', 'file'][source]

The target for codegen. If target is ‘html’ then the code will be escaped for use in HTML, i.e. embedded in a script tag ‘html’ is the default target to avoid accidental XSS vulnerabilities, and will work for file targets as well (just with extra escaping which makes it less readable)

is_within_jsx()[source]

Return True if the current node is within a JSX element. This can be used to determine how to print certain nodes.

For example, a StringLiteral within a JSX element would be <Element>Text</Element>, but outside would be "Text".

jsx_transform: Node | None[source]

How to treat JSX elements. If specified, JSX elements will be transformed to the equivalent of React.createElement calls. The specific function called is identified by jsx_transform, but the relevant import must be added manually.

node_stack: list[Node | str | int | float | bool | None | list[Node | str | int | float | bool | None | list[NodeLike] | tuple[NodeLike] | dict] | tuple[Node | str | int | float | bool | None | list[NodeLike] | tuple[NodeLike] | dict] | dict][source]

Current node stack for printing. As each node is printed it is pushed onto this stack. This can be used to determine the parent node of the current node.

parent_node()[source]

Return the parent node of the current node being processed by print. This only makes sense when called from within print.

This can be used to determine what to do with a node conditionally based on its parent.

print(node)[source]

Recursively print the code for the specified node

Parameters:

node (Node | str | int | float | bool | None | list[Node | str | int | float | bool | None | list[NodeLike] | tuple[NodeLike] | dict] | tuple[Node | str | int | float | bool | None | list[NodeLike] | tuple[NodeLike] | dict] | dict)

Return type:

str

relative_to_path: Path[source]

Path any imports are relative to. Only used if a Path is received - if a string is encountered it used directly

resolve_import_url: Callable[[Path | str], str] | None[source]

Function used to resolve the URL to use for an import. This can be used to do things like resolve it to a dev server URL or to a built file. If not provided import source is used as is.

class alliance_platform.codegen.printer.TypescriptSourceFileWriter(path=None, path_base=None, resolve_import_url=None, jsx_transform=PropertyAccessExpression(leading_comments=None, trailing_comments=None, expression=Identifier(leading_comments=None, trailing_comments=None, name='React', type=None), name=Identifier(leading_comments=None, trailing_comments=None, name='createElement', type=None)))[source]

Source file writer with some helpers

Helps add imports to nodes without needing to manually track duplicates etc. Use resolve_import to get a valid Identifier to use.

Usage:

with TypescriptSourceFileWriter(path) as sfw:
    sfw.add_node(
        FunctionDeclaration(
            Identifier("identity"),
            [Parameter(Identifier("value"))],
            [
                ReturnStatement(
                   Identifier("value")
                )
            ],
        )
    )

# Will write source to ``path``:
#
# function identity(value) {
#     return value;
# }

If no path is supplied then nothing will be written automatically. In that case retrieve the code with get_code:

Usage:

with SourceFileWrite() as sfw:
    sfw.add_node(...)
    print(sfw.get_code())

The resolve_import_url argument can be used to resolve imports to the correct location based on usage:

bundler = get_bundler()
with TypescriptSourceFileWriter(resolve_import_url=bundler.get_url) as sfw:
    # any imports will be resolved by the bundler
Parameters:
  • path (Path | None)

  • path_base (Path | None)

  • resolve_import_url (Callable[[Path | str], str] | None)

  • jsx_transform (Node | None)

add_node(node)[source]

Add a node to be included in the code

Parameters:

node (Node)

get_code()[source]

Returns the printed code

Return type:

str

jsx_transform: Node | None[source]

How to treat JSX elements. If specified, JSX elements will be transformed to the equivalent of React.createElement calls. The specific function called is identified by jsx_transform, but the relevant import must be added manually.

leading_nodes: list[Node][source]

Nodes that will be included at the start of the generated code. This is useful for adding header comments.

nodes: list[Node][source]

The nodes that will be included in the generated code.

path_base: Path | None[source]

Path any imports are relative to. Passed to TypescriptPrinter.

required_imports: list[ImportDeclaration][source]

Any imports that are required. This is based on calls to resolve_import. This imports will be included in the generated code.

resolve_import(source, specifier, import_order_priority=0)[source]

Resolve an import. This will make sure the import is included in the final source (while not conflicting with other imports) and will return the Identifier to use to reference it.

Parameters:
Returns:

The Identifier that can be used to reference the import.

Return type:

Identifier

resolve_import_url: Callable[[Path | str], str] | None[source]

Function used to resolve the URL to use for an import. This can be used to do things like resolve it to a dev server URL or to a built file.