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
List Params support in CEL #5137
Conversation
Codecov ReportBase: 56.41% // Head: 56.30% // Decreases project coverage by
Additional details and impacted files@@ Coverage Diff @@
## master #5137 +/- ##
==========================================
- Coverage 56.41% 56.30% -0.12%
==========================================
Files 315 315
Lines 21150 21282 +132
Branches 4288 4338 +50
==========================================
+ Hits 11932 11982 +50
- Misses 8193 8263 +70
- Partials 1025 1037 +12
Help us with your feedback. Take ten seconds to tell us how you rate us. Have a feature suggestion? Share it here. ☔ View full report at Codecov. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The winds are blowing in the direction of making lists be delimited strings rather than JSON expressions. This would make it easier to represent in GUI dialogs and reads easier in .env files.
src/deploy/functions/build.ts
Outdated
export type Field<T extends string | number | boolean> = T | Expression<T> | null; | ||
export type FieldList = Expression<string[]> | (string | Expression<string>)[] | null; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I do wonder if we can start by assuming you have either a string[] or Expression<string[]>. Array<string | Expression> may be hard to represent in Proto and it may not be a hard blocker for people to not be able to hard code only parts of a list.
src/deploy/functions/build.ts
Outdated
export type Field<T extends string | number | boolean> = T | Expression<T> | null; | ||
export type FieldList = Expression<string[]> | (string | Expression<string>)[] | null; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, nit picking, if it's a FieldList it sounds like a list of fields. A ListField sounds like a field that is a list, which personally sounds more accurate to my ears. NBD if you disagree though.
src/deploy/functions/params.ts
Outdated
(res: string[]) => res | ||
); | ||
} else if (isTextInput(param.input)) { | ||
prompt = `Enter a list of strings for ${param.label || param.name}:`; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This will probably get more complex if/when we transition to inputting with a delimiter. If your delimiter is newline, you probably have to accept double newlines as the way you end your prompt. IDK if the prompt library supports that, so we might, for now stick to just comma delimiters.
src/deploy/functions/params.ts
Outdated
@@ -584,6 +688,10 @@ async function promptResourceString( | |||
} | |||
|
|||
type retryInput = { message: string }; | |||
function shouldRetry(obj: any): obj is retryInput { | |||
return (obj as retryInput).message !== undefined; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you also need to verify that obj is indeed an object? It looks like the previous code this is replacing used to check for that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good catch.
resolvedDefault: T[] | undefined, | ||
converter: (res: string[]) => T[] | retryInput | ||
): Promise<T[]> { | ||
const response = await promptOnce({ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In firebase init we explain to people that they should use space to select a list item and return to choose the selection. We should probably add that to the prompt here. Similarly, when using a text input for list items, we should explain the delimiter usage.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1
@@ -106,6 +107,14 @@ export function assertKeyTypes<T extends object>( | |||
} | |||
continue; | |||
} | |||
if (schemaType === "List") { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Technically you've defined "List?" as a type. Do you want to check for value === null first or is that case already handled?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It looks to me like the conditional checks immediately above that one cover this case, unless I'm badly misinterpreting your comment.
expect( | ||
resolveExpression( | ||
"string[]", | ||
'{{ params.FOO == params.FOO ? [ "foo", params.BAR, {{ params.BAR }} ] : [] }}', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't the last field be "{{ params.BAR }}"
(with the quotes)
src/deploy/functions/cel.ts
Outdated
// by the preprocessLists() invocation at the beginning of CEL resolution | ||
const parsed = JSON.parse(value); | ||
if (!Array.isArray(parsed)) { | ||
throw new ExprParseError(""); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we include more descriptive parser error message?
src/deploy/functions/params.ts
Outdated
(res: string[]) => res | ||
); | ||
} else if (isTextInput(param.input)) { | ||
prompt = `Enter a list of strings for ${param.label || param.name}:`; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can we expand the prompt to help instruct users how they can input the delimeter-separated list input?
resolvedDefault: T[] | undefined, | ||
converter: (res: string[]) => T[] | retryInput | ||
): Promise<T[]> { | ||
const response = await promptOnce({ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1
Co-authored-by: Daniel Lee <danielylee@google.com>
Co-authored-by: Daniel Lee <danielylee@google.com>
Co-authored-by: Daniel Lee <danielylee@google.com>
Co-authored-by: Daniel Lee <danielylee@google.com>
Co-authored-by: Daniel Lee <danielylee@google.com>
"This creaky regular expression based hack of an interpreter for our limited CEL subset can't possibly handle more features!," said Frog, as he built another feature on top of it