-
Notifications
You must be signed in to change notification settings - Fork 39
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
New centralised model for CALM (#790) #902
Conversation
@@ -0,0 +1,17 @@ | |||
/* eslint-disable @typescript-eslint/no-explicit-any */ |
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, it would be good to not have this linting suppression. What if we use unknown
on line 10 instead of any
.
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.
Ah yes - that was a topic wanted to raise but forgot. In the end I went with status quo in other classes so let's reiterate this on next meet-up. Will go with unknown
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.
Discussed this further with @aidanm3341 further and we agreed it would have been better to go with object than unknown. However, on further thought, I decided that actually it might be better to define types in the schema structures after all and have added this on latest commit.
expect(control.name).toBe('JSON Control'); | ||
expect(control.description).toBe('Description from JSON'); | ||
}); | ||
}); |
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 reckon these data classes be responsible for basic validation that the fields in the input data exist before using them. E.g. if name was not provided, an error should be thrown here
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.
Think its a good question - certainly on #790 we discussed the generator and visualizer would assume the document is validated already. The quesiton is how will the validator work with the model
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.
As long as we're consistent either way, e.g. I noticed that in the flow model you are doing some basic validations "// Ensure value
is an object". If we're assuming that the input is valid, then we don't need that validation check there
shared/src/model/node.ts
Outdated
public dataClassification?: CalmDataClassification, | ||
public runAs?: string, | ||
public instance?: string, | ||
public interfaces?: CalmInterface[], |
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.
to make using these model objects a little nicer to use, we could get rid of the optional aspect of these lists and instead default them to an empty list. That would mean that any client code using these models doesn't have to worry about checking for undefined before iterating over it.
public interfaces: CalmInterface[] = []
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.
Yeah thinkng about it, the optionality I put in because it matched the json-schema btu given we are parsing I like the idea of avoiding such checks.
shared/src/model/node.ts
Outdated
export class CalmNodeDetails { | ||
'detailed-architecture'?: string; | ||
'required-pattern'?: string; | ||
|
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 this class doesn't have a constructor like the others? Not sure if I'm missing something with this particular class
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.
Yeah this class clearly got neglected :D
0c4d0cf
to
94e0ad9
Compare
relationships?: CalmRelationshipSchema[]; | ||
metadata?: CalmMetadataSchema; | ||
controls?: CalmControlsSchema; | ||
flows?: CalmFlowSchema[]; |
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.
One thing I considered was stating that this could be an array of CalmFlowSchema[] | String[]. For now I kept it as this, but it requires the calm doc to be de-referenced before parsing which left as a TODO as requires @willosborne PR work on SchemaDirectory.
const logger = CalmParser.logger; | ||
try { | ||
const data = fs.readFileSync(coreCalmFilePath, 'utf8'); | ||
const dereferencedData: CalmCoreSchema = JSON.parse(data); // TODO: this needs to use SchemaDirectory to parse the other documents e.g. flows. |
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 don't think this needs to block the PR to get the models in, but we really do need to ensure that the document is dereferenced prior to trying to parse into a model. If we decide we don't want to do that then likely CalmCore.fromJson doesn't get called. I think the individual Calm method fromJson e.g. CalmFlow.fromJson would though.
A similar thing applies to the fact that a CalmControlDetail has reference to a requirementUrl but there is no official linkage to load the CalmRequirement. Added that to description of PR to consider CALM change to have a linkage of flowUrls.
94e0ad9
to
8d352ca
Compare
8d352ca
to
3725906
Compare
//TODO: There is no required section. | ||
export type CalmCoreSchema = { | ||
nodes?: CalmNodeSchema[]; | ||
relationships?: CalmRelationshipSchema[]; |
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.
aren't nodes and relationships required?
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.
Not atm on core.json which is why I put that an observation on this PR description
constructor(public uniqueId: string) {} | ||
|
||
static fromJson(data: CalmInterfaceTypeSchema): CalmInterface { | ||
if ('host' in data && 'port' in data) { |
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 bit is the only part I'm a little iffy about. Happy to proceed with this approach for now but we might need some more thought on this later
|
||
static fromJson(data: CalmMetadataSchema): CalmMetadata { | ||
const flattenedData = data.reduce((acc, curr) => { | ||
return { ...acc, ...curr }; |
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.
Very nifty.
constructor(public data: Record<string, unknown>) {} | ||
|
||
static fromJson(data: CalmMetadataSchema): CalmMetadata { | ||
const flattenedData = data.reduce((acc, curr) => { |
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.
Does this flatten only the top level? We probably don't want it to recursively flatten all the nested objects
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.
Should be only first level, but can add a test case to confirm on subsequent commit.
🔍 Summary
This PR introduces a centralized and structured data model for CALM. Per discussion on #899, The new model provides well-defined TypeScript classes and enums for core CALM components, ensuring seamless integration and validation for cli and visualizer componenets.
✨ Key Changes
CalmCore
as the centralized entry point for nodes, relationships, metadata, controls, and flows.CalmNode
,CalmRelationship
,CalmFlow
,CalmControl
, andCalmMetadata
.fromJson()
factory method to enable seamless conversion from JSON.❌ Out of Scope for this PR
types.ts
yet, as this will wait for the completion of SchemaDirectory changes as per Restructure SchemaDirectory to use document loading strategy #897Observations around CALM Specification