Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

+ ++README #36

Merged
merged 2 commits into from
Dec 23, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 33 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ Stated templates are modular and can be imported from a URL:
}
```


## Why Do We Need stated?

Consider this ordinary program:
Expand Down Expand Up @@ -1719,6 +1720,38 @@ This can be combined with the `--importPath` option to import files relative to
"res": "bar: foo"
}
```
## The $open function
Allowing expressions to open local files is a security risk. For this reason the core TemplateProcessor does
not support the $open function. However, the CLI/REPL which are for local usage allow the $open function. Additionally,
programs that want to allow properly guarded `$open` operations may inject a `$open` function of their choosing
into the TemplateProcessor contexet. $open accepts a relative path, and parses the JSON or YAML file on that path into
an object.
```json [false, "true", false, "a.c='the answer is: 42' and b.c='the answer is: 42'", "true"]
> .note This shows two equivalent ways to open a json or yaml file using $open
"============================================================="
> .cd example
"Current directory changed to: /Users/falken/proj/jsonataexperiments/example"
> .init -f "importLocal.json"
{
"a": "${'ex01.json'~>$open~>$import}",
"b": "${$import($open('ex01.json'))}"
}
> .out
{
"a": {
"a": 42,
"b": 42,
"c": "the answer is: 42"
},
"b": {
"a": 42,
"b": 42,
"c": "the answer is: 42"
}
}
> .cd ..
"Current directory changed to: /Users/falken/proj/jsonataexperiments"
```
# Understanding Plans
This information is to explain the planning algorithms to comitters. As a user you do not need to understand how
Stated formulates plans. Before explaining how a plan is made, let's show the end-to-end flow of how a plan is used
Expand Down
4 changes: 4 additions & 0 deletions example/importLocal.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"a": "${'ex01.json'~>$open~>$import}",
"b": "${$import($open('ex01.json'))}"
}
18 changes: 11 additions & 7 deletions src/CliCore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ export default class CliCore {
return {...parsed, ...processedArgs}; //spread the processedArgs back into what was parsed
}

async readFileAndParse(filepath, importPath) {
async readFileAndParse(filepath, importPath?) {
const fileExtension = path.extname(filepath).toLowerCase().replace(/\W/g, '');
if (fileExtension === 'js' || fileExtension === 'mjs') {
return await import(CliCore.resolveImportPath(filepath, importPath));
Expand Down Expand Up @@ -117,11 +117,7 @@ export default class CliCore {
if(filepath===undefined){
return undefined;
}
let _filepath = filepath;
if(this.currentDirectory){
_filepath = path.join(this.currentDirectory, _filepath);
}
const input = await this.readFileAndParse(_filepath, importPath);
const input = await this.openFile(filepath);
const contextData = contextFilePath ? await this.readFileAndParse(contextFilePath, importPath) : {};
options.importPath = importPath; //path is where local imports will be sourced from. We sneak path in with the options
// if we initialize for the first time, we need to create a new instance of TemplateProcessor
Expand All @@ -143,7 +139,7 @@ export default class CliCore {
// set options
this.templateProcessor.logger.level = this.logLevel;
this.templateProcessor.logger.debug(`arguments: ${JSON.stringify(parsed)}`);

this.templateProcessor.context["open"] = this.openFile.bind(this); //$open('foo.json') is supported by the CLI adding $open function. It is not part of core TemplateProcessor as that would be security hole
try {
await this.templateProcessor.initialize(input);
if (oneshot === true) {
Expand All @@ -163,6 +159,14 @@ export default class CliCore {

}

private async openFile(fname:string){
let _filepath = fname;
if(this.currentDirectory){
_filepath = path.join(this.currentDirectory, _filepath);
}
return await this.readFileAndParse(_filepath);
}


async set(args) {
const options = args.match(/(?:[^\s"]+|"[^"]*")+/g);
Expand Down
2 changes: 1 addition & 1 deletion src/TestUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ function runMarkdownTests(testData: CommandAndResponse[], cliCore:CliCore, print
expect(responseNormalized).toBeDefined();
}
}
}, 30000); // set timeout to 30 seconds for each test
}, 100000); // set timeout to 100 seconds for each test
});
}finally {
cliCore.close();
Expand Down
Loading