-
Notifications
You must be signed in to change notification settings - Fork 1.1k
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
shell: Even more types #21425
base: main
Are you sure you want to change the base?
shell: Even more types #21425
Changes from 1 commit
97d27a5
de229c6
203a0fa
b9239a0
35a2d1e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -19,7 +19,7 @@ | |
|
||
import cockpit from "cockpit"; | ||
|
||
import { ManifestKeyword, ManifestDocs, Manifest, Manifests, Machine } from "./machines/machines"; | ||
import { ManifestKeyword, ManifestDocs, ManifestSection, Manifest, Manifests, Machine } from "./machines/machines"; | ||
|
||
export interface Location { | ||
host: string; | ||
|
@@ -91,6 +91,16 @@ export interface ManifestItem { | |
keywords: ManifestKeyword[]; | ||
} | ||
|
||
export interface ManifestParentSection { | ||
martinpitt marked this conversation as resolved.
Show resolved
Hide resolved
|
||
component?: string; | ||
docs?: ManifestDocs[]; | ||
} | ||
|
||
export interface ShellManifest { | ||
docs?: ManifestDocs[]; | ||
locales?: { [id: string]: string }; | ||
} | ||
|
||
export class CompiledComponents { | ||
manifests: Manifests; | ||
items: { [path: string] : ManifestItem; } = { }; | ||
|
@@ -101,7 +111,8 @@ export class CompiledComponents { | |
|
||
load(section: string): void { | ||
Object.entries(this.manifests).forEach(([name, manifest]) => { | ||
Object.entries(manifest[section] || { }).forEach(([prop, info]) => { | ||
const manifest_section = (manifest[section] || {}) as ManifestSection; | ||
Object.entries(manifest_section).forEach(([prop, info]) => { | ||
Comment on lines
+114
to
+115
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This cast is weird and IMHO detrimental. This isn't a case of "ts can't figure it out", it's literally "this could be anything as it's an user-provided (or at least user-customizable) external file on disk". So even after the That's why I think for this case something like There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Yes... it is keeping the status quo, but we should try to do better eventually, agreed.
Hmm, I would call this input validation rather than static typing. Currently, we validate manifest input by just pretending it's all valid and let the shell crash when it isn't. (And we have been fine with that since forever.) Static typing makes this obvious, but by itself is not enough to improve it. We would have to write new code to do real input validation. I was hoping there is a way to get TypeScript to do that. Here are some good pointers: https://stackoverflow.com/questions/33800497/check-if-an-object-implements-an-interface-at-runtime-with-typescript There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Yes, exactly. And input validation is a runtime thing, the type checker can't help with that. We either need some "JSON schema validation" thing, or just pick out the values individually with the expected type and default (which I personally favor -- it's explicit, tsc can help us get it right, and we don't reject manifests with wrong keys wholesale, which would be a behaviour changes). |
||
const item: ManifestItem = { | ||
path: "", // set below | ||
hash: "", // set below | ||
|
@@ -172,8 +183,11 @@ export class CompiledComponents { | |
// Still don't know where it comes from, check for parent | ||
if (!component) { | ||
const comp = this.manifests[path]; | ||
if (comp && comp.parent && comp.parent.component) | ||
component = comp.parent.component as string; | ||
if (comp && comp.parent) { | ||
const parent = comp.parent as ManifestParentSection; | ||
if (parent.component) | ||
component = parent.component; | ||
} | ||
Comment on lines
-175
to
+190
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In the same spirit as above, I think There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So you are asking for "The Shell should validate the schema of all manifests". That's a good idea. We could have done that without TypeScript all these years, but we didn't. A bug in a manifests is like a bug in JavaScript, and should be found and fixed by the developer. And while TypeScript might benefit from it once schema validation is done (think generating TS types from JSON schemas), I don't think TypeScript by itself is gonna help. All it does it point out our sins... So, can I ask to keep the manifest schema validation yak out of this PR? :-) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
I am fine with that. I am not fine with pretending that everything is good here and papering over the issue with There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Summary from meeting: My gut feeling/slight preference is the |
||
} | ||
|
||
const item = this.items[component]; | ||
|
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.
Hmm... we could make some functions like
manifest_parent_section(m: Manifest): ManifestParentSection
which would ide all the "unsafe" JSON manipulations.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 whole Manifest stuff should go to its own file, actually.
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.
Like, helpers which do type validation? what would they do on errors then?
This feels simultaneously too strict (hard to handle errors at that level, as these are effectively user-provided files) and too specific (we parse JSON everywhere, and should generalize the mechanics).
Are you aware of the bridge's jsonutil? That may be a more adequate way to parse JSON with strict typing, and the API would then also include default values.