summaryrefslogtreecommitdiff
path: root/tools/ts_library_builder/README.md
diff options
context:
space:
mode:
Diffstat (limited to 'tools/ts_library_builder/README.md')
-rw-r--r--tools/ts_library_builder/README.md95
1 files changed, 95 insertions, 0 deletions
diff --git a/tools/ts_library_builder/README.md b/tools/ts_library_builder/README.md
new file mode 100644
index 000000000..de1305dca
--- /dev/null
+++ b/tools/ts_library_builder/README.md
@@ -0,0 +1,95 @@
+# ts_library_builder
+
+This tool allows us to produce a single TypeScript declaration file that
+describes the complete Deno runtime, including global variables and the built-in
+`deno` module. The output of this tool, `lib.deno_runtime.d.ts`, serves several
+purposes:
+
+1. It is passed to the TypeScript compiler `js/compiler.ts`, so that TypeScript
+ knows what types to expect and can validate code against the runtime
+ environment.
+2. It is outputted to stdout by `deno --types`, so that users can easily have
+ access to the complete declaration file. Editors can use this in the future
+ to perform type checking.
+3. Because JSDocs are maintained, this serves as a simple documentation page for
+ Deno. We will use this file to generate HTML docs in the future.
+
+The tool depends upon a couple libraries:
+
+- [`ts-node`](https://www.npmjs.com/package/ts-node) to provide just in time
+ transpiling of TypeScript for the tool itself.
+- [`ts-simple-ast`](https://www.npmjs.com/package/ts-simple-ast) which provides
+ a more rational and functional interface to the TypeScript AST to make
+ manipulations easier.
+- [`prettier`](https://www.npmjs.com/package/prettier) and
+ [`@types/prettier`](https://www.npmjs.com/package/@types/prettier) to format
+ the output.
+
+## Design
+
+Ideally we wouldn't have to build this tool at all, and could simply use `tsc`
+to output this declaration file. While, `--emitDeclarationsOnly`, `--outFile`
+and `--module AMD` generates a single declaration file, it isn't clean. It was
+never designed for a library generation, where what is available in a runtime
+environment significantly differs from the code that creates that environment's
+structure.
+
+Therefore this tool injects some of the knowledge of what occurs in the Deno
+runtime environment as well as ensures that the output file is more clean and
+logical for an end user. In the deno runtime, code runs in a global scope that
+is defined in `js/global.ts`. This contains global scope items that one
+reasonably expects in a JavaScript runtime, like `console`. It also defines the
+global scope on a self-reflective `window` variable. There is currently only one
+module of Deno specific APIs which is available to the user. This is defined in
+`js/deno.ts`.
+
+This tool takes advantage of an experimental feature of TypeScript that items
+that are not really intended to be part of the public API are marked with a
+comment pragma of `@internal` and then are not emitted when generating type
+definitions. In addition TypeScript will _tree-shake_ any dependencies tied to
+that "hidden" API and elide them as well. This really helps keep the public API
+clean and as minimal as needed.
+
+In order to create the default type library, the process at a high-level looks
+like this:
+
+- We read in all of the runtime environment definition code into TypeScript AST
+ parser "project".
+- We emit the TypeScript type definitions only into another AST parser
+ "project".
+- We process the `deno` namespace/module, by "flattening" the type definition
+ file.
+ - We determine the exported symbols for `js/deno.ts`.
+ - We create a custom extraction of the `gen/msg_generated.ts` which is
+ generated during the build process and contains the type information related
+ to flatbuffer structures that communicate between the privileged part of
+ deno and the user land. Currently, the tool doesn't do full complex
+ dependency analysis to be able to determine what is required out of this
+ file, so we explicitly extract the type information we need.
+ - We recurse over all imports/exports of the modules, only exporting those
+ symbols which are finally exported by `js/deno.ts`.
+ - We replace the import/export with the type information from the source file.
+ - This process assumes that all the modules that feed `js/deno.ts` will have a
+ public type API that does not have name conflicts.
+- We process the `js/globals.ts` file to generate the global namespace.
+ - Currently we create a `"globals"` module which will contain the type
+ definitions.
+ - We create a `Window` interface and a `global` scope augmentation namespace.
+ - We iterate over augmentations to the `window` variable declared in the file,
+ extract the type information and apply it to both a global variable
+ declaration and a property on the `Window` interface.
+- We take each namespace import to `js/globals.ts`, we resolve the emitted
+ declaration `.d.ts` file and create it as its own namespace withing the
+ `"globals"` module. It is unsafe to just flatten these, because there is a
+ high risk of collisions, but also, it makes authoring the types easier within
+ the generated interface and variable declarations.
+- We then validate the resulting definition file and write it out to the
+ appropriate build path.
+
+## TODO
+
+- The tool does not _tree-shake_ when flattening imports. This means there are
+ extraneous types that get included that are not really needed and it means
+ that `gen/msg_generated.ts` has to be explicitly carved down.
+- Complete the tests... we have some coverage, but not a lot of what is in
+ `ast_util_test` which is being tested implicitly.