Skip to content
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
70 changes: 70 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -872,6 +872,76 @@ expression are also tagged.
}

```
## Blocked Properties with ⛔
Properties whose names start with "⛔" are completely ignored during template processing. This is useful for:

1. Adding notes or comments that should not be evaluated
2. Temporarily disabling parts of a template
3. Keeping sensitive or debug information in the template but preventing its evaluation

When a property name starts with "⛔", the MetaInfoProducer will skip that property and all of its children, effectively making them invisible to the template processor.

```json
> .init -f "example/ex25.json"
{
"a": 42,
"⛔note": "${$string('should not be evaluated: ') & a}",
"c": "${a}"
}
> .out
{
"a": 42,
"⛔note": "${$string('should not be evaluated: ') & a}",
"c": 42
}
> .init -f "example/ex26.json"
{
"a": 42,
"⛔note": "${$string('Will NOT be evaluated: ') & a}",
"note": "${$string('Will be evaluated: ') & a}",
"config": {
"⛔productionDb": "${$env('DB_PROD_URL', 'mysql://prod.example.com:3306')}",
"productionDb": "${$env('DB_PROD_URL', 'mysql://prod.example.com:3306')}",
"localDb": "mysql://localhost:3306"
},
"features": {
"⛔experimental": {
"enabled": true,
"endpoint": "${$string('https://api.example.com/config/') & 'experimental'}"
},
"experimental": {
"enabled": true,
"endpoint": "${$string('https://api.example.com/config/') & 'experimental'}"
}
}
}
> .out
{
"a": 42,
"⛔note": "${$string('Will NOT be evaluated: ') & a}",
"note": "Will be evaluated: 42",
"config": {
"⛔productionDb": "${$env('DB_PROD_URL', 'mysql://prod.example.com:3306')}",
"productionDb": "mysql://prod.example.com:3306",
"localDb": "mysql://localhost:3306"
},
"features": {
"⛔experimental": {
"enabled": true,
"endpoint": "${$string('https://api.example.com/config/') & 'experimental'}"
},
"experimental": {
"enabled": true,
"endpoint": "https://api.example.com/config/experimental"
}
}
}
```

In these examples, `⛔...` will be completely ignored during template processing - the expression will not be evaluated.

Note that array elements with "⛔" in their values will still be processed, as array indices are numbers, not property names. Only object properties that start with "⛔" are blocked.

# Generative Templates
Templates can contain generative expressions that cause their content to change over time.
For instance the `$setInterval` function behaves exactly as it does in Javascript. Below,
Expand Down
5 changes: 5 additions & 0 deletions example/ex25.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"a": 42,
"⛔note": "${$string('should not be evaluated: ') & a}",
"c": "${a}"
}
20 changes: 20 additions & 0 deletions example/ex26.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"a": 42,
"⛔note": "${$string('Will NOT be evaluated: ') & a}",
"note": "${$string('Will be evaluated: ') & a}",
"config": {
"⛔productionDb": "${$env('DB_PROD_URL', 'mysql://prod.example.com:3306')}",
"productionDb": "${$env('DB_PROD_URL', 'mysql://prod.example.com:3306')}",
"localDb": "mysql://localhost:3306"
},
"features": {
"⛔experimental": {
"enabled": true,
"endpoint": "${$string('https://api.example.com/config/') & 'experimental'}"
},
"experimental": {
"enabled": true,
"endpoint": "${$string('https://api.example.com/config/') & 'experimental'}"
}
}
}
2 changes: 2 additions & 0 deletions src/MetaInfoProducer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@ export default class MetaInfoProducer {
const emit: MetaInfo[] = [];

async function getPaths(o:any, path: JsonPointerStructureArray = [], isTemp=false) {
if (String(path.at(-1))[0] === '⛔') return;

const type = typeof o;
const metaInfo: MetaInfo = {
"materialized__": true,
Expand Down
256 changes: 256 additions & 0 deletions src/test/MetaInfoProducer.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -1117,5 +1117,261 @@ test("temp vars 3", async () => {
]);
});

test("blocked paths with ⛔ character 1", async () => {
const template = {
"a": 42,
"⛔b": "Should be ignored",
"c": "${a}"
};
const metaInfos = await MetaInfoProducer.getMetaInfos(template);
expect(JSON.parse(stringify(metaInfos))).toEqual([
{
"absoluteDependencies__": [],
"dependees__": [],
"dependencies__": [],
"jsonPointer__": [
"a"
],
"materialized__": true,
"parent__": [],
"tags__": [],
"temp__": false,
"treeHasExpressions__": false
},
{
"absoluteDependencies__": [],
"dependees__": [],
"dependencies__": [],
"exprRootPath__": null,
"exprTargetJsonPointer__": [],
"expr__": "a",
"jsonPointer__": [
"c"
],
"materialized__": true,
"parent__": [],
"tags__": [],
"temp__": false,
"treeHasExpressions__": true
},
{
"absoluteDependencies__": [],
"dependees__": [],
"dependencies__": [],
"jsonPointer__": [],
"materialized__": true,
"parent__": [],
"tags__": [],
"temp__": false,
"treeHasExpressions__": true
}
]);
});

test("blocked paths with ⛔ character 2", async () => {
const template = {
"a": 42,
"b": {
"normal": "value",
"⛔secret": {
"nested": "This should be ignored"
}
},
"c": "${a}"
};
const metaInfos = await MetaInfoProducer.getMetaInfos(template);
expect(JSON.parse(stringify(metaInfos))).toEqual([
{
"absoluteDependencies__": [],
"dependees__": [],
"dependencies__": [],
"jsonPointer__": [
"a"
],
"materialized__": true,
"parent__": [],
"tags__": [],
"temp__": false,
"treeHasExpressions__": false
},
{
"absoluteDependencies__": [],
"dependees__": [],
"dependencies__": [],
"jsonPointer__": [
"b",
"normal"
],
"materialized__": true,
"parent__": [
"b"
],
"tags__": [],
"temp__": false,
"treeHasExpressions__": false
},
{
"absoluteDependencies__": [],
"dependees__": [],
"dependencies__": [],
"jsonPointer__": [
"b"
],
"materialized__": true,
"parent__": [],
"tags__": [],
"temp__": false,
"treeHasExpressions__": false
},
{
"absoluteDependencies__": [],
"dependees__": [],
"dependencies__": [],
"exprRootPath__": null,
"exprTargetJsonPointer__": [],
"expr__": "a",
"jsonPointer__": [
"c"
],
"materialized__": true,
"parent__": [],
"tags__": [],
"temp__": false,
"treeHasExpressions__": true
},
{
"absoluteDependencies__": [],
"dependees__": [],
"dependencies__": [],
"jsonPointer__": [],
"materialized__": true,
"parent__": [],
"tags__": [],
"temp__": false,
"treeHasExpressions__": true
}
]);
});

test("blocked paths with ⛔ character in array", async () => {
const template = {
"a": 42,
"arr": [
"normal",
"⛔blocked", // This should be included since array indices are numbers, not strings with ⛔
{
"⛔key": "blocked object key",
"normal": "normal object key"
}
]
};
const metaInfos = await MetaInfoProducer.getMetaInfos(template);
expect(JSON.parse(stringify(metaInfos))).toEqual([
{
"absoluteDependencies__": [],
"dependees__": [],
"dependencies__": [],
"jsonPointer__": [
"a"
],
"materialized__": true,
"parent__": [],
"tags__": [],
"temp__": false,
"treeHasExpressions__": false
},
{
"absoluteDependencies__": [],
"dependees__": [],
"dependencies__": [],
"jsonPointer__": [
"arr",
0
],
"materialized__": true,
"parent__": [
"arr"
],
"tags__": [],
"temp__": false,
"treeHasExpressions__": false
},
{
"absoluteDependencies__": [],
"dependees__": [],
"dependencies__": [],
"jsonPointer__": [
"arr",
1
],
"materialized__": true,
"parent__": [
"arr"
],
"tags__": [],
"temp__": false,
"treeHasExpressions__": false
},
{
"absoluteDependencies__": [],
"dependees__": [],
"dependencies__": [],
"jsonPointer__": [
"arr",
2,
"normal"
],
"materialized__": true,
"parent__": [
"arr",
2
],
"tags__": [],
"temp__": false,
"treeHasExpressions__": false
},
{
"absoluteDependencies__": [],
"dependees__": [],
"dependencies__": [],
"jsonPointer__": [
"arr",
2
],
"materialized__": true,
"parent__": [
"arr"
],
"tags__": [],
"temp__": false,
"treeHasExpressions__": false
},
{
"absoluteDependencies__": [],
"dependees__": [],
"dependencies__": [],
"jsonPointer__": [
"arr"
],
"materialized__": true,
"parent__": [],
"tags__": [],
"temp__": false,
"treeHasExpressions__": false
},
{
"absoluteDependencies__": [],
"dependees__": [],
"dependencies__": [],
"jsonPointer__": [],
"materialized__": true,
"parent__": [],
"tags__": [],
"temp__": false,
"treeHasExpressions__": false
}
]);
});



Loading