This PR was opened by the Changesets release GitHub action. When you're ready to do a release, you can merge this and publish to npm yourself or setup this action to publish automatically. If you're not ready to do a release yet, that's fine, whenever you add more changesets to main, this PR will be updated.
Releases
next-tinacms-cloudinary@2.0.0
Minor Changes
7e8f414e: contextual error messages in media library
Patch Changes
Updated dependencies [d42e2bcf]
Updated dependencies [ab4e388b]
Updated dependencies [7351d92f]
Updated dependencies [95244e14]
tina-graphql-gateway@0.4.0
tina-graphql@0.2.0
Minor Changes
7351d92f: # Define schema changes
We're going to be leaning on a more primitive concept of how types are defined with Tina, and in doing so will be introducing some breaking changes to the way schemas are defined. Read the detailed RFC discussion for more on this topic, specifically the latter portions of the discussion.
Collections now accept a fieldsortemplates property
You can now provide fields instead of templates for your collection, doing so will result in a more straightforward schema definition:
{
collections: [
{
name: 'post',
label: 'Post',
path: 'content/posts',
fields: [
{
name: 'title',
label: 'Title',
type: 'string', // read on below to learn more about _type_ changes
},
],
// defining `fields` and `templates` would result in a compilation error
},
]
}
Why?
Previously, a collection could define multiple templates, the ambiguity introduced with this feature meant that your documents needed a _template field on them so we'd know which one they belonged to. It also mean having to disambiguate your queries in graphql:
getPostDocument(relativePage: $relativePath) {
data {
...on Article_Doc_Data {
title
}
}
}
Going forward, if you use fields on a collection, you can omit the _template key and simplify your query:
getPostDocument(relativePage: $relativePath) {
data {
title
}
}
type changes
Types will look a little bit different, and are meant to reflect the lowest form of the shape they can represent. Moving forward, the ui field will represent the UI portion of what you might expect. For a blog post "description" field, you'd define it like this:
For the most part, the UI properties are added to the field and adhere to the existing capabilities of Tina's core field plugins. But there's nothing stopping you from providing your own components -- just be sure to register those with the CMS object on the frontend:
Every property in the defineSchema API must be serlializable. Meaning functions will not work. For example, there's no way to define a validate or parse function at this level. However, you can either use the formify API to get access to the Tina form, or provide your own logic by specifying a plugin of your choice:
And then when you register the plugin, provide your custom logic here:
import { TextFieldPlugin } from 'tinacms'
// ...
cms.fields.add({
...TextFieldPlugin, // spread existing text plugin
name: 'myText',
validate: value => {
someValidationLogic(value)
},
})
Why?
The reality is that under the hood this has made no difference to the backend, so we're removing it as a point of friction. Instead, type is the true definition of the field's shape, while ui can be used for customizing the look and behavior of the field's UI.
Defensive coding in Tina
When working with GraphQL, there are 2 reasons a property may not be present.
The data is not a required property. That is to say, if I have a blog post document, and "category" is an optional field, we'll need to make sure we factor that into how we render our page:
But with Tina, there's a 3rd scenario: the document may be in an invalid state. Meaning, we could mark the field as requiredand query for the appropriate field, and still not have the expected shape of data. Due to the contextual nature of Tina, it's very common to be in an intermediate state, where your data is incomplete simply because you're still working on it. Most APIs would throw an error when a document is in an invalid state. Or, more likely, you couldn't even request it.
Undefined list fields will return null
Previously an listable field which wasn't defined in the document was treated as an emptry array. So for example:
---
title: 'Hello, World'
categories:
- sports
- movies
---
The responsee would be categories: ['sports', 'movies']. If you omit the items, but kept the empty array:
---
title: 'Hello, World'
categories: []
---
The responsee would be categories: []. If you omit the field entirely:
---
title: 'Hello, World'
---
The response will be categories: null. Previously this would have been [], which was incorrect.
For a listable item which is required: true you must provide a ui.defaultItem property
Why?
It's possible for Tina's editing capabilities to introduce an invalid state during edits to list items. Imagine the scenario where you are iterating through an array of objects, and each object has a categories array on it we'd like to render:
For a new item, categories will be null, so we'll get an error. This only happens when you're editing your page with Tina, so it's not a production-facing issue.
Every type can be a list
Previously, we had a list field, which allowed you to supply a field property. Instead, every primitive type can be represented as a list:
Note we may introduce an enum type, but haven't discussed it thoroughly
Introducing the object type
Tina currently represents the concept of an object in two ways: a group (and group-list), which is a uniform collection of fields; and blocks, which is a polymporphic collection. Moving forward, we'll be introducing a more comporehensive type, which envelopes the behavior of both group and blocks, and since every field can be a list, this also makes group-list redundant.
Note: we've previously assumed that blocks usage would always be as an array. We'll be keeping that assumption with the blocks type for compatibility, but object will allow for non-array polymorphic objects.
Defining an object type
An object type takes either a fieldsortemplates property (just like the collections definition). If you supply fields, you'll end up with what is essentially a group item. And if you say list: true, you'll have what used to be a group-list definition.
Likewise, if you supply a templates field and list: true, you'll get the same API as blocks. However you can also say list: false (or omit it entirely), and you'll have a polymorphic object which is not an array.
This is identical to the current blocks definition:
You can now request dataJSON for the entire data object as a single query key. This is great for more tedius queries like theme files where including each item in the result is cumbersome.
Note there is no typescript help for this feature for now
The GraphQL connection spec opens up a more future-proof structure, allowing us to put more information in to the connection itself like how many results have been returned, and how to request the next page of data.
Read a detailed explanation of how the connection spec provides a richer set of capabilities.
Note: sorting and filtering is still not supported for list queries.
_body is no longer included by default
There is instead an isBody boolean which can be added to any string field
Why?
Since markdown files sort of have an implicit "body" to them, we were automatically populating a field which represented the body of your markdown file. This wasn't that useful, and kind of annoying. Instead, just attach isBody to the field which you want to represent your markdown "body":
They now include the proper namespace to prevent naming collisions and no longer require _Doc_Data suffix. All generated __typename properties are going to be slightly different. We weren't fully namespacing fields so it wasn't possible to guarantee that no collisions would occur. The pain felt here will likely be most seen when querying and filtering through blocks. This ensures the stability of this type in the future
{
getPageDocument(relativePath: "home.md") {
data {
title
myBlocks {
...on Page_Hero_Data { # previously this would have been Hero_Data
# ...
}
}
}
}
Patch Changes
fdb7724b: Fix stringify for json extensions
d42e2bcf: Adds number, datetime, and boolean fields back into primitive field generators
5cd5ce76: - Improve types for ui field
Marks system fields as required so the user has a guarantee that they'll be there
Return null for listable fields which are null or undefined
Handle null values for reference fields better
8c425440: Remmove accidental additional of dataJSON in schema
Updated dependencies [7351d92f]
tina-graphql-helpers@0.1.2
tina-graphql-gateway@0.4.0
Minor Changes
ab4e388b: Updates where LoadingDots is imported from
7351d92f: # Define schema changes
We're going to be leaning on a more primitive concept of how types are defined with Tina, and in doing so will be introducing some breaking changes to the way schemas are defined. Read the detailed RFC discussion for more on this topic, specifically the latter portions of the discussion.
Collections now accept a fieldsortemplates property
You can now provide fields instead of templates for your collection, doing so will result in a more straightforward schema definition:
{
collections: [
{
name: 'post',
label: 'Post',
path: 'content/posts',
fields: [
{
name: 'title',
label: 'Title',
type: 'string', // read on below to learn more about _type_ changes
},
],
// defining `fields` and `templates` would result in a compilation error
},
]
}
Why?
Previously, a collection could define multiple templates, the ambiguity introduced with this feature meant that your documents needed a _template field on them so we'd know which one they belonged to. It also mean having to disambiguate your queries in graphql:
getPostDocument(relativePage: $relativePath) {
data {
...on Article_Doc_Data {
title
}
}
}
Going forward, if you use fields on a collection, you can omit the _template key and simplify your query:
getPostDocument(relativePage: $relativePath) {
data {
title
}
}
type changes
Types will look a little bit different, and are meant to reflect the lowest form of the shape they can represent. Moving forward, the ui field will represent the UI portion of what you might expect. For a blog post "description" field, you'd define it like this:
For the most part, the UI properties are added to the field and adhere to the existing capabilities of Tina's core field plugins. But there's nothing stopping you from providing your own components -- just be sure to register those with the CMS object on the frontend:
Every property in the defineSchema API must be serlializable. Meaning functions will not work. For example, there's no way to define a validate or parse function at this level. However, you can either use the formify API to get access to the Tina form, or provide your own logic by specifying a plugin of your choice:
And then when you register the plugin, provide your custom logic here:
import { TextFieldPlugin } from 'tinacms'
// ...
cms.fields.add({
...TextFieldPlugin, // spread existing text plugin
name: 'myText',
validate: value => {
someValidationLogic(value)
},
})
Why?
The reality is that under the hood this has made no difference to the backend, so we're removing it as a point of friction. Instead, type is the true definition of the field's shape, while ui can be used for customizing the look and behavior of the field's UI.
Defensive coding in Tina
When working with GraphQL, there are 2 reasons a property may not be present.
The data is not a required property. That is to say, if I have a blog post document, and "category" is an optional field, we'll need to make sure we factor that into how we render our page:
But with Tina, there's a 3rd scenario: the document may be in an invalid state. Meaning, we could mark the field as requiredand query for the appropriate field, and still not have the expected shape of data. Due to the contextual nature of Tina, it's very common to be in an intermediate state, where your data is incomplete simply because you're still working on it. Most APIs would throw an error when a document is in an invalid state. Or, more likely, you couldn't even request it.
Undefined list fields will return null
Previously an listable field which wasn't defined in the document was treated as an emptry array. So for example:
---
title: 'Hello, World'
categories:
- sports
- movies
---
The responsee would be categories: ['sports', 'movies']. If you omit the items, but kept the empty array:
---
title: 'Hello, World'
categories: []
---
The responsee would be categories: []. If you omit the field entirely:
---
title: 'Hello, World'
---
The response will be categories: null. Previously this would have been [], which was incorrect.
For a listable item which is required: true you must provide a ui.defaultItem property
Why?
It's possible for Tina's editing capabilities to introduce an invalid state during edits to list items. Imagine the scenario where you are iterating through an array of objects, and each object has a categories array on it we'd like to render:
For a new item, categories will be null, so we'll get an error. This only happens when you're editing your page with Tina, so it's not a production-facing issue.
Every type can be a list
Previously, we had a list field, which allowed you to supply a field property. Instead, every primitive type can be represented as a list:
Note we may introduce an enum type, but haven't discussed it thoroughly
Introducing the object type
Tina currently represents the concept of an object in two ways: a group (and group-list), which is a uniform collection of fields; and blocks, which is a polymporphic collection. Moving forward, we'll be introducing a more comporehensive type, which envelopes the behavior of both group and blocks, and since every field can be a list, this also makes group-list redundant.
Note: we've previously assumed that blocks usage would always be as an array. We'll be keeping that assumption with the blocks type for compatibility, but object will allow for non-array polymorphic objects.
Defining an object type
An object type takes either a fieldsortemplates property (just like the collections definition). If you supply fields, you'll end up with what is essentially a group item. And if you say list: true, you'll have what used to be a group-list definition.
Likewise, if you supply a templates field and list: true, you'll get the same API as blocks. However you can also say list: false (or omit it entirely), and you'll have a polymorphic object which is not an array.
This is identical to the current blocks definition:
You can now request dataJSON for the entire data object as a single query key. This is great for more tedius queries like theme files where including each item in the result is cumbersome.
Note there is no typescript help for this feature for now
The GraphQL connection spec opens up a more future-proof structure, allowing us to put more information in to the connection itself like how many results have been returned, and how to request the next page of data.
Read a detailed explanation of how the connection spec provides a richer set of capabilities.
Note: sorting and filtering is still not supported for list queries.
_body is no longer included by default
There is instead an isBody boolean which can be added to any string field
Why?
Since markdown files sort of have an implicit "body" to them, we were automatically populating a field which represented the body of your markdown file. This wasn't that useful, and kind of annoying. Instead, just attach isBody to the field which you want to represent your markdown "body":
They now include the proper namespace to prevent naming collisions and no longer require _Doc_Data suffix. All generated __typename properties are going to be slightly different. We weren't fully namespacing fields so it wasn't possible to guarantee that no collisions would occur. The pain felt here will likely be most seen when querying and filtering through blocks. This ensures the stability of this type in the future
{
getPageDocument(relativePath: "home.md") {
data {
title
myBlocks {
...on Page_Hero_Data { # previously this would have been Hero_Data
# ...
}
}
}
}
Patch Changes
d42e2bcf: Adds number, datetime, and boolean fields back into primitive field generators
95244e14: Early return for query nodes which can't be formified
Updated dependencies [7351d92f]
tina-graphql-helpers@0.1.2
tina-graphql-gateway-cli@0.4.0
Minor Changes
7351d92f: # Define schema changes
We're going to be leaning on a more primitive concept of how types are defined with Tina, and in doing so will be introducing some breaking changes to the way schemas are defined. Read the detailed RFC discussion for more on this topic, specifically the latter portions of the discussion.
Collections now accept a fieldsortemplates property
You can now provide fields instead of templates for your collection, doing so will result in a more straightforward schema definition:
{
collections: [
{
name: 'post',
label: 'Post',
path: 'content/posts',
fields: [
{
name: 'title',
label: 'Title',
type: 'string', // read on below to learn more about _type_ changes
},
],
// defining `fields` and `templates` would result in a compilation error
},
]
}
Why?
Previously, a collection could define multiple templates, the ambiguity introduced with this feature meant that your documents needed a _template field on them so we'd know which one they belonged to. It also mean having to disambiguate your queries in graphql:
getPostDocument(relativePage: $relativePath) {
data {
...on Article_Doc_Data {
title
}
}
}
Going forward, if you use fields on a collection, you can omit the _template key and simplify your query:
getPostDocument(relativePage: $relativePath) {
data {
title
}
}
type changes
Types will look a little bit different, and are meant to reflect the lowest form of the shape they can represent. Moving forward, the ui field will represent the UI portion of what you might expect. For a blog post "description" field, you'd define it like this:
For the most part, the UI properties are added to the field and adhere to the existing capabilities of Tina's core field plugins. But there's nothing stopping you from providing your own components -- just be sure to register those with the CMS object on the frontend:
Every property in the defineSchema API must be serlializable. Meaning functions will not work. For example, there's no way to define a validate or parse function at this level. However, you can either use the formify API to get access to the Tina form, or provide your own logic by specifying a plugin of your choice:
And then when you register the plugin, provide your custom logic here:
import { TextFieldPlugin } from 'tinacms'
// ...
cms.fields.add({
...TextFieldPlugin, // spread existing text plugin
name: 'myText',
validate: value => {
someValidationLogic(value)
},
})
Why?
The reality is that under the hood this has made no difference to the backend, so we're removing it as a point of friction. Instead, type is the true definition of the field's shape, while ui can be used for customizing the look and behavior of the field's UI.
Defensive coding in Tina
When working with GraphQL, there are 2 reasons a property may not be present.
The data is not a required property. That is to say, if I have a blog post document, and "category" is an optional field, we'll need to make sure we factor that into how we render our page:
But with Tina, there's a 3rd scenario: the document may be in an invalid state. Meaning, we could mark the field as requiredand query for the appropriate field, and still not have the expected shape of data. Due to the contextual nature of Tina, it's very common to be in an intermediate state, where your data is incomplete simply because you're still working on it. Most APIs would throw an error when a document is in an invalid state. Or, more likely, you couldn't even request it.
Undefined list fields will return null
Previously an listable field which wasn't defined in the document was treated as an emptry array. So for example:
---
title: 'Hello, World'
categories:
- sports
- movies
---
The responsee would be categories: ['sports', 'movies']. If you omit the items, but kept the empty array:
---
title: 'Hello, World'
categories: []
---
The responsee would be categories: []. If you omit the field entirely:
---
title: 'Hello, World'
---
The response will be categories: null. Previously this would have been [], which was incorrect.
For a listable item which is required: true you must provide a ui.defaultItem property
Why?
It's possible for Tina's editing capabilities to introduce an invalid state during edits to list items. Imagine the scenario where you are iterating through an array of objects, and each object has a categories array on it we'd like to render:
For a new item, categories will be null, so we'll get an error. This only happens when you're editing your page with Tina, so it's not a production-facing issue.
Every type can be a list
Previously, we had a list field, which allowed you to supply a field property. Instead, every primitive type can be represented as a list:
Note we may introduce an enum type, but haven't discussed it thoroughly
Introducing the object type
Tina currently represents the concept of an object in two ways: a group (and group-list), which is a uniform collection of fields; and blocks, which is a polymporphic collection. Moving forward, we'll be introducing a more comporehensive type, which envelopes the behavior of both group and blocks, and since every field can be a list, this also makes group-list redundant.
Note: we've previously assumed that blocks usage would always be as an array. We'll be keeping that assumption with the blocks type for compatibility, but object will allow for non-array polymorphic objects.
Defining an object type
An object type takes either a fieldsortemplates property (just like the collections definition). If you supply fields, you'll end up with what is essentially a group item. And if you say list: true, you'll have what used to be a group-list definition.
Likewise, if you supply a templates field and list: true, you'll get the same API as blocks. However you can also say list: false (or omit it entirely), and you'll have a polymorphic object which is not an array.
This is identical to the current blocks definition:
You can now request dataJSON for the entire data object as a single query key. This is great for more tedius queries like theme files where including each item in the result is cumbersome.
Note there is no typescript help for this feature for now
The GraphQL connection spec opens up a more future-proof structure, allowing us to put more information in to the connection itself like how many results have been returned, and how to request the next page of data.
Read a detailed explanation of how the connection spec provides a richer set of capabilities.
Note: sorting and filtering is still not supported for list queries.
_body is no longer included by default
There is instead an isBody boolean which can be added to any string field
Why?
Since markdown files sort of have an implicit "body" to them, we were automatically populating a field which represented the body of your markdown file. This wasn't that useful, and kind of annoying. Instead, just attach isBody to the field which you want to represent your markdown "body":
They now include the proper namespace to prevent naming collisions and no longer require _Doc_Data suffix. All generated __typename properties are going to be slightly different. We weren't fully namespacing fields so it wasn't possible to guarantee that no collisions would occur. The pain felt here will likely be most seen when querying and filtering through blocks. This ensures the stability of this type in the future
{
getPageDocument(relativePath: "home.md") {
data {
title
myBlocks {
...on Page_Hero_Data { # previously this would have been Hero_Data
# ...
}
}
}
}
33e27538: Init command now adds admin.tsx file to the users pages folder
8c8fc2ad: Init script now checks for file extention.
Patch Changes
5cd5ce76: - Improve types for ui field
Marks system fields as required so the user has a guarantee that they'll be there
Return null for listable fields which are null or undefined
Handle null values for reference fields better
Updated dependencies [fdb7724b]
Updated dependencies [d42e2bcf]
Updated dependencies [5cd5ce76]
Updated dependencies [8c425440]
Updated dependencies [7351d92f]
tina-graphql@0.2.0
tina-graphql-helpers@0.1.2
tina-graphql-helpers@0.1.2
Patch Changes
7351d92f: # Define schema changes
We're going to be leaning on a more primitive concept of how types are defined with Tina, and in doing so will be introducing some breaking changes to the way schemas are defined. Read the detailed RFC discussion for more on this topic, specifically the latter portions of the discussion.
Collections now accept a fieldsortemplates property
You can now provide fields instead of templates for your collection, doing so will result in a more straightforward schema definition:
{
collections: [
{
name: 'post',
label: 'Post',
path: 'content/posts',
fields: [
{
name: 'title',
label: 'Title',
type: 'string', // read on below to learn more about _type_ changes
},
],
// defining `fields` and `templates` would result in a compilation error
},
]
}
Why?
Previously, a collection could define multiple templates, the ambiguity introduced with this feature meant that your documents needed a _template field on them so we'd know which one they belonged to. It also mean having to disambiguate your queries in graphql:
getPostDocument(relativePage: $relativePath) {
data {
...on Article_Doc_Data {
title
}
}
}
Going forward, if you use fields on a collection, you can omit the _template key and simplify your query:
getPostDocument(relativePage: $relativePath) {
data {
title
}
}
type changes
Types will look a little bit different, and are meant to reflect the lowest form of the shape they can represent. Moving forward, the ui field will represent the UI portion of what you might expect. For a blog post "description" field, you'd define it like this:
For the most part, the UI properties are added to the field and adhere to the existing capabilities of Tina's core field plugins. But there's nothing stopping you from providing your own components -- just be sure to register those with the CMS object on the frontend:
Every property in the defineSchema API must be serlializable. Meaning functions will not work. For example, there's no way to define a validate or parse function at this level. However, you can either use the formify API to get access to the Tina form, or provide your own logic by specifying a plugin of your choice:
And then when you register the plugin, provide your custom logic here:
import { TextFieldPlugin } from 'tinacms'
// ...
cms.fields.add({
...TextFieldPlugin, // spread existing text plugin
name: 'myText',
validate: value => {
someValidationLogic(value)
},
})
Why?
The reality is that under the hood this has made no difference to the backend, so we're removing it as a point of friction. Instead, type is the true definition of the field's shape, while ui can be used for customizing the look and behavior of the field's UI.
Defensive coding in Tina
When working with GraphQL, there are 2 reasons a property may not be present.
The data is not a required property. That is to say, if I have a blog post document, and "category" is an optional field, we'll need to make sure we factor that into how we render our page:
But with Tina, there's a 3rd scenario: the document may be in an invalid state. Meaning, we could mark the field as requiredand query for the appropriate field, and still not have the expected shape of data. Due to the contextual nature of Tina, it's very common to be in an intermediate state, where your data is incomplete simply because you're still working on it. Most APIs would throw an error when a document is in an invalid state. Or, more likely, you couldn't even request it.
Undefined list fields will return null
Previously an listable field which wasn't defined in the document was treated as an emptry array. So for example:
---
title: 'Hello, World'
categories:
- sports
- movies
---
The responsee would be categories: ['sports', 'movies']. If you omit the items, but kept the empty array:
---
title: 'Hello, World'
categories: []
---
The responsee would be categories: []. If you omit the field entirely:
---
title: 'Hello, World'
---
The response will be categories: null. Previously this would have been [], which was incorrect.
For a listable item which is required: true you must provide a ui.defaultItem property
Why?
It's possible for Tina's editing capabilities to introduce an invalid state during edits to list items. Imagine the scenario where you are iterating through an array of objects, and each object has a categories array on it we'd like to render:
For a new item, categories will be null, so we'll get an error. This only happens when you're editing your page with Tina, so it's not a production-facing issue.
Every type can be a list
Previously, we had a list field, which allowed you to supply a field property. Instead, every primitive type can be represented as a list:
Note we may introduce an enum type, but haven't discussed it thoroughly
Introducing the object type
Tina currently represents the concept of an object in two ways: a group (and group-list), which is a uniform collection of fields; and blocks, which is a polymporphic collection. Moving forward, we'll be introducing a more comporehensive type, which envelopes the behavior of both group and blocks, and since every field can be a list, this also makes group-list redundant.
Note: we've previously assumed that blocks usage would always be as an array. We'll be keeping that assumption with the blocks type for compatibility, but object will allow for non-array polymorphic objects.
Defining an object type
An object type takes either a fieldsortemplates property (just like the collections definition). If you supply fields, you'll end up with what is essentially a group item. And if you say list: true, you'll have what used to be a group-list definition.
Likewise, if you supply a templates field and list: true, you'll get the same API as blocks. However you can also say list: false (or omit it entirely), and you'll have a polymorphic object which is not an array.
This is identical to the current blocks definition:
You can now request dataJSON for the entire data object as a single query key. This is great for more tedius queries like theme files where including each item in the result is cumbersome.
Note there is no typescript help for this feature for now
The GraphQL connection spec opens up a more future-proof structure, allowing us to put more information in to the connection itself like how many results have been returned, and how to request the next page of data.
Read a detailed explanation of how the connection spec provides a richer set of capabilities.
Note: sorting and filtering is still not supported for list queries.
_body is no longer included by default
There is instead an isBody boolean which can be added to any string field
Why?
Since markdown files sort of have an implicit "body" to them, we were automatically populating a field which represented the body of your markdown file. This wasn't that useful, and kind of annoying. Instead, just attach isBody to the field which you want to represent your markdown "body":
They now include the proper namespace to prevent naming collisions and no longer require _Doc_Data suffix. All generated __typename properties are going to be slightly different. We weren't fully namespacing fields so it wasn't possible to guarantee that no collisions would occur. The pain felt here will likely be most seen when querying and filtering through blocks. This ensures the stability of this type in the future
{
getPageDocument(relativePath: "home.md") {
data {
title
myBlocks {
...on Page_Hero_Data { # previously this would have been Hero_Data
# ...
}
}
}
}
tina-cloud-starter@0.2.0
Minor Changes
7e8f414e: contextual error messages in media library
Patch Changes
Updated dependencies [d42e2bcf]
Updated dependencies [7e8f414e]
Updated dependencies [ab4e388b]
Updated dependencies [7351d92f]
Updated dependencies [95244e14]
tina-graphql-gateway@0.4.0
next-tinacms-cloudinary@2.0.0
demo@0.1.6
Patch Changes
Updated dependencies [fdb7724b]
Updated dependencies [d42e2bcf]
Updated dependencies [5cd5ce76]
Updated dependencies [ab4e388b]
Updated dependencies [8c425440]
Updated dependencies [7351d92f]
Updated dependencies [95244e14]
tina-graphql@0.2.0
tina-graphql-gateway@0.4.0
tina-graphql-helpers@0.1.2
test@0.1.6
Patch Changes
Updated dependencies [fdb7724b]
Updated dependencies [d42e2bcf]
Updated dependencies [5cd5ce76]
Updated dependencies [ab4e388b]
Updated dependencies [8c425440]
Updated dependencies [7351d92f]
Updated dependencies [95244e14]
tina-graphql@0.2.0
tina-graphql-gateway@0.4.0
tina-graphql-helpers@0.1.2
tina-cloud-starter-experimental@0.1.1
Patch Changes
d42e2bcf: Adds number, datetime, and boolean fields back into primitive field generators
7351d92f: # Define schema changes
We're going to be leaning on a more primitive concept of how types are defined with Tina, and in doing so will be introducing some breaking changes to the way schemas are defined. Read the detailed RFC discussion for more on this topic, specifically the latter portions of the discussion.
Collections now accept a fieldsortemplates property
You can now provide fields instead of templates for your collection, doing so will result in a more straightforward schema definition:
{
collections: [{
name: "post",
label: "Post",
path: "content/posts",
fields: [
{
name: "title",
label: "Title",
type: "string" // read on below to learn more about _type_ changes
}
]
// defining `fields` and `templates` would result in a compilation error
}]
}
Why?
Previously, a collection could define multiple templates, the ambiguity introduced with this feature meant that your documents needed a _template field on them so we'd know which one they belonged to. It also mean having to disambiguate your queries in graphql:
getPostDocument(relativePage: $relativePath) {
data {
...on Article_Doc_Data {
title
}
}
}
Going forward, if you use fields on a collection, you can omit the _template key and simplify your query:
getPostDocument(relativePage: $relativePath) {
data {
title
}
}
type changes
Types will look a little bit different, and are meant to reflect the lowest form of the shape they can represent. Moving forward, the ui field will represent the UI portion of what you might expect. For a blog post "description" field, you'd define it like this:
For the most part, the UI properties are added to the field and adhere to the existing capabilities of Tina's core field plugins. But there's nothing stopping you from providing your own components -- just be sure to register those with the CMS object on the frontend:
Every property in the defineSchema API must be serlializable. Meaning functions will not work. For example, there's no way to define a validate or parse function at this level. However, you can either use the formify API to get access to the Tina form, or provide your own logic by specifying a plugin of your choice:
The reality is that under the hood this has made no difference to the backend, so we're removing it as a point of friction. Instead, type is the true definition of the field's shape, while ui can be used for customizing the look and behavior of the field's UI.
Defensive coding in Tina
When working with GraphQL, there are 2 reasons a property may not be present.
The data is not a required property. That is to say, if I have a blog post document, and "category" is an optional field, we'll need to make sure we factor that into how we render our page:
But with Tina, there's a 3rd scenario: the document may be in an invalid state. Meaning, we could mark the field as requiredand query for the appropriate field, and still not have the expected shape of data. Due to the contextual nature of Tina, it's very common to be in an intermediate state, where your data is incomplete simply because you're still working on it. Most APIs would throw an error when a document is in an invalid state. Or, more likely, you couldn't even request it.
Undefined list fields will return null
Previously an listable field which wasn't defined in the document was treated as an emptry array. So for example:
---
title: "Hello, World"
categories:
- sports
- movies
---
The responsee would be categories: ['sports', 'movies']. If you omit the items, but kept the empty array:
---
title: "Hello, World"
categories: []
---
The responsee would be categories: []. If you omit the field entirely:
---
title: "Hello, World"
---
The response will be categories: null. Previously this would have been [], which was incorrect.
For a listable item which is required: true you must provide a ui.defaultItem property
Why?
It's possible for Tina's editing capabilities to introduce an invalid state during edits to list items. Imagine the scenario where you are iterating through an array of objects, and each object has a categories array on it we'd like to render:
For a new item, categories will be null, so we'll get an error. This only happens when you're editing your page with Tina, so it's not a production-facing issue.
Every type can be a list
Previously, we had a list field, which allowed you to supply a field property. Instead, every primitive type can be represented as a list:
Note we may introduce an enum type, but haven't discussed it thoroughly
Introducing the object type
Tina currently represents the concept of an object in two ways: a group (and group-list), which is a uniform collection of fields; and blocks, which is a polymporphic collection. Moving forward, we'll be introducing a more comporehensive type, which envelopes the behavior of both group and blocks, and since every field can be a list, this also makes group-list redundant.
Note: we've previously assumed that blocks usage would always be as an array. We'll be keeping that assumption with the blocks type for compatibility, but object will allow for non-array polymorphic objects.
Defining an object type
An object type takes either a fieldsortemplates property (just like the collections definition). If you supply fields, you'll end up with what is essentially a group item. And if you say list: true, you'll have what used to be a group-list definition.
Likewise, if you supply a templates field and list: true, you'll get the same API as blocks. However you can also say list: false (or omit it entirely), and you'll have a polymorphic object which is not an array.
This is identical to the current blocks definition:
You can now request dataJSON for the entire data object as a single query key. This is great for more tedius queries like theme files where including each item in the result is cumbersome.
Note there is no typescript help for this feature for now
The GraphQL connection spec opens up a more future-proof structure, allowing us to put more information in to the connection itself like how many results have been returned, and how to request the next page of data.
Read a detailed explanation of how the connection spec provides a richer set of capabilities.
Note: sorting and filtering is still not supported for list queries.
_body is no longer included by default
There is instead an isBody boolean which can be added to any string field
Why?
Since markdown files sort of have an implicit "body" to them, we were automatically populating a field which represented the body of your markdown file. This wasn't that useful, and kind of annoying. Instead, just attach isBody to the field which you want to represent your markdown "body":
They now include the proper namespace to prevent naming collisions and no longer require _Doc_Data suffix. All generated __typename properties are going to be slightly different. We weren't fully namespacing fields so it wasn't possible to guarantee that no collisions would occur. The pain felt here will likely be most seen when querying and filtering through blocks. This ensures the stability of this type in the future
{
getPageDocument(relativePath: "home.md") {
data {
title
myBlocks {
...on Page_Hero_Data { # previously this would have been Hero_Data
# ...
}
}
}
}
This PR was opened by the Changesets release GitHub action. When you're ready to do a release, you can merge this and publish to npm yourself or setup this action to publish automatically. If you're not ready to do a release yet, that's fine, whenever you add more changesets to main, this PR will be updated.
Releases
next-tinacms-cloudinary@2.0.0
Minor Changes
Patch Changes
Updated dependencies [95244e14]
tina-graphql@0.2.0
Minor Changes
7351d92f: # Define schema changes
We're going to be leaning on a more primitive concept of how types are defined with Tina, and in doing so will be introducing some breaking changes to the way schemas are defined. Read the detailed RFC discussion for more on this topic, specifically the latter portions of the discussion.
Collections now accept a
fields
ortemplates
propertyYou can now provide
fields
instead oftemplates
for your collection, doing so will result in a more straightforward schema definition:Why?
Previously, a collection could define multiple templates, the ambiguity introduced with this feature meant that your documents needed a
_template
field on them so we'd know which one they belonged to. It also mean having to disambiguate your queries in graphql:Going forward, if you use
fields
on a collection, you can omit the_template
key and simplify your query:type
changesTypes will look a little bit different, and are meant to reflect the lowest form of the shape they can represent. Moving forward, the
ui
field will represent the UI portion of what you might expect. For a blog post "description" field, you'd define it like this:By default
string
will use thetext
field, but you can change that by specifying thecomponent
:For the most part, the UI properties are added to the field and adhere to the existing capabilities of Tina's core field plugins. But there's nothing stopping you from providing your own components -- just be sure to register those with the CMS object on the frontend:
Register your
myMapField
with Tina:One important gotcha
Every property in the
defineSchema
API must be serlializable. Meaning functions will not work. For example, there's no way to define avalidate
orparse
function at this level. However, you can either use the formify API to get access to the Tina form, or provide your own logic by specifying a plugin of your choice:And then when you register the plugin, provide your custom logic here:
Why?
The reality is that under the hood this has made no difference to the backend, so we're removing it as a point of friction. Instead,
type
is the true definition of the field's shape, whileui
can be used for customizing the look and behavior of the field's UI.Defensive coding in Tina
When working with GraphQL, there are 2 reasons a property may not be present.
But with Tina, there's a 3rd scenario: the document may be in an invalid state. Meaning, we could mark the field as
required
and query for the appropriate field, and still not have the expected shape of data. Due to the contextual nature of Tina, it's very common to be in an intermediate state, where your data is incomplete simply because you're still working on it. Most APIs would throw an error when a document is in an invalid state. Or, more likely, you couldn't even request it.Undefined list fields will return
null
Previously an listable field which wasn't defined in the document was treated as an emptry array. So for example:
The responsee would be
categories: ['sports', 'movies']
. If you omit the items, but kept the empty array:The responsee would be
categories: []
. If you omit the field entirely:The response will be
categories: null
. Previously this would have been[]
, which was incorrect.For a listable item which is
required: true
you must provide aui.defaultItem
propertyWhy?
It's possible for Tina's editing capabilities to introduce an invalid state during edits to list items. Imagine the scenario where you are iterating through an array of objects, and each object has a categories array on it we'd like to render:
For a new item,
categories
will be null, so we'll get an error. This only happens when you're editing your page with Tina, so it's not a production-facing issue.Every
type
can be a listPreviously, we had a
list
field, which allowed you to supply afield
property. Instead, every primitive type can be represented as a list:Additionally, enumerable lists and selects are inferred from the
options
property. The following example is represented by aselect
field:While this, is a
checkbox
fieldIntroducing the
object
typeTina currently represents the concept of an object in two ways: a
group
(andgroup-list
), which is a uniform collection of fields; andblocks
, which is a polymporphic collection. Moving forward, we'll be introducing a more comporehensive type, which envelopes the behavior of bothgroup
andblocks
, and since every field can be alist
, this also makesgroup-list
redundant.Defining an
object
typeAn
object
type takes either afields
ortemplates
property (just like thecollections
definition). If you supplyfields
, you'll end up with what is essentially agroup
item. And if you saylist: true
, you'll have what used to be agroup-list
definition.Likewise, if you supply a
templates
field andlist: true
, you'll get the same API asblocks
. However you can also saylist: false
(or omit it entirely), and you'll have a polymorphic object which is not an array.This is identical to the current
blocks
definition:And here is one for
group
:dataJSON
fieldYou can now request
dataJSON
for the entire data object as a single query key. This is great for more tedius queries like theme files where including each item in the result is cumbersome.Lists queries will now adhere to the GraphQL connection spec
Read the spec
Previously, lists would return a simple array of items:
Which would result in:
In the new API, you'll need to step through
edges
&nodes
:Why?
The GraphQL connection spec opens up a more future-proof structure, allowing us to put more information in to the connection itself like how many results have been returned, and how to request the next page of data.
Read a detailed explanation of how the connection spec provides a richer set of capabilities.
_body
is no longer included by defaultThere is instead an
isBody
boolean which can be added to anystring
fieldWhy?
Since markdown files sort of have an implicit "body" to them, we were automatically populating a field which represented the body of your markdown file. This wasn't that useful, and kind of annoying. Instead, just attach
isBody
to the field which you want to represent your markdown "body":This would result in a form field called
My Body
getting saved to the body of your markdown file (if you're using markdown):References now point to more than one collection.
Instead of a
collection
property, you must now define acollections
field, which is an array:Other breaking changes
The
template
field on polymorphic objects (formerly blocks) is now_template
Old API:
New API:
data
__typename
values have changedThey now include the proper namespace to prevent naming collisions and no longer require
_Doc_Data
suffix. All generated__typename
properties are going to be slightly different. We weren't fully namespacing fields so it wasn't possible to guarantee that no collisions would occur. The pain felt here will likely be most seen when querying and filtering through blocks. This ensures the stability of this type in the futurePatch Changes
Updated dependencies [7351d92f]
tina-graphql-gateway@0.4.0
Minor Changes
7351d92f: # Define schema changes
We're going to be leaning on a more primitive concept of how types are defined with Tina, and in doing so will be introducing some breaking changes to the way schemas are defined. Read the detailed RFC discussion for more on this topic, specifically the latter portions of the discussion.
Collections now accept a
fields
ortemplates
propertyYou can now provide
fields
instead oftemplates
for your collection, doing so will result in a more straightforward schema definition:Why?
Previously, a collection could define multiple templates, the ambiguity introduced with this feature meant that your documents needed a
_template
field on them so we'd know which one they belonged to. It also mean having to disambiguate your queries in graphql:Going forward, if you use
fields
on a collection, you can omit the_template
key and simplify your query:type
changesTypes will look a little bit different, and are meant to reflect the lowest form of the shape they can represent. Moving forward, the
ui
field will represent the UI portion of what you might expect. For a blog post "description" field, you'd define it like this:By default
string
will use thetext
field, but you can change that by specifying thecomponent
:For the most part, the UI properties are added to the field and adhere to the existing capabilities of Tina's core field plugins. But there's nothing stopping you from providing your own components -- just be sure to register those with the CMS object on the frontend:
Register your
myMapField
with Tina:One important gotcha
Every property in the
defineSchema
API must be serlializable. Meaning functions will not work. For example, there's no way to define avalidate
orparse
function at this level. However, you can either use the formify API to get access to the Tina form, or provide your own logic by specifying a plugin of your choice:And then when you register the plugin, provide your custom logic here:
Why?
The reality is that under the hood this has made no difference to the backend, so we're removing it as a point of friction. Instead,
type
is the true definition of the field's shape, whileui
can be used for customizing the look and behavior of the field's UI.Defensive coding in Tina
When working with GraphQL, there are 2 reasons a property may not be present.
But with Tina, there's a 3rd scenario: the document may be in an invalid state. Meaning, we could mark the field as
required
and query for the appropriate field, and still not have the expected shape of data. Due to the contextual nature of Tina, it's very common to be in an intermediate state, where your data is incomplete simply because you're still working on it. Most APIs would throw an error when a document is in an invalid state. Or, more likely, you couldn't even request it.Undefined list fields will return
null
Previously an listable field which wasn't defined in the document was treated as an emptry array. So for example:
The responsee would be
categories: ['sports', 'movies']
. If you omit the items, but kept the empty array:The responsee would be
categories: []
. If you omit the field entirely:The response will be
categories: null
. Previously this would have been[]
, which was incorrect.For a listable item which is
required: true
you must provide aui.defaultItem
propertyWhy?
It's possible for Tina's editing capabilities to introduce an invalid state during edits to list items. Imagine the scenario where you are iterating through an array of objects, and each object has a categories array on it we'd like to render:
For a new item,
categories
will be null, so we'll get an error. This only happens when you're editing your page with Tina, so it's not a production-facing issue.Every
type
can be a listPreviously, we had a
list
field, which allowed you to supply afield
property. Instead, every primitive type can be represented as a list:Additionally, enumerable lists and selects are inferred from the
options
property. The following example is represented by aselect
field:While this, is a
checkbox
fieldIntroducing the
object
typeTina currently represents the concept of an object in two ways: a
group
(andgroup-list
), which is a uniform collection of fields; andblocks
, which is a polymporphic collection. Moving forward, we'll be introducing a more comporehensive type, which envelopes the behavior of bothgroup
andblocks
, and since every field can be alist
, this also makesgroup-list
redundant.Defining an
object
typeAn
object
type takes either afields
ortemplates
property (just like thecollections
definition). If you supplyfields
, you'll end up with what is essentially agroup
item. And if you saylist: true
, you'll have what used to be agroup-list
definition.Likewise, if you supply a
templates
field andlist: true
, you'll get the same API asblocks
. However you can also saylist: false
(or omit it entirely), and you'll have a polymorphic object which is not an array.This is identical to the current
blocks
definition:And here is one for
group
:dataJSON
fieldYou can now request
dataJSON
for the entire data object as a single query key. This is great for more tedius queries like theme files where including each item in the result is cumbersome.Lists queries will now adhere to the GraphQL connection spec
Read the spec
Previously, lists would return a simple array of items:
Which would result in:
In the new API, you'll need to step through
edges
&nodes
:Why?
The GraphQL connection spec opens up a more future-proof structure, allowing us to put more information in to the connection itself like how many results have been returned, and how to request the next page of data.
Read a detailed explanation of how the connection spec provides a richer set of capabilities.
_body
is no longer included by defaultThere is instead an
isBody
boolean which can be added to anystring
fieldWhy?
Since markdown files sort of have an implicit "body" to them, we were automatically populating a field which represented the body of your markdown file. This wasn't that useful, and kind of annoying. Instead, just attach
isBody
to the field which you want to represent your markdown "body":This would result in a form field called
My Body
getting saved to the body of your markdown file (if you're using markdown):References now point to more than one collection.
Instead of a
collection
property, you must now define acollections
field, which is an array:Other breaking changes
The
template
field on polymorphic objects (formerly blocks) is now_template
Old API:
New API:
data
__typename
values have changedThey now include the proper namespace to prevent naming collisions and no longer require
_Doc_Data
suffix. All generated__typename
properties are going to be slightly different. We weren't fully namespacing fields so it wasn't possible to guarantee that no collisions would occur. The pain felt here will likely be most seen when querying and filtering through blocks. This ensures the stability of this type in the futurePatch Changes
Updated dependencies [7351d92f]
tina-graphql-gateway-cli@0.4.0
Minor Changes
7351d92f: # Define schema changes
We're going to be leaning on a more primitive concept of how types are defined with Tina, and in doing so will be introducing some breaking changes to the way schemas are defined. Read the detailed RFC discussion for more on this topic, specifically the latter portions of the discussion.
Collections now accept a
fields
ortemplates
propertyYou can now provide
fields
instead oftemplates
for your collection, doing so will result in a more straightforward schema definition:Why?
Previously, a collection could define multiple templates, the ambiguity introduced with this feature meant that your documents needed a
_template
field on them so we'd know which one they belonged to. It also mean having to disambiguate your queries in graphql:Going forward, if you use
fields
on a collection, you can omit the_template
key and simplify your query:type
changesTypes will look a little bit different, and are meant to reflect the lowest form of the shape they can represent. Moving forward, the
ui
field will represent the UI portion of what you might expect. For a blog post "description" field, you'd define it like this:By default
string
will use thetext
field, but you can change that by specifying thecomponent
:For the most part, the UI properties are added to the field and adhere to the existing capabilities of Tina's core field plugins. But there's nothing stopping you from providing your own components -- just be sure to register those with the CMS object on the frontend:
Register your
myMapField
with Tina:One important gotcha
Every property in the
defineSchema
API must be serlializable. Meaning functions will not work. For example, there's no way to define avalidate
orparse
function at this level. However, you can either use the formify API to get access to the Tina form, or provide your own logic by specifying a plugin of your choice:And then when you register the plugin, provide your custom logic here:
Why?
The reality is that under the hood this has made no difference to the backend, so we're removing it as a point of friction. Instead,
type
is the true definition of the field's shape, whileui
can be used for customizing the look and behavior of the field's UI.Defensive coding in Tina
When working with GraphQL, there are 2 reasons a property may not be present.
But with Tina, there's a 3rd scenario: the document may be in an invalid state. Meaning, we could mark the field as
required
and query for the appropriate field, and still not have the expected shape of data. Due to the contextual nature of Tina, it's very common to be in an intermediate state, where your data is incomplete simply because you're still working on it. Most APIs would throw an error when a document is in an invalid state. Or, more likely, you couldn't even request it.Undefined list fields will return
null
Previously an listable field which wasn't defined in the document was treated as an emptry array. So for example:
The responsee would be
categories: ['sports', 'movies']
. If you omit the items, but kept the empty array:The responsee would be
categories: []
. If you omit the field entirely:The response will be
categories: null
. Previously this would have been[]
, which was incorrect.For a listable item which is
required: true
you must provide aui.defaultItem
propertyWhy?
It's possible for Tina's editing capabilities to introduce an invalid state during edits to list items. Imagine the scenario where you are iterating through an array of objects, and each object has a categories array on it we'd like to render:
For a new item,
categories
will be null, so we'll get an error. This only happens when you're editing your page with Tina, so it's not a production-facing issue.Every
type
can be a listPreviously, we had a
list
field, which allowed you to supply afield
property. Instead, every primitive type can be represented as a list:Additionally, enumerable lists and selects are inferred from the
options
property. The following example is represented by aselect
field:While this, is a
checkbox
fieldIntroducing the
object
typeTina currently represents the concept of an object in two ways: a
group
(andgroup-list
), which is a uniform collection of fields; andblocks
, which is a polymporphic collection. Moving forward, we'll be introducing a more comporehensive type, which envelopes the behavior of bothgroup
andblocks
, and since every field can be alist
, this also makesgroup-list
redundant.Defining an
object
typeAn
object
type takes either afields
ortemplates
property (just like thecollections
definition). If you supplyfields
, you'll end up with what is essentially agroup
item. And if you saylist: true
, you'll have what used to be agroup-list
definition.Likewise, if you supply a
templates
field andlist: true
, you'll get the same API asblocks
. However you can also saylist: false
(or omit it entirely), and you'll have a polymorphic object which is not an array.This is identical to the current
blocks
definition:And here is one for
group
:dataJSON
fieldYou can now request
dataJSON
for the entire data object as a single query key. This is great for more tedius queries like theme files where including each item in the result is cumbersome.Lists queries will now adhere to the GraphQL connection spec
Read the spec
Previously, lists would return a simple array of items:
Which would result in:
In the new API, you'll need to step through
edges
&nodes
:Why?
The GraphQL connection spec opens up a more future-proof structure, allowing us to put more information in to the connection itself like how many results have been returned, and how to request the next page of data.
Read a detailed explanation of how the connection spec provides a richer set of capabilities.
_body
is no longer included by defaultThere is instead an
isBody
boolean which can be added to anystring
fieldWhy?
Since markdown files sort of have an implicit "body" to them, we were automatically populating a field which represented the body of your markdown file. This wasn't that useful, and kind of annoying. Instead, just attach
isBody
to the field which you want to represent your markdown "body":This would result in a form field called
My Body
getting saved to the body of your markdown file (if you're using markdown):References now point to more than one collection.
Instead of a
collection
property, you must now define acollections
field, which is an array:Other breaking changes
The
template
field on polymorphic objects (formerly blocks) is now_template
Old API:
New API:
data
__typename
values have changedThey now include the proper namespace to prevent naming collisions and no longer require
_Doc_Data
suffix. All generated__typename
properties are going to be slightly different. We weren't fully namespacing fields so it wasn't possible to guarantee that no collisions would occur. The pain felt here will likely be most seen when querying and filtering through blocks. This ensures the stability of this type in the future33e27538: Init command now adds admin.tsx file to the users pages folder
8c8fc2ad: Init script now checks for file extention.
Patch Changes
Updated dependencies [7351d92f]
tina-graphql-helpers@0.1.2
Patch Changes
7351d92f: # Define schema changes
We're going to be leaning on a more primitive concept of how types are defined with Tina, and in doing so will be introducing some breaking changes to the way schemas are defined. Read the detailed RFC discussion for more on this topic, specifically the latter portions of the discussion.
Collections now accept a
fields
ortemplates
propertyYou can now provide
fields
instead oftemplates
for your collection, doing so will result in a more straightforward schema definition:Why?
Previously, a collection could define multiple templates, the ambiguity introduced with this feature meant that your documents needed a
_template
field on them so we'd know which one they belonged to. It also mean having to disambiguate your queries in graphql:Going forward, if you use
fields
on a collection, you can omit the_template
key and simplify your query:type
changesTypes will look a little bit different, and are meant to reflect the lowest form of the shape they can represent. Moving forward, the
ui
field will represent the UI portion of what you might expect. For a blog post "description" field, you'd define it like this:By default
string
will use thetext
field, but you can change that by specifying thecomponent
:For the most part, the UI properties are added to the field and adhere to the existing capabilities of Tina's core field plugins. But there's nothing stopping you from providing your own components -- just be sure to register those with the CMS object on the frontend:
Register your
myMapField
with Tina:One important gotcha
Every property in the
defineSchema
API must be serlializable. Meaning functions will not work. For example, there's no way to define avalidate
orparse
function at this level. However, you can either use the formify API to get access to the Tina form, or provide your own logic by specifying a plugin of your choice:And then when you register the plugin, provide your custom logic here:
Why?
The reality is that under the hood this has made no difference to the backend, so we're removing it as a point of friction. Instead,
type
is the true definition of the field's shape, whileui
can be used for customizing the look and behavior of the field's UI.Defensive coding in Tina
When working with GraphQL, there are 2 reasons a property may not be present.
But with Tina, there's a 3rd scenario: the document may be in an invalid state. Meaning, we could mark the field as
required
and query for the appropriate field, and still not have the expected shape of data. Due to the contextual nature of Tina, it's very common to be in an intermediate state, where your data is incomplete simply because you're still working on it. Most APIs would throw an error when a document is in an invalid state. Or, more likely, you couldn't even request it.Undefined list fields will return
null
Previously an listable field which wasn't defined in the document was treated as an emptry array. So for example:
The responsee would be
categories: ['sports', 'movies']
. If you omit the items, but kept the empty array:The responsee would be
categories: []
. If you omit the field entirely:The response will be
categories: null
. Previously this would have been[]
, which was incorrect.For a listable item which is
required: true
you must provide aui.defaultItem
propertyWhy?
It's possible for Tina's editing capabilities to introduce an invalid state during edits to list items. Imagine the scenario where you are iterating through an array of objects, and each object has a categories array on it we'd like to render:
For a new item,
categories
will be null, so we'll get an error. This only happens when you're editing your page with Tina, so it's not a production-facing issue.Every
type
can be a listPreviously, we had a
list
field, which allowed you to supply afield
property. Instead, every primitive type can be represented as a list:Additionally, enumerable lists and selects are inferred from the
options
property. The following example is represented by aselect
field:While this, is a
checkbox
fieldIntroducing the
object
typeTina currently represents the concept of an object in two ways: a
group
(andgroup-list
), which is a uniform collection of fields; andblocks
, which is a polymporphic collection. Moving forward, we'll be introducing a more comporehensive type, which envelopes the behavior of bothgroup
andblocks
, and since every field can be alist
, this also makesgroup-list
redundant.Defining an
object
typeAn
object
type takes either afields
ortemplates
property (just like thecollections
definition). If you supplyfields
, you'll end up with what is essentially agroup
item. And if you saylist: true
, you'll have what used to be agroup-list
definition.Likewise, if you supply a
templates
field andlist: true
, you'll get the same API asblocks
. However you can also saylist: false
(or omit it entirely), and you'll have a polymorphic object which is not an array.This is identical to the current
blocks
definition:And here is one for
group
:dataJSON
fieldYou can now request
dataJSON
for the entire data object as a single query key. This is great for more tedius queries like theme files where including each item in the result is cumbersome.Lists queries will now adhere to the GraphQL connection spec
Read the spec
Previously, lists would return a simple array of items:
Which would result in:
In the new API, you'll need to step through
edges
&nodes
:Why?
The GraphQL connection spec opens up a more future-proof structure, allowing us to put more information in to the connection itself like how many results have been returned, and how to request the next page of data.
Read a detailed explanation of how the connection spec provides a richer set of capabilities.
_body
is no longer included by defaultThere is instead an
isBody
boolean which can be added to anystring
fieldWhy?
Since markdown files sort of have an implicit "body" to them, we were automatically populating a field which represented the body of your markdown file. This wasn't that useful, and kind of annoying. Instead, just attach
isBody
to the field which you want to represent your markdown "body":This would result in a form field called
My Body
getting saved to the body of your markdown file (if you're using markdown):References now point to more than one collection.
Instead of a
collection
property, you must now define acollections
field, which is an array:Other breaking changes
The
template
field on polymorphic objects (formerly blocks) is now_template
Old API:
New API:
data
__typename
values have changedThey now include the proper namespace to prevent naming collisions and no longer require
_Doc_Data
suffix. All generated__typename
properties are going to be slightly different. We weren't fully namespacing fields so it wasn't possible to guarantee that no collisions would occur. The pain felt here will likely be most seen when querying and filtering through blocks. This ensures the stability of this type in the futuretina-cloud-starter@0.2.0
Minor Changes
Patch Changes
Updated dependencies [95244e14]
demo@0.1.6
Patch Changes
Updated dependencies [95244e14]
test@0.1.6
Patch Changes
Updated dependencies [95244e14]
tina-cloud-starter-experimental@0.1.1
Patch Changes
7351d92f: # Define schema changes
We're going to be leaning on a more primitive concept of how types are defined with Tina, and in doing so will be introducing some breaking changes to the way schemas are defined. Read the detailed RFC discussion for more on this topic, specifically the latter portions of the discussion.
Collections now accept a
fields
ortemplates
propertyYou can now provide
fields
instead oftemplates
for your collection, doing so will result in a more straightforward schema definition:Why?
Previously, a collection could define multiple templates, the ambiguity introduced with this feature meant that your documents needed a
_template
field on them so we'd know which one they belonged to. It also mean having to disambiguate your queries in graphql:Going forward, if you use
fields
on a collection, you can omit the_template
key and simplify your query:type
changesTypes will look a little bit different, and are meant to reflect the lowest form of the shape they can represent. Moving forward, the
ui
field will represent the UI portion of what you might expect. For a blog post "description" field, you'd define it like this:By default
string
will use thetext
field, but you can change that by specifying thecomponent
:For the most part, the UI properties are added to the field and adhere to the existing capabilities of Tina's core field plugins. But there's nothing stopping you from providing your own components -- just be sure to register those with the CMS object on the frontend:
Register your
myMapField
with Tina:One important gotcha
Every property in the
defineSchema
API must be serlializable. Meaning functions will not work. For example, there's no way to define avalidate
orparse
function at this level. However, you can either use the formify API to get access to the Tina form, or provide your own logic by specifying a plugin of your choice:And then when you register the plugin, provide your custom logic here:
Why?
The reality is that under the hood this has made no difference to the backend, so we're removing it as a point of friction. Instead,
type
is the true definition of the field's shape, whileui
can be used for customizing the look and behavior of the field's UI.Defensive coding in Tina
When working with GraphQL, there are 2 reasons a property may not be present.
But with Tina, there's a 3rd scenario: the document may be in an invalid state. Meaning, we could mark the field as
required
and query for the appropriate field, and still not have the expected shape of data. Due to the contextual nature of Tina, it's very common to be in an intermediate state, where your data is incomplete simply because you're still working on it. Most APIs would throw an error when a document is in an invalid state. Or, more likely, you couldn't even request it.Undefined list fields will return
null
Previously an listable field which wasn't defined in the document was treated as an emptry array. So for example:
The responsee would be
categories: ['sports', 'movies']
. If you omit the items, but kept the empty array:The responsee would be
categories: []
. If you omit the field entirely:The response will be
categories: null
. Previously this would have been[]
, which was incorrect.For a listable item which is
required: true
you must provide aui.defaultItem
propertyWhy?
It's possible for Tina's editing capabilities to introduce an invalid state during edits to list items. Imagine the scenario where you are iterating through an array of objects, and each object has a categories array on it we'd like to render:
For a new item,
categories
will be null, so we'll get an error. This only happens when you're editing your page with Tina, so it's not a production-facing issue.Every
type
can be a listPreviously, we had a
list
field, which allowed you to supply afield
property. Instead, every primitive type can be represented as a list:Additionally, enumerable lists and selects are inferred from the
options
property. The following example is represented by aselect
field:While this, is a
checkbox
fieldIntroducing the
object
typeTina currently represents the concept of an object in two ways: a
group
(andgroup-list
), which is a uniform collection of fields; andblocks
, which is a polymporphic collection. Moving forward, we'll be introducing a more comporehensive type, which envelopes the behavior of bothgroup
andblocks
, and since every field can be alist
, this also makesgroup-list
redundant.Defining an
object
typeAn
object
type takes either afields
ortemplates
property (just like thecollections
definition). If you supplyfields
, you'll end up with what is essentially agroup
item. And if you saylist: true
, you'll have what used to be agroup-list
definition.Likewise, if you supply a
templates
field andlist: true
, you'll get the same API asblocks
. However you can also saylist: false
(or omit it entirely), and you'll have a polymorphic object which is not an array.This is identical to the current
blocks
definition:And here is one for
group
:dataJSON
fieldYou can now request
dataJSON
for the entire data object as a single query key. This is great for more tedius queries like theme files where including each item in the result is cumbersome.Lists queries will now adhere to the GraphQL connection spec
Read the spec
Previously, lists would return a simple array of items:
Which would result in:
In the new API, you'll need to step through
edges
&nodes
:Why?
The GraphQL connection spec opens up a more future-proof structure, allowing us to put more information in to the connection itself like how many results have been returned, and how to request the next page of data.
Read a detailed explanation of how the connection spec provides a richer set of capabilities.
_body
is no longer included by defaultThere is instead an
isBody
boolean which can be added to anystring
fieldWhy?
Since markdown files sort of have an implicit "body" to them, we were automatically populating a field which represented the body of your markdown file. This wasn't that useful, and kind of annoying. Instead, just attach
isBody
to the field which you want to represent your markdown "body":This would result in a form field called
My Body
getting saved to the body of your markdown file (if you're using markdown):References now point to more than one collection.
Instead of a
collection
property, you must now define acollections
field, which is an array:Other breaking changes
The
template
field on polymorphic objects (formerly blocks) is now_template
Old API:
New API:
data
__typename
values have changedThey now include the proper namespace to prevent naming collisions and no longer require
_Doc_Data
suffix. All generated__typename
properties are going to be slightly different. We weren't fully namespacing fields so it wasn't possible to guarantee that no collisions would occur. The pain felt here will likely be most seen when querying and filtering through blocks. This ensures the stability of this type in the futureUpdated dependencies [95244e14]
tina-tailwind-sidebar-demo@0.1.4
Patch Changes