Gathering detailed insights and metrics for jsii-rosetta
Gathering detailed insights and metrics for jsii-rosetta
Gathering detailed insights and metrics for jsii-rosetta
Gathering detailed insights and metrics for jsii-rosetta
npm install jsii-rosetta
Module System
Min. Node Version
Typescript Support
Node Version
NPM Version
21 Stars
872 Commits
12 Forks
13 Watching
8 Branches
85 Contributors
Updated on 28 Nov 2024
TypeScript (95.56%)
Java (1.37%)
Go (1.23%)
C# (1.08%)
Python (0.75%)
JavaScript (0.01%)
Cumulative downloads
Total Downloads
Last day
-4.6%
40,907
Compared to previous day
Last week
9.5%
242,649
Compared to previous week
Last month
10.7%
957,490
Compared to previous month
Last year
51.9%
11,530,800
Compared to previous year
13
29
jsii-rosetta
translates code samples contained in jsii libraries from TypeScript to supported jsii target languages.
This is what enables the AWS Cloud Development Kit to deliver polyglot documentation from a single codebase!
jsii-rosetta
leverages knowledge about jsii language translation conventions in order to produce translations. It only
supports a limited set of TypeScript language features (which can be reliably represented in other languages).
Head over to our documentation website!
The jsii toolchain spreads out on multiple repositories:
jsii
compiler is maintained (except releases
in the 1.x
line)jsii-rosetta
sample code transliteration tool
is maintained (except releases in the 1.x
line)@jsii/spec
, the package that defines the .jsii
assembly specificationjsii-config
, an interactive tool to help configure your jsii packagejsii-pacmak
, the bindings generator for jsii packagesjsii-reflect
, a higher-level way to process .jsii
assemblies1.x
release lines of jsii
and jsii-rosetta
The applicable Maintenance & Support policy can be reviewed in SUPPORT.md.
The current status of jsii-rosetta
releases is:
Release | Status | EOS | Comment |
---|---|---|---|
5.7.x | Current | TBD | |
5.6.x | Maintenance | 2025-07-01 | |
5.5.x | Maintenance | 2025-05-15 | |
5.4.x | Maintenance | 2025-02-28 |
See CONTRIBUTING.
This section describes what to pay attention to when writing examples that will be converted by Rosetta.
The translator can translate both code that completely compiles and typechecks, as well as code that doesn't.
In case of non-compiling samples the translations will be based off of grammatical parsing only. This has the downside that we do not have the type information available to the exact thing in all instances. Specifically struct types will not be able to be inferred from object literals. Have a look at the following piece of code:
1someObject.someMethod('foo', {
2 bar: 3,
3});
In non-TypeScript languages, it is important to know the type of the second
argument to the method here. However, without access to the definition of
someMethod()
, it's impossible for Rosetta to know the type, and hence
it cannot translate the example. It is therefore important to include necessary
imports, variable declarations, etc, to give Rosetta enough information to figure
out what's going on in this code, and the example should read like this:
1import * as myLib from 'some-library'; 2 3declare const someObject: myLib.SomeClass; 4 5someObject.someMethod('foo', { 6 bar: 3, 7});
By default, Rosetta will accept non-compiling examples. If you set
jsiiRosetta.strict
to true
in your package.json
,
the Rosetta command will fail if any example contains an error:
1/// package.json 2{ 3 "jsiiRosetta": { 4 "strict": true 5 } 6}
To avoid having to repeat common setup every time, code samples can use
"fixtures": a source template where the example is inserted. A fixture must
contain the text /// here
and typically looks like this:
1const * as module from '@some/dependency'; 2 3class MyClass { 4 constructor() { 5 const obj = new MyObject(); 6 7 /// here 8 } 9}
The example will be inserted at the location marked as /// here
and will have
access to module
, obj
and this
. Any import
statements found in the
example will automatically be hoisted at the top of the fixture, where they are
guaranteed to be syntactically valid.
The default file loaded as a fixture is called rosetta/default.ts-fixture
in
the package directory (if it exists).
Examples can request an alternative fixture by specifying a fixture
parameter
as part of the code block fence:
1```ts fixture=some-fixture
Or opt out of using the default fixture by specifying nofixture
:
1```ts nofixture
To specify fixtures in an @example
block, use an accompanying @exampleMetadata
tag:
1/** 2 * My cool class 3 * 4 * @exampleMetadata fixture=with-setup 5 * @example 6 * 7 * new MyCoolClass(); 8 */
When compiling examples, Rosetta will make sure your package itself and all of
its dependencies
and peerDependencies
are available in the dependency
closure that your examples will be compiled in.
If there are packages you want to use in an example that should not be part
of your package's dependencies, declare them in jsiiRosetta.exampleDependencies
in your package.json
:
1/// package.json 2{ 3 "jsiiRosetta": { 4 "exampleDependencies": { 5 "@some-other/package": "^1.2.3", 6 "@yet-another/package": "*", 7 } 8 } 9}
You can also set up a directory with correct dependencies yourself, and pass
--directory
when running jsii-rosetta extract
. We recommend using the
automatic closure building mechanism and specifying exampleDependencies
though.
This section describes how Rosetta integrates into your build process.
Rosetta has a number of subcommands. The most important one is jsii-rosetta extract
.
The jsii-rosetta extract
command will take one or more jsii assemblies,
extract the snippets from them, will try to compile them with respect to a given
home directory, and finally store all translations in something called a
"tablet".
A couple of things to note here:
jsii
to
regenerate the assembly, before re-running jsii-rosetta extract
.import
s. Currently, you
are responsible for building a directory with the correct node_modules
directories in there so that a TypeScript compilation step will find all
libraries referenced in the examples. This is especially revelant if your
examples include libraries that depend on the current library: it is not
uncommon to write examples in library A
showing how to use it in combination
with library B
, where B
depends on A
. However, since by definition B
cannot be in the set of dependencies of A
, you must build a directory with
both B
and A
in it somewhere in your filesystem and run Rosetta in that
directory.The extract command will write a file named .jsii.tabl.json
next to every
assembly, containing translations for all samples found in the assembly. You
should include this file in your NPM package when you publish, so that
downstream consumers of the package have access to the translations.
An example invocation of jsii-rosetta extract
looks like this:
1jsii-rosetta extract --directory some/dir $(find . -name .jsii)
Since TypeScript compilation takes a lot of time, much time can be gained by
using the CPUs in your system effectively. jsii-rosetta extract
will run the
compilations in parallel.
jsii-rosetta
will use a number of workers equal to half the number of CPU
cores, up to a maximum of 16 workers. This default maximum can be overridden by
setting the JSII_ROSETTA_MAX_WORKER_COUNT
environment variable.
If you get out of memory errors running too many workers, run a command like this to raise the memory allowed for your workers:
1/sbin/sysctl -w vm.max_map_count=2251954
Rosetta extract will translate all examples found in .jsii
and write the
translations to .jsii.tabl.json
. From compilation to compilation, many of these
examples won't have changed. Since TypeScript compilation is a fairly expensive
process, we would like to avoid doing unnecessary work as much as possible.
To that end, rosetta can reuse translations from a cache, and write new translations into the same cache:
1jsii-rosetta extract \ 2 --directory some/dir \ 3 --cache cache.json \ 4 [--trim-cache] \ 5 $(find . -name .jsii)
The --trim-cache
flag will remove any old translations from the cache that
don't exist anymore in any of the given assemblies. This prevents the cache from
growing endlessly over time (an equivalent jsii-rosetta trim-cache
command is
available if your workflow involves running extract
in multiple distinct
invocations and want to retain the cache between them).
The jsii-rosetta infuse
command increases the coverage of examples for classes
in the assembly.
It finds classes in the assembly that don't have an example associated with them
yet (as specified via the @example
tag in the doc comments), but that are used
in another example found elsewhere—in either a README
or an example of another
class—it will copy the example to all classes involved. This will make sure
your handwritten examples go as far as possible.
Note that in order to do this, infuse
will modify the assemblies it is
given.
rosetta infuse
depends on the analysis perfomed by rosetta extract
, and must
therefore be run after extract
. It can also be run as part of extract
, by
passing the --infuse
flag:
1jsii-rosetta extract \ 2 --directory some/dir \ 3 --infuse \ 4 $(find . -name .jsii)
jsii-pacmak
will read translation from tablets to substitute translated examples
into the generated source bindings. pacmak
will automatically read individual
.jsii.tabl.json
files if present, and can additionally also read from a global
tablet file.
When a translation for a code sample cannot be found, pacmak
can be configured
to do one of the following:
extract
command)Example:
1jsii-pacmak \ 2 [--rosetta-tablet=global.json] \ 3 [--rosetta-unknown-snippets=verbatim|translate|fail]
The diagram below shows how data flows through the jsii tools when used together:
1┌───────────┐ 2│ │ 3│ Source ├───┐ 4│ │ │ ╔══════════╗ ┌────────────┐ ╔═══════════════╗ ┌──────────┐ 5└───────────┘ │ ║ ║ │ │ ║ rosetta ║ │ │ 6 ├───▶║ jsii ║───▶│ assembly │────▶║ extract ║───▶│ tablet │ 7┌───────────┐ │ ║ ║ │ │ ║ ║ │ │ 8│ │ │ ╚══════════╝ └────────────┘ ╚═══════════════╝ └──────────┘ 9│ README │───┘ │ │ 10│ │ │ │ 11└───────────┘ │ ╔═══════════════╗ │ 12 │ ║ rosetta ║ │ 13 └──────────▶║ infuse ║◀─────────┘ 14 ║ ║ 15 ╚═══════════════╝ 16 │ 17 ┌───────────────────┴───────────────────┐ 18 │ │ 19 ▼ ▼ 20 ┌────────────┐ ┌──────────┐ 21 │ │ │ │ 22 │ assembly' │ │ tablet' │ 23 │ │ │ │ 24 └────────────┘ └──────────┘ 25 │ │ 26 │ │ 27 │ ▼ ┌─────────────┐ 28 │ ╔═══════════════╗ ┌┴────────────┐│ 29 │ ║ ║ │ ││ 30 └──────────────────────────────▶║ pacmak ║────▶│ packages ││ 31 ║ ║ │ ├┘ 32 ╚═══════════════╝ └─────────────┘ 33 (potentially 34 live-translates)
In order to make examples compile, boilerplate code may need to be added that detracts from the example at hand (such as variable declarations and imports).
This package supports hiding parts of the original source after translation.
To mark special locations in the source tree, we can use one of three mechanisms:
void
expression statement to mark statement locations in the AST.comma
operator combined with a void
expression to mark expression locations in the AST./// !hide
, /// !show
) to mark locations that span AST nodes. This is less reliable
(because the source location of translated syntax sometimes will have to be estimated) but the only option if you want
to mark non-contiguous nodes (such as hide part of a class declaration but show statements inside the constructor).The void
expression keyword and or the comma
operator feature are little-used JavaScript features that are reliably
parsed by TypeScript and do not affect the semantics of the application in which they appear (so the program executes
the same with or without them).
A handy mnemonic for this feature is that you can use it to "send your code into the void".
Statement hiding looks like this:
1before(); // will be shown 2 3void 0; // start hiding (the argument to 'void' doesn't matter) 4middle(); // will not be shown 5void 'show'; // stop hiding 6 7after(); // will be shown again
For hiding expressions, we use comma
expressions to attach a void
statement to an expression value without changing
the meaning of the code.
Example:
1foo(1, 2, (void 1, 3));
Will render as
1foo(1, 2)
Also supports a visible ellipsis:
1const x = (void '...', 3);
Renders to:
1x = ...
Use special comment directives:
1before(); 2/// !hide 3notShown(); 4/// !show 5after();
Thanks goes to these wonderful people (emoji key):
This project follows the all-contributors specification. Contributions of any kind welcome!
jsii is distributed under the Apache License, Version 2.0.
No vulnerabilities found.
No security vulnerabilities found.