Skip to content

Commit

Permalink
Add else to retrieve and var.
Browse files Browse the repository at this point in the history
If the named variable isn't set, then (and only then) an else clause is executed to return a value.

This is useful for defaults, but also for sub-expressions where it only does things like prompting the user if the value isn't set.

Part of #36.
  • Loading branch information
jkomoros committed Jul 9, 2023
1 parent 21d8ef3 commit c5019be
Show file tree
Hide file tree
Showing 6 changed files with 129 additions and 3 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -554,6 +554,7 @@ Returns a variable from environment. See also `let`.
Required parameters:
- `name` - A named variable in environment to get.
- `else` - If the key does not exist, execute this sub-expression and return its value instead.
#### let
Expand Down Expand Up @@ -605,6 +606,7 @@ Unlike `let`, this affects multiple runs. See also `store` and `delete`.
Required parameters:
- `store` - (optional) The ID of the store to store in. If omitted, will use environment.store. By convention you should name a store like `komoroske.com:name`, to avoid collisions.
- `key` - The key to retrieve.
- `else` - If the key does not exist, execute this sub-expression and return its value instead.
Environment:
- `store` - The default store ID to use if one is not provided.
Expand Down
42 changes: 42 additions & 0 deletions seed-schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -2057,6 +2057,27 @@
"description": "The name of the variable in environment to fetch"
}
]
},
"else": {
"anyOf": [
{
"$ref": "#/definitions/seedData"
},
{
"$ref": "#/definitions/seedData/anyOf/0/properties/prompt/anyOf/1"
},
{
"anyOf": [
{
"not": {}
},
{
"$ref": "#/definitions/seedData/anyOf/5/properties/value/anyOf/2/anyOf/1/additionalProperties/anyOf/2"
}
],
"description": "The sub-expression to execute to get a value if value is undefined"
}
]
}
},
"required": [
Expand Down Expand Up @@ -2350,6 +2371,27 @@
"description": "The name of the variable in environment to retrieve"
}
]
},
"else": {
"anyOf": [
{
"$ref": "#/definitions/seedData"
},
{
"$ref": "#/definitions/seedData/anyOf/0/properties/prompt/anyOf/1"
},
{
"anyOf": [
{
"not": {}
},
{
"$ref": "#/definitions/seedData/anyOf/5/properties/value/anyOf/2/anyOf/1/additionalProperties/anyOf/2"
}
],
"description": "The sub-expression to execute to get a value if value is undefined"
}
]
}
},
"required": [
Expand Down
10 changes: 8 additions & 2 deletions src/grow.ts
Original file line number Diff line number Diff line change
Expand Up @@ -586,7 +586,11 @@ const growVar = async (seed : Seed<SeedDataVar>, env : Environment) : Promise<Va
const nameInput = extractString(await getProperty(seed, env, data.name));
const name = env.getVarName(nameInput);
//environment.get will properly refuse to get secretValues.
return env.get(name);
const result = env.get(name);
if (result === null) {
return await getProperty(seed, env, data.else, null);
}
return result;
};

const growLet = async (seed : Seed<SeedDataLet>, env : Environment) : Promise<Value> => {
Expand Down Expand Up @@ -632,7 +636,9 @@ const growRetrieve = async (seed : Seed<SeedDataRetrieve>, env : Environment) :
const storeID = env.getStoreID(rawStoreID);
const key = extractString(await getProperty(seed, env, data.name));
const result = seed.garden.profile.retrieve(storeID, key);
if (result === undefined) return null;
if (result === undefined) {
return await getProperty(seed, env, data.else, null);
}
return result;
};

Expand Down
4 changes: 3 additions & 1 deletion src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -768,7 +768,8 @@ export type SeedDataThrow = z.infer<typeof seedDataThrow>;
const seedDataConfigVar = {
type: z.literal('var'),
properties: {
name: varName.describe('The name of the variable in environment to fetch')
name: varName.describe('The name of the variable in environment to fetch'),
else: inputValue.optional().describe('The sub-expression to execute to get a value if value is undefined'),
}
};

Expand Down Expand Up @@ -823,6 +824,7 @@ const seedDataConfigRetrieve = {
properties: {
store: storeID.optional().describe('The store ID to use'),
name: storeKey.describe('The name of the variable in environment to retrieve'),
else: inputValue.optional().describe('The sub-expression to execute to get a value if value is undefined'),
}
};

Expand Down
42 changes: 42 additions & 0 deletions test/base/a_test.json
Original file line number Diff line number Diff line change
Expand Up @@ -279,6 +279,48 @@
"throw-test": {
"type": "throw",
"error": "This is an error"
},
"var-with-value-set": {
"type": "let",
"name": "val",
"value": 3,
"block": {
"type": "var",
"name": "val",
"else": {
"type": "throw",
"error": "This shouldn't happen since val is set"
}
}
},
"var-without-value-set": {
"type": "var",
"name": "val",
"else": 5
},
"retrieve-with-value-set": {
"type": "array",
"return": "last",
"items": [
{
"type": "store",
"name": "val",
"value": 3
},
{
"type": "retrieve",
"name": "val",
"else": {
"type": "throw",
"error": "This shouldn't happen since val is set"
}
}
]
},
"retrieve-without-value-set": {
"type": "retrieve",
"name": "val",
"else": 5
}
}
}
32 changes: 32 additions & 0 deletions test/base/test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -845,6 +845,38 @@ Suffix`;
});
});

it('var set else test', async () => {
const garden = loadTestGarden();
const seed = await garden.seed('var-with-value-set');
const actual = await seed.grow();
const golden = 3;
assert.deepStrictEqual(actual, golden);
});

it('var unset else test', async () => {
const garden = loadTestGarden();
const seed = await garden.seed('var-without-value-set');
const actual = await seed.grow();
const golden = 5;
assert.deepStrictEqual(actual, golden);
});

it('retrieve set else test', async () => {
const garden = loadTestGarden();
const seed = await garden.seed('retrieve-with-value-set');
const actual = await seed.grow();
const golden = 3;
assert.deepStrictEqual(actual, golden);
});

it('retrieve unset else test', async () => {
const garden = loadTestGarden();
const seed = await garden.seed('retrieve-without-value-set');
const actual = await seed.grow();
const golden = 5;
assert.deepStrictEqual(actual, golden);
});

});

describe('expandSeedPacket tests', () => {
Expand Down

0 comments on commit c5019be

Please sign in to comment.