-
Notifications
You must be signed in to change notification settings - Fork 2
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
feat: write a prototypeApplication
schema with definitions based on primary application type
#236
feat: write a prototypeApplication
schema with definitions based on primary application type
#236
Conversation
|
||
export interface OwnersNoticeDate extends BaseOwners { | ||
noticeDate: Date; | ||
} |
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.
Ownership
is a nice migration story:
Our original application
types used code comments to note which shape of owners we expected for various application types, ultimately justifying a type that was too-generic and made all of these options possible: https://github.com/theopensystemslab/digital-planning-data-schemas/blob/main/types/schemas/application/data/Applicant.ts#L88-L101
Now the LDCApplicant
definition and so on specify only the ownership variation it actually expects!
pp: PPApplicationData; | ||
listed: NonFeeCarryingApplicationData; | ||
landDrainageConsent: FeeCarryingApplicationData; |
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.
Again, nice migration win in here of now explicitly defining which application types are "fee carrying" and which are not. There's a big semantic difference between fee: 0
& fee: "notApplicable"
that is now better communicated, no longer confusable based on a union type !
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 is nice! I had imagined these maps would always be application type specific, but this is a great solution.
@@ -174,15 +174,15 @@ type BasePlanningDesignation = | |||
*/ | |||
type NonIntersectingPlanningDesignation = { | |||
intersects: false; | |||
} & BasePlanningDesignation; | |||
} & {value: BasePlanningDesignation}; |
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.
PlanningDesignations
are actually an interesting case where I'm not totally convinced we want to migrate to a new enum
structure? Will be curious to hear BOPS feedback on this.
Designations & constraints aren't the same typical value/description
object enums like ProjectTypes
(which make sense to simplify to string enums!) because other properties are also/still present (eg intersects
).
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 is good to flag that they aren't true "enums" as per the rest.
There might be a middle ground where they still end up in a fairly formal anyOf
but keep a single enum-like key (as opposed to having to have a perfectly matching value and description).
Agreed that reaching out for feedback here seems best!
@@ -1,4 +1,4 @@ | |||
import {URL} from '../../shared/utils'; | |||
import {URL} from './utils'; | |||
|
|||
/** | |||
* @id #Responses |
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.
Note that Responses
are now shared between the application
& prototypeApplication
, but nearly all else is re-defined fresh (eg even Metadata
requires updated FileType
enum structure).
The shared
folder is generally still sparsely populated, this will make more sense to refactor once prototypeApplication
replaces application
in my opinion ! It's felt much easier to just keep them totally seperate while doing this comparison/migration exercise rather than try to refactor/share more in same go.
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.
Makes sense!
"Integer": { | ||
"format": "integer", | ||
"type": "number" | ||
}, |
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 is a first attempt at adding a specific "Integer" type via utils defintions - this works well as an initial placeholder, but isn't technically meaningful yet !
I'm aiming for "type": "integer"
as supported by JSON Schema, but with a way of generating from ts-json-schema-generator
.
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.
Okay further investigation here:
- our lib
ts-json-schema-generator
does NOT supportinteger
types (yet?): https://github.com/vega/ts-json-schema-generator?tab=readme-ov-file#current-state - alternatively
typescript-json-schema
does support with an annotation like this: https://github.com/YousefED/typescript-json-schema?tab=readme-ov-file#annotations (this is a good example of our goal state)
Is it insane to think about switching TS generation libs? This thread has a lot of comparison notes, opinions: vega/ts-json-schema-generator#101 (one for a followup discussion/PR for sure!)
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 that's a frustrating limitation to hit.
It looks like ajv-formats support int32 and floats, so it might just be that this is the recommended library to use (or one with similar support).
Not sure how well this would work cross-language or in other contexts - it's definitely far from ideal, and we should strive to have the generated .json
file be the source of truth 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.
Another option (I've not tried yet) might be multipleOf: 1
(docs).
Awkward workaround, but maybe one of these two options might get us to v1.
// name: 'PrototypeApplication', | ||
// schema: prototypeApplicationSchema, | ||
// examples: getJSONExamples<PrototypeApplication>('prototypeApplication'), | ||
// }, |
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 didn't work so smoothly & throws a number of type errors !
One to sort out in a follow-up PR I think, and for here I'm just relying on TS definitions & pnpm build-json-examples
as the "validation" check (eg building the JSON example fails if type errors).
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.
Happy for this to be a follow up!
/** | ||
* @id #FileType | ||
* @description Types of planning documents and drawings | ||
*/ | ||
export type FileType = | ||
export type PrototypeFileType = |
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.
A few temporary "renames" required else we'll throw an error that more than one type with same name can't be exported ! Again, these will get simplified once prototypeApplication
replaces application
prototypeApplication
schema with definitions based on primary application type
@@ -712,6 +712,6 @@ export const landDrainageConsent: Application = { | |||
payable: [], | |||
}, | |||
}, | |||
schema: `https://theopensystemslab.github.io/digital-planning-data-schemas/${version}/schema.json`, | |||
schema: `https://theopensystemslab.github.io/digital-planning-data-schemas/${version}/schemas/application.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.
When we re-organised the file structure, we missed updating existing example payload URLs - so those are handled here! Sorry it makes for another 13 x 2 files changed though 🙈
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 thanks!
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.
Huge effort! 🙌
A few very minor comments - pretty much all typos and annotation suggestions.
All looks good to me, happy to help and fix forward some of the outstanding issues around tests and types.
@@ -712,6 +712,6 @@ export const landDrainageConsent: Application = { | |||
payable: [], | |||
}, | |||
}, | |||
schema: `https://theopensystemslab.github.io/digital-planning-data-schemas/${version}/schema.json`, | |||
schema: `https://theopensystemslab.github.io/digital-planning-data-schemas/${version}/schemas/application.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.
Good catch thanks!
@@ -174,15 +174,15 @@ type BasePlanningDesignation = | |||
*/ | |||
type NonIntersectingPlanningDesignation = { | |||
intersects: false; | |||
} & BasePlanningDesignation; | |||
} & {value: BasePlanningDesignation}; |
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 is good to flag that they aren't true "enums" as per the rest.
There might be a middle ground where they still end up in a fairly formal anyOf
but keep a single enum-like key (as opposed to having to have a perfectly matching value and description).
Agreed that reaching out for feedback here seems best!
@@ -1,4 +1,4 @@ | |||
import {URL} from '../../shared/utils'; | |||
import {URL} from './utils'; | |||
|
|||
/** | |||
* @id #Responses |
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.
Makes sense!
"Integer": { | ||
"format": "integer", | ||
"type": "number" | ||
}, |
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 that's a frustrating limitation to hit.
It looks like ajv-formats support int32 and floats, so it might just be that this is the recommended library to use (or one with similar support).
Not sure how well this would work cross-language or in other contexts - it's definitely far from ideal, and we should strive to have the generated .json
file be the source of truth here.
// name: 'PrototypeApplication', | ||
// schema: prototypeApplicationSchema, | ||
// examples: getJSONExamples<PrototypeApplication>('prototypeApplication'), | ||
// }, |
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.
Happy for this to be a follow up!
pp: PPApplicationData; | ||
listed: NonFeeCarryingApplicationData; | ||
landDrainageConsent: FeeCarryingApplicationData; |
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 is nice! I had imagined these maps would always be application type specific, but this is a great solution.
* @id #UKRegion | ||
* @description The UK region that contains this address sourced from planning.data.gov.uk/dataset/region, where London is a proxy for the Greater London Authority (GLA) area | ||
*/ | ||
export type UKRegion = |
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 new in this PR, but just noticed!) These are actually regions of England and not the UK - maybe a question for Planning Data would be if this is always going to be the case.
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.
Aha this is a great shout - I think we should probably be using "England" throughout for clarity. Going to find + replace this one in a followup PR 👍
export interface LondonProperty extends UKProperty { | ||
region: Extract<UKRegion, 'London'>; | ||
titleNumber?: { | ||
known: 'Yes' | 'No'; |
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.
We may want a pass through all binary choices to make them booleans.
*/ | ||
newStoreys?: NewBuildingsOrStoreys; | ||
/** | ||
* @description Project cost |
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.
nit: Worth adding GBP?
Co-authored-by: Dafydd Llŷr Pearson <[email protected]>
I know this is a VERY BIG PR - but it wasn't a particularly easy one to break up, so thanks in advance for patience reviewing !
Here's a summary of key changes:
prototypeApplication
schema now has "real" type definitions which are feature-parity with the originalapplication
schema - but now enhanced with rules-based variations based on the primaryapplicationType
@id
notations as we used to use per Idox feedback about this and opted for just@descriptions
, so please take a look at the generated JSON too and see how this comparesapplication
examples now have an equivalentprototypeApplication
example for side-by-side comparisons of what's changing (13 example payloads in total => 26 new files here)What I haven't done here:
data.proposal
for this MVP, definitely one to revisit separately soon ! Also, it'll never be perfectapplication
schema here, which is already "householder" centric in-line with upcoming integration expectations