BSON-Transpilers
Transpilers for building BSON documents in any language. Current support
provided for shell
as inputs. java
, c#
, node
, shell
, python
, ruby
and go
as outputs.
See also the original presentation: https://drive.google.com/file/d/1jvwtR3k9oBUzIjL4z_VtpHvdWahfcjTK/view
NOTES:
- A version of the code with support for
python
with corresponding test cases has been removed to avoid bundling and supporting unused code, however it can be still be found in https://github.com/mongodb-js/compass/tree/80cf701e44cd966207f956fac69e8233861b1cd5/packages/bson-transpilers. - The
shell
output is disabled as is essentially the only input in use and it produces code that is compatible only with legacy mongo
shell not the new mongosh
shell. See COMPASS-4930 for some additional context.
Usage
const transpiler = require('bson-transpilers');
const input = 'shell';
const output = 'java';
const string = `
{ item: "book", qty: Int32(10), tags: ["red", "blank"], dim_cm: [14, Int32("81")] }`;
try {
const compiledString = transpiler[input][output].compile(string);
console.log(compiledCode);
} catch (error) {
console.error(error);
}
API
compiledString = transpiler[inputLang][outputLang].compile(codeString)
Output a compiled string given input and output languages.
- inputLang: Input language of the code string.
shell
and javascript
are currently supported. - outputLang: The language you would like the output to be.
java
,
python
, shell
, javascript
, and csharp
are currently supported. - codeString: The code string you would like to be compiled to your
selected output language.
importsString = transpiler[inputLang][outputLang].getImports(mode, driverSyntax)
Output a string containing the set of import statements for the generated code
to compile. These are all the packages that the compiled code could use so that
the transpiler output will be runnable.
- inputLang: Input language of the code string.
shell
and javascript
are currently supported. - outputLang: The language you would like the output to be.
java
,
python
, shell
, javascript
, and csharp
are currently supported. - mode: Either 'Query' for the
.find()
method or 'Pipeline' for .aggregate()
. - driverSyntax: Whether or not you want to include Driver Syntax into your output string.
catch (error)
Any transpiler errors that occur will be thrown. To catch them, wrap the
transpiler
in a try/catch
block.
- error.message: Message
bson-transpilers
will send back letting you know
the transpiler error. - error.stack: The usual error stacktrace.
- error.code: Error code that
bson-transpilers
adds to the error object to
help you distinguish error types. - error.line: If it is a syntax error, will have the line.
- error.column: If it is a syntax error, will have the column.
- error.symbol: If it is a syntax error, will have the symbol associated with the error.
State
The CodeGenerationVisitor
class manages a global state which is bound to the argsTemplate
functions. This state is intended to be used as a solution for the argsTemplate
functions to communicate with the DriverTemplate
function. For example:
ObjectIdEqualsArgsTemplate: !!js/function &ObjectIdEqualsArgsTemplate >
(_) => {
this.oneLineStatement = "Hello World";
return '';
}
DriverTemplate: !!js/function &DriverTemplate >
(_spec) => {
return this.oneLineStatement;
}
The output of the driver syntax for this language will be the one-line statement Hello World
.
DeclarationStore
A more practical use-case of state is to accumulate variable declarations throughout the argsTemplate
to be rendered by the DriverTemplate
. That is, the motivation for using DeclarationStore
is to prepend the driver syntax with variable declarations rather than using non-idiomatic solutions such as closures.
The DeclarationStore
class maintains an internal state concerning variable declarations. For example,
(arg) => {
return this.declarations.add('Temp', 'objectID', (varName) => {
return [
`${varName}, err := primitive.ObjectIDFromHex(${arg})`,
'if err != nil {',
' log.Fatal(err)',
'}',
].join('\n');
});
};
Note that each use of the same variable name will result in an increment being added to the declaration statement. For example, if the variable name objectIDForTemp
is used two times the resulting declaration statements will use objectIDForTemp
for the first declaration and objectID2ForTemp
for the second declaration. The add
method returns the incremented variable name, and is therefore what would be expected as the right-hand side of the statement defined by the argsTemplate
function.
The instance of the DeclarationStore
constructed by the transpiler class is passed into the driver, syntax via state, for use:
(spec) => {
const comment = '// some comment';
const client =
'client, err := mongo.Connect(context.Background(), options.Client().ApplyURI(cs.String()))';
return '#{comment}\n\n#{client}\n\n${this.declarations.toString()}';
};
Errors
There are a few different error classes thrown by bson-transpilers
, each with
their own error code:
BsonTranspilersArgumentError
code: E_BSONTRANSPILERS_ARGUMENT
This will occur when you're using a method with a wrong number of arguments, or
the arguments are of the wrong type.
For example, ObjectId().equals()
requires one argument and it will throw if
anything other than one argument is provided:
ObjectId().equals(ObjectId(), ObjectId());
ObjectId().equals(ObjectId());
ObjectId({});
ObjectId();
BsonTranspilersAttributeError
code: E_BSONTRANSPILERS_ATTRIBUTE
Will be thrown if an invalid method or property is used on a BSON object. For
example, since new DBRef()
doesn't have a method .foo()
, transpiler will
throw:
new DBRef('newCollection', new ObjectId()).foo();
new DBRef('newCollection', new ObjectId()).toString(10);
code: E_BSONTRANSPILERS_SYNTAX
This will throw if you have a syntax error. For example missing a colon in
Object assignment, or forgetting a comma in array definition:
{ key 'beep' }
[ 'beep'; 'boop' 'beepBoop' ]
{ key: 'beep' }
[ 'beep', 'boop', 'beepBoop' ]
BsonTranspilersTypeError
code: E_BSONTRANSPILERS_TYPE
This error will occur if a symbol is treated as the wrong type. For example, if
a non-function is called:
Long.MAX_VALUE();
Long.MAX_VALUE;
BsonTranspilersUnimplementedError
code: E_BSONTRANSPILERS_UNIMPLEMENTED
If there is a feature in the input code that is not currently supported by the
transpiler.
BsonTranspilersRuntimeError
code: E_BSONTRANSPILERS_RUNTIME
A generic runtime error will be thrown for all errors that are not covered by the
above list of errors. These are usually constructor requirements, for example
when using a RegExp()
an unsupported flag is given:
new RegExp('ab+c', 'beep');
new RegExp('ab+c', 'im');
BsonTranspilersInternalError
code: E_BSONTRANSPILERS_INTERNAL
In the case where something has gone wrong within compilation, and an error has
occured. If you see this error, please create an issue on Github!
Install
npm install -S bson-transpilers
Contributing
Head over to the readme on contributing to find out more
information on project structure and setting up your environment.
Authors
License
Apache-2.0