-
Notifications
You must be signed in to change notification settings - Fork 247
feat: diagram edit handling COMPASS-9312 #6932
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
Changes from 11 commits
0f448e3
1ff361c
2cfef3a
ab816be
298348d
d37e941
c48a66e
e1175c3
7b8acd8
c2792e5
f116d6b
9102096
38d3165
555f3ef
37066a4
c019e8c
cf148ae
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -24,7 +24,7 @@ class DataModelStorageElectron implements DataModelStorage { | |
| async loadAll(): Promise<MongoDBDataModelDescription[]> { | ||
| try { | ||
| const res = await this.userData.readAll(); | ||
| return res.data; | ||
| return res.data as MongoDBDataModelDescription[]; | ||
|
||
| } catch (err) { | ||
| return []; | ||
| } | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,4 +1,96 @@ | ||
| import { z } from '@mongodb-js/compass-user-data'; | ||
| import type { MongoDBJSONSchema } from 'mongodb-schema'; | ||
|
|
||
| export const RelationshipSideSchema = z.object({ | ||
| ns: z.string(), | ||
| cardinality: z.number(), | ||
| fields: z.array(z.string()), | ||
| }); | ||
|
|
||
| export type RelationshipSide = z.output<typeof RelationshipSideSchema>; | ||
|
|
||
| export const RelationshipSchema = z.object({ | ||
| id: z.string(), | ||
paula-stacho marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| relationship: z.tuple([RelationshipSideSchema, RelationshipSideSchema]), | ||
| isInferred: z.boolean(), | ||
| }); | ||
|
|
||
| export type Relationship = z.output<typeof RelationshipSchema>; | ||
|
|
||
| export const StaticModelSchema = z.object({ | ||
| collections: z.array( | ||
| z.object({ | ||
| ns: z.string(), | ||
| jsonSchema: z.unknown(), // skipped for simplicity | ||
|
||
| indexes: z.array(z.record(z.unknown())), | ||
| shardKey: z.record(z.unknown()).optional(), | ||
| displayPosition: z.tuple([z.number(), z.number()]), | ||
| }) | ||
| ), | ||
| relationships: z.array(RelationshipSchema), | ||
| }); | ||
|
|
||
| export type StaticModel = Omit< | ||
| z.output<typeof StaticModelSchema>, | ||
| 'collections' | ||
| > & { | ||
| collections: Array< | ||
| Omit< | ||
| z.output<typeof StaticModelSchema>['collections'][number], | ||
| 'jsonSchema' | ||
| > & { | ||
| jsonSchema: MongoDBJSONSchema; | ||
| } | ||
| >; | ||
| }; | ||
|
|
||
| export const EditSchema = z.discriminatedUnion('type', [ | ||
| z.object({ | ||
| type: z.literal('SetModel'), | ||
| id: z.string(), | ||
| timestamp: z.string(), | ||
paula-stacho marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| model: StaticModelSchema, | ||
| }), | ||
| z.object({ | ||
| type: z.literal('AddRelationship'), | ||
| id: z.string(), | ||
paula-stacho marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| timestamp: z.string(), | ||
| relationship: RelationshipSchema, | ||
| }), | ||
| z.object({ | ||
| type: z.literal('RemoveRelationship'), | ||
| id: z.string(), | ||
| timestamp: z.string(), | ||
| relationshipId: z.string(), | ||
| }), | ||
| ]); | ||
|
|
||
| type BaseEdit = z.output<typeof EditSchema>; | ||
| type SetModelEdit = Omit<Extract<BaseEdit, { type: 'SetModel' }>, 'model'> & { | ||
| model: StaticModel; | ||
| }; | ||
|
|
||
| export type Edit = | ||
| | SetModelEdit | ||
| | Extract<BaseEdit, { type: 'AddRelationship' | 'RemoveRelationship' }>; | ||
|
|
||
| export const validateEdit = ( | ||
| edit: unknown | ||
| ): { result: true; errors?: never } | { result: false; errors: string[] } => { | ||
| try { | ||
| EditSchema.parse(edit); | ||
| return { result: true }; | ||
| } catch (e) { | ||
| return { | ||
| result: false, | ||
| errors: (e as z.ZodError).issues.map(({ path, message }) => | ||
| message === 'Required' | ||
| ? `'${path}' is required` | ||
| : `Invalid field '${path}': ${message}` | ||
| ), | ||
| }; | ||
| } | ||
| }; | ||
|
|
||
| export const MongoDBDataModelDescriptionSchema = z.object({ | ||
| id: z.string(), | ||
|
|
@@ -11,13 +103,15 @@ export const MongoDBDataModelDescriptionSchema = z.object({ | |
| */ | ||
| connectionId: z.string().nullable(), | ||
|
|
||
| // TODO: define rest of the schema based on arch doc / tech design | ||
| edits: z.array(z.unknown()).default([]), | ||
| edits: z.array(EditSchema).default([]), | ||
| }); | ||
|
|
||
| export type MongoDBDataModelDescription = z.output< | ||
| typeof MongoDBDataModelDescriptionSchema | ||
| >; | ||
| export type MongoDBDataModelDescription = Omit< | ||
| z.output<typeof MongoDBDataModelDescriptionSchema>, | ||
| 'edits' | ||
| > & { | ||
| edits: Array<Edit>; | ||
| }; | ||
|
|
||
| export interface DataModelStorage { | ||
| save(description: MongoDBDataModelDescription): Promise<boolean>; | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.