Skip to content

Commit

Permalink
feat: prevent immutable fields from being updated at runtime
Browse files Browse the repository at this point in the history
  • Loading branch information
JulissaDantes committed Feb 6, 2024
1 parent c0e7841 commit 60e1584
Show file tree
Hide file tree
Showing 4 changed files with 32 additions and 234 deletions.
9 changes: 5 additions & 4 deletions packages/runtime/src/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -528,10 +528,10 @@ class SchemaBuilder {
},
}
for (const [key, field] of Object.entries(fields)) {
// Don't show meta or immutable fields in schema
if (field.type == 'meta' || (field as any).immutable) continue

switch (field.type) {
case 'meta':
// Don't show meta fields in schema
continue
case 'reference':
config[key] = this._buildDocumentObjectReferenceField(key, field)
break
Expand Down Expand Up @@ -945,7 +945,7 @@ class SchemaBuilder {
const inputPrefix = isDocument || required ? '' : 'Partial'

for (const [key, field] of Object.entries(fields)) {
let type
let type//TODO should it also go here?
switch (field.type) {
case 'meta':
case 'view':
Expand Down Expand Up @@ -1077,6 +1077,7 @@ class SchemaBuilder {
name: string,
model: RuntimeModel,
) {
console.trace("i came here")
switch (model.accountRelation.type) {
case 'list':
this.#mutations[`create${name}`] = mutationWithClientMutationId({
Expand Down
216 changes: 0 additions & 216 deletions packages/runtime/test/__snapshots__/runtime.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -1115,221 +1115,6 @@ exports[`runtime create and query ratings with filters and ordering 3`] = `
}
`;

exports[`runtime immutable operations TODO update this test name 1`] = `
"type Query {
"""Fetches objects given their IDs"""
nodes(
"""The IDs of objects"""
ids: [ID!]!
): [Node]!
"""Fetches an object given its ID"""
node(
"""The ID of an object"""
id: ID!
): Node
"""Account currently authenticated on the Ceramic instance, if set"""
viewer: CeramicAccount
postIndex(
"""Returns the items in the list that come after the specified cursor."""
after: String
"""Returns the first n items from the list."""
first: Int
"""Returns the items in the list that come before the specified cursor."""
before: String
"""Returns the last n items from the list."""
last: Int
filters: PostFiltersInput
sorting: PostSortingInput
): PostConnection
postCount(filters: PostFiltersInput): Int!
}
"""An object with an ID"""
interface Node {
"""The id of the object."""
id: ID!
}
type CeramicAccount implements Node {
"""Globally unique identifier of the account (DID string)"""
id: ID!
"""
Whether the Ceramic instance is currently authenticated with this account or not
"""
isViewer: Boolean!
postList(
"""Returns the items in the list that come after the specified cursor."""
after: String
"""Returns the first n items from the list."""
first: Int
"""Returns the items in the list that come before the specified cursor."""
before: String
"""Returns the last n items from the list."""
last: Int
filters: PostFiltersInput
sorting: PostSortingInput
): PostConnection
postListCount(filters: PostFiltersInput): Int!
}
"""A connection to a list of items."""
type PostConnection {
"""Information to aid in pagination."""
pageInfo: PageInfo!
"""A list of edges."""
edges: [PostEdge]
}
"""Information about pagination in a connection."""
type PageInfo {
"""When paginating forwards, are there more items?"""
hasNextPage: Boolean!
"""When paginating backwards, are there more items?"""
hasPreviousPage: Boolean!
"""When paginating backwards, the cursor to continue."""
startCursor: String
"""When paginating forwards, the cursor to continue."""
endCursor: String
}
"""An edge in a connection."""
type PostEdge {
"""The item at the end of the edge"""
node: Post
"""A cursor for use in pagination"""
cursor: String!
}
type Post implements Node {
id: ID!
date: DateTime
text: String!
title: String!
"""Account controlling the document"""
author: CeramicAccount!
}
"""
A date-time string at UTC, such as 2007-12-03T10:15:30Z, compliant with the \`date-time\` format outlined in section 5.6 of the RFC 3339 profile of the ISO 8601 standard for representation of dates and times using the Gregorian calendar.
"""
scalar DateTime
input PostFiltersInput {
where: PostObjectFilterInput
and: [PostFiltersInput!]
or: [PostFiltersInput!]
not: PostFiltersInput
}
input PostObjectFilterInput {
title: StringValueFilterInput
}
input StringValueFilterInput {
isNull: Boolean
equalTo: String
notEqualTo: String
in: [String!]
notIn: [String!]
lessThan: String
lessThanOrEqualTo: String
greaterThan: String
greaterThanOrEqualTo: String
}
input PostSortingInput {
title: SortOrder
}
enum SortOrder {
ASC
DESC
}
type Mutation {
createPost(input: CreatePostInput!): CreatePostPayload
updatePost(input: UpdatePostInput!): UpdatePostPayload
}
type CreatePostPayload {
"""Fetches an object given its ID"""
node(
"""The ID of an object"""
id: ID!
): Node
"""Account currently authenticated on the Ceramic instance, if set"""
viewer: CeramicAccount
document: Post!
clientMutationId: String
}
input CreatePostInput {
content: PostInput!
clientMutationId: String
}
input PostInput {
date: DateTime
text: String!
title: String!
}
type UpdatePostPayload {
"""Fetches an object given its ID"""
node(
"""The ID of an object"""
id: ID!
): Node
"""Account currently authenticated on the Ceramic instance, if set"""
viewer: CeramicAccount
document: Post!
clientMutationId: String
}
input UpdatePostInput {
id: ID!
content: PartialPostInput!
options: UpdateOptionsInput
clientMutationId: String
}
input PartialPostInput {
date: DateTime
text: String
title: String
}
input UpdateOptionsInput {
"""
Fully replace the document contents instead of performing a shallow merge
"""
replace: Boolean = false
"""Only perform mutation if the document matches the provided version"""
version: CeramicCommitID
}
"""A Ceramic Commit ID"""
scalar CeramicCommitID @specifiedBy(url: "https://cips.ceramic.network/CIPs/cip-59#commitid")"
`;

exports[`runtime interfaces queries 1`] = `
{
"data": {
Expand Down Expand Up @@ -1699,7 +1484,6 @@ type Post implements Node {
id: ID!
date: DateTime
text: String!
title: String!
"""Account controlling the document"""
author: CeramicAccount!
Expand Down
40 changes: 27 additions & 13 deletions packages/runtime/test/runtime.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -813,7 +813,7 @@ describe('runtime', () => {
expect(favorite2Res.data).toMatchSnapshot()
})

test.only('runtime operations on models with immutable field', async () => {
test('runtime operations on models with immutable field', async () => {
const postWithImmutableFieldSchema = `
type Post
@createModel(accountRelation: LIST, description: "Simple post with immutable field")
Expand All @@ -826,12 +826,11 @@ describe('runtime', () => {
`
const composite = await Composite.create({ ceramic, schema: postWithImmutableFieldSchema })
const definition = composite.toRuntime()

expect(printGraphQLSchema(definition)).toMatchSnapshot()

const runtime = new ComposeRuntime({ ceramic, definition })

// can create record with immutable field
const createPostMutation = `
mutation CreatePost($input: CreatePostInput!) {
createPost(input: $input) {
Expand All @@ -841,18 +840,33 @@ describe('runtime', () => {
}
}
`
const postRes = await runtime.executeQuery(createPostMutation, {
input: { content: { title: 'A first post', text: 'First post content', date: '2024-01-01T10:15:30Z' } },

const res = await runtime.executeQuery(createPostMutation, {
input: {
content: {
title: 'A first post',
text: 'First post content',
date: '2024-01-01T10:15:30Z',
},
},
})
const doc = res.data?.createPost.document
expect(doc.id).toBeDefined()

/*
const postID = postRes.data?.createPost.document.id
expect(postID).toBeDefined()*/

// can read record with immutable field

// cannot update immutable field
const updatePost = `mutation UpdatePost($i: UpdatePostInput!) {
updatePost(input: $i) {
document {
id
title
text
}
}
}`

const res2 = await runtime.executeQuery(updatePost, {
input: { id: doc.id, content: { title: 'A different title' } },
})

expect(true)

}, 60000)
})
1 change: 0 additions & 1 deletion packages/types/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,6 @@ export type RuntimeModel = {
implements: Array<string>
accountRelation: ModelAccountRelationV2
immutableFields?: Array<string>

}

/**
Expand Down

0 comments on commit 60e1584

Please sign in to comment.